3. back 개발환경 셋팅과 db설계

IntelliJ를 이용해서 pointRee폴더 내에 back폴더를 생성해주고 여기에 spring boot 2.4로 프로젝트를 시작했습니다.

dependencies {
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    //db
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'com.h2database:h2'
    implementation 'mysql:mysql-connector-java'

    //lombok
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

dependency는 위와 같이 추가해주었습니다.



db설계

포인트의 유효기간을 처음에 생각을 했었으나 db설계와 구현과정에 있어 많은 시간이 생각보다 소요될 것 같아 일단 유효기간이 없다고 생각하고 설계를 진행했습니다. 완성후 다른곳에 문제가 없다면 차차 추가할 생각입니다.

CREATE TABLE USER (
     id                 bigint NOT NULL AUTO_INCREMENT, --사용자 PK
     name               varchar(20) NOT NULL,           --사용자명
     email              varchar(50) NOT NULL,           --로그인 이메일
     passwd             varchar(80) NOT NULL,           --로그인 비밀번호
     phone_number       varchar(20) NOT NULL,           --전화번호
     accumulation_rate  int NOT NULL DEFAULT 5,         --포인트 적립율
     role               varchar(20) NOT NULL,
     created_time       datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
     PRIMARY KEY (id),
     CONSTRAINT unq_user_email UNIQUE (email)
);

CREATE TABLE CUSTOMER (
    id                  bigint NOT NULL AUTO_INCREMENT,     --고객 PK
    user_id             bigint NOT NULL,                   --user FK
    phone_number        varchar(20) NOT NULL,               --전화번호
    total_point         int NOT NULL default 0,                --총 포인트
    purchase_cnt        int NOT NULL default 0,               --구매 횟수
    created_time        datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
    PRIMARY KEY (id),
    CONSTRAINT fk_user_id FOREIGN KEY(user_id) REFERENCES USER (id) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE ORDERS (
    id                  bigint NOT NULL AUTO_INCREMENT,     --구매기록 PK
    customer_id         bigint NOT NULL,                   --customer FK
    price               int NOT NULL,                       --가격
    accumulation_rate   int NOT NULL,                       --적립율(기본은 유저적립율)
    save_point          int,                                --적립율과 가격에 따른 적립포인트
    payment_type        varchar(20) NOT NULL DEFAULT 'CASH',                --결제 방법
    created_time        datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
    PRIMARY KEY (id),
    CONSTRAINT fk_customer_id FOREIGN KEY(customer_id) REFERENCES CUSTOMER (id) ON DELETE CASCADE ON UPDATE CASCADE
);

기능은 많지 않다보니 table 3개로 모두 구현가능 할 것 같아 위와같이 설계를 해주었고 지금은 시작 초기데이터도 몇개 추가해 주었습니다.

--
INSERT INTO user(id,name, email, password, phone_number,accumulation_rate,role) VALUES (1,'tester', '[email protected]', '$2a$10$mzF7/rMylsnxxwNcTsJTEOFhh1iaHv3xVox.vpf6JQybEhE4jDZI.', '010-0123-1111', 5,'ADMIN');
INSERT INTO user(id,name, email, password, phone_number,accumulation_rate,role) VALUES (2,'raon', '[email protected]', '$2a$10$mzF7/rMylsnxxwNcTsJTEOFhh1iaHv3xVox.vpf6JQybEhE4jDZI.', '010-1234-1234', 10,'USER');
INSERT INTO customer(id,user_id, phone_number, total_point, purchase_cnt,created_time) VALUES (1,1,'010-1111-1111', 3700, 3,'2021-04-10 20:41:10');
INSERT INTO customer(id,user_id, phone_number, total_point, purchase_cnt,created_time) VALUES (2,1,'010-2222-2222', 600, 2,'2021-04-10 20:41:10');
INSERT INTO customer(id,user_id, phone_number, total_point, purchase_cnt,created_time) VALUES (3,2,'010-4444-4444', 5000, 1,'2021-04-10 20:41:10');
INSERT INTO orders(price,save_point, accumulation_rate, payment_type,customer_id,created_time) values (12000, 600, 5, 'CASH', 1,'2021-04-10 20:41:10');
INSERT INTO orders(price,save_point, accumulation_rate,payment_type,customer_id,created_time) values (20000,1000,5, 'CASH', 1,'2021-04-12 20:41:10');
INSERT INTO orders(price,save_point, accumulation_rate,payment_type,customer_id,created_time) values (21000,2100,10, 'CARD', 1,'2021-04-13 20:41:10');
INSERT INTO orders(price,save_point, accumulation_rate,payment_type,customer_id,created_time) values (12000, 600, 5, 'CASH', 2,'2021-04-14 20:41:10');
INSERT INTO orders(price,save_point, accumulation_rate,payment_type,customer_id,created_time) values (100000, 5000, 5, 'CARD', 3, '2021-04-16 20:41:10');



application.yml 설정

spring:
  application:
    name: pointree
  jpa:
    hibernate:
      ddl-auto: create-drop
    properties:
      hibernate:
        format_sql: true
        jdbc:
          lob:
            non_contextual_createion: true
      hikari:
        minimum-idle: 1
        maximum-pool-size: 5
    show-sql: true
  datasource:
    initialization-mode: always

#Server
server:
  port: 8999
  http2:
    enabled: true
  servlet:
    encoding:
      charset: UTF-8
      enabled: true
      force: true

#Logging
logging:
  level:
    org:
      hibernate:
        springframework:
          security: DEBUG
        type:
          descrptor:
            sql:
              BasicBinder: TRACE

우선은 개발단계이기 때문에 db생성규칙은 create-drop으로 해주었고 port, hibernate logging등 을 설정해 주었고 github에 올릴예정으로 db정보는 아래와 같이 별도의 jdbc.yml을 작성해서 .gitignore에 추가해주었습니다.

spring:
  datasource:
    url: 'jdbc:mysql://127.0.0.1:3306/pointree?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&characterEncoding=UTF-8&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false'
    username: pointree
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    database-platform: org.hibernate.dialect.MySQL8Dialect


그리고 test는 좀더 빠른 실행을 위해 임베디드 db로 설정을 해주었습니다.

spring:
  datasource:
    username: sa
    password:
    url: 'jdbc:h2:mem:pointree;MODE=MYSQL;DB_CLOSE_DELAY=-1'
    driver-class-name: org.h2.Driver
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
  h2:
    console:
      enabled: true



jdbc.yml설정 적용해 실행해보기

@SpringBootApplication
public class PointreeApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(PointreeApplication.class)
                .properties(
                        "spring.config.location=" +
                        "classpath:/application.yml,"+
                        "classpath:/jdbc.yml").run(args);
    }
}

IntelliJ의 실행 환경변수로 추가해줄 수도 있지만, terminal로 실행시킬때 매번 해주기 귀찮아 main함수에 위와 같이 config 경로를 설정해주고 실행을 했습니다.

그러면 실행터미널에 우리가 앞에 생성해주었던 schema대로 table이 만들어지고 data가 만들어지는 것을 볼 수 있습니다.