From a5c6ed22c3f7d073d5078108f5a900ab578da8f6 Mon Sep 17 00:00:00 2001 From: "Choi, Minwoo" Date: Tue, 26 Aug 2025 20:24:56 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20Flyway=20=EC=84=A4=EC=A0=95=EC=9D=84?= =?UTF-8?q?=20=ED=86=B5=ED=95=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=B2=A0?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=8A=A4=ED=82=A4=EB=A7=88=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=A0=81=EC=9A=A9(#66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: local, dev, test 환경 설정에서 ddl-auto: none으로 변경 * chore: prod, dev, test 환경 설정에서 open-in-view: false 추가 * chore: build.gradle에 Flyway 의존성 추가 * chore: Flyway 환경별 프로필(prod/dev/local/test) 설정 추가 * chore: applicaion.yml에 sql.init.mode: never 추가 * chore: V1__create_tables.sql 추가 --- build.gradle | 7 +- src/main/resources/application-dev.yml | 10 +- src/main/resources/application-local.yml | 12 +- src/main/resources/application-prod.yml | 10 +- src/main/resources/application.yml | 4 + .../db/migration/V1__create_tables.sql | 201 ++++++++++++++++++ src/test/resources/application-test.yml | 10 +- 7 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/db/migration/V1__create_tables.sql diff --git a/build.gradle b/build.gradle index 2acb55c..a0ae3b5 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ plugins { id 'org.springframework.boot' version '3.5.0' id 'io.spring.dependency-management' version '1.1.7' id 'com.diffplug.spotless' version '6.21.0' + id 'org.flywaydb.flyway' version '11.11.2' } group = 'com.ject' @@ -32,7 +33,6 @@ dependencies { implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0") compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' // Validation implementation 'org.springframework.boot:spring-boot-starter-validation' @@ -54,6 +54,11 @@ dependencies { // Redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // Flyway (MySQL) + implementation "org.flywaydb:flyway-core" + implementation 'org.flywaydb:flyway-mysql' + runtimeOnly 'com.mysql:mysql-connector-j' + // Firebase-admin implementation 'com.google.firebase:firebase-admin:9.2.0' diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index ab39ea0..72553e9 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -5,7 +5,15 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: none # 스키마 변경 책임은 전부 Flyway로. Hibernate는 생성/수정 금지 + open-in-view: false + + flyway: + enabled: true # Flyway 켜기 + locations: classpath:db/migration # 마이그레이션 SQL 파일 위치(V1, V2, V3 등 여기서 읽음) + validate-on-migrate: true # 마이그레이션 전체 검증 + fail-on-missing-locations: true # 경로 누락 시 실패 + clean-disabled: true # Flyway Clean(스키마 삭제) 금지 logging: level: diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index f4679f7..388a36d 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -5,14 +5,20 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: none # 스키마 변경 책임은 전부 Flyway로. Hibernate는 생성/수정 금지 show-sql: true + open-in-view: false properties: hibernate: format_sql: true dialect: org.hibernate.dialect.MySQL8Dialect - defer-datasource-initialization: true - open-in-view: false + + flyway: + enabled: true # Flyway 켜기 + locations: classpath:db/migration # 마이그레이션 SQL 파일 위치(V1, V2, V3 등 여기서 읽음) + validate-on-migrate: true # 마이그레이션 전체 검증 + fail-on-missing-locations: true # 경로 누락 시 실패 + clean-disabled: false logging: level: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 940b53c..32a60c7 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -5,4 +5,12 @@ spring: jpa: hibernate: - ddl-auto: none + ddl-auto: none # 스키마 변경 책임은 전부 Flyway로. Hibernate는 생성/수정 금지 + open-in-view: false + + flyway: + enabled: true # Flyway 켜기 + locations: classpath:db/migration # 마이그레이션 SQL 파일 위치(V1, V2, V3 등 여기서 읽음) + validate-on-migrate: true # 마이그레이션 전체 검증 + fail-on-missing-locations: true # 경로 누락 시 실패 + clean-disabled: true # Flyway Clean(스키마 삭제) 금지 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 339ca79..e253547 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,6 +5,10 @@ spring: - redis - security + sql: + init: + mode: never + server: forward-headers-strategy: framework diff --git a/src/main/resources/db/migration/V1__create_tables.sql b/src/main/resources/db/migration/V1__create_tables.sql new file mode 100644 index 0000000..0147971 --- /dev/null +++ b/src/main/resources/db/migration/V1__create_tables.sql @@ -0,0 +1,201 @@ +CREATE TABLE member ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + social_provider ENUM('KAKAO','GOOGLE') NOT NULL, + social_id VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL UNIQUE, + nickname VARCHAR(50) NOT NULL, + profile_image VARCHAR(512) NULL, + category ENUM('STUDENT','WORKER','FREELANCER','JOBSEEKER') NOT NULL, + role ENUM('ROLE_USER','ROLE_ADMIN','ROLE_OWNER') NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL +); + +CREATE TABLE trip ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + name VARCHAR(255) NOT NULL, + memo VARCHAR(255) NULL, + start_date DATE NOT NULL, + end_date DATE NULL, + total_stamps INT NULL, + completed_stamps INT NULL, + completed BOOLEAN NOT NULL, + category ENUM('COURSE', 'EXPLORE') NOT NULL, + + -- 외래키 필드 + member_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건: trip.member_id → member.id + FOREIGN KEY (member_id) REFERENCES member (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE stamp ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + name VARCHAR(255) NOT NULL, + stamp_order INT NULL, + completed BOOLEAN NOT NULL, + + -- 외래키 필드 + trip_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건: stamp.trip_id → trip.id + FOREIGN KEY (trip_id) REFERENCES trip (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE mission ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + name VARCHAR(255) NOT NULL, + completed BOOLEAN NOT NULL, + + -- 외래키 필드 + stamp_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건: mission.stamp_id → stamp.id + FOREIGN KEY (stamp_id) REFERENCES stamp (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE daily_goal ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + title VARCHAR(255) NOT NULL, + completed BOOLEAN NOT NULL, + + -- 외래키 필드 + trip_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건: stamp.trip_id → trip.id + FOREIGN KEY (trip_id) REFERENCES trip (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE study_log ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + title VARCHAR(255) NOT NULL, + content VARCHAR(255) NOT NULL, + + -- 외래키 필드 + member_id BIGINT NOT NULL, + daily_goal_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건 + FOREIGN KEY (member_id) REFERENCES member (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT, + + FOREIGN KEY (daily_goal_id) REFERENCES daily_goal (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE daily_mission ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 외래키 필드 + mission_id BIGINT NOT NULL, + daily_goal_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건 + FOREIGN KEY (mission_id) REFERENCES mission (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT, + + FOREIGN KEY (daily_goal_id) REFERENCES daily_goal (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE study_log_daily_mission ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 외래키 필드 + study_log_id BIGINT NOT NULL, + daily_mission_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건 + FOREIGN KEY (study_log_id) REFERENCES study_log (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT, + + FOREIGN KEY (daily_mission_id) REFERENCES daily_mission (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); + +CREATE TABLE pomodoro ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + + -- 도메인 필드 + focus_duration_in_seconds INT NULL, + focus_session_count INT NULL, + break_duration_in_seconds INT NULL, + total_focus_time_in_seconds INT NULL, + + -- 외래키 필드 + daily_goal_id BIGINT NOT NULL, + + -- Auditing + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + deleted_at DATETIME(6) NULL, + + -- 외래키 제약조건 + FOREIGN KEY (daily_goal_id) REFERENCES daily_goal (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT +); diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 85d0292..acd769a 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -5,9 +5,17 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: none # 스키마 변경 책임은 전부 Flyway로. Hibernate는 생성/수정 금지 show-sql: true + open-in-view: false properties: hibernate: format_sql: true dialect: org.hibernate.dialect.MySQL8Dialect + + flyway: + enabled: true # Flyway 켜기 + locations: classpath:db/migration # 마이그레이션 SQL 파일 위치(V1, V2, V3 등 여기서 읽음) + validate-on-migrate: true # 마이그레이션 전체 검증 + fail-on-missing-locations: true # 경로 누락 시 실패 + clean-disabled: false