devgrr

backend

Flyway 도입 가이드: 이미 돌아가는 DB에 버전 관리를 얹는 법

애플리케이션 코드는 git으로 관리하면서 DB 스키마는 아직도 누군가 콘솔에서 ALTER TABLE을 칩니다. Flyway는 그 SQL을 파일로 만들고, 순서대로 한 번씩만 실행하고, 무엇을 실행했는지 DB 안에 적어 둡니다. 빈 DB가 아니라 이미 운영 중인 DB에 도입하는 경우까지 다룹니다.

V1, V2, V3 마이그레이션 파일이 한 줄의 타임라인 위에 순서대로 놓이고, 그 끝이 flyway_schema_history 테이블로 이어지는 그림

DB 스키마도 코드입니다

새 기능을 만들면서 컬럼 하나를 추가한다고 해 봅시다. 로컬 DB에서 ALTER TABLE users ADD COLUMN phone VARCHAR(20)을 실행하고, 코드를 짜고, PR을 올립니다. 리뷰가 끝나고 배포합니다. 그리고 운영 서버가 Unknown column 'phone'으로 죽습니다.

누군가 스테이징과 운영 DB에도 같은 SQL을 쳐야 했는데, 그 사실이 코드 어디에도 적혀 있지 않았기 때문입니다. 이 문제는 팀이 커질수록 다음 형태로 나타납니다.

  • 환경마다 스키마가 다릅니다. 로컬, 개발, 스테이징, 운영이 조금씩 어긋나고, 어디가 어떻게 다른지 아무도 모릅니다.
  • 신규 입사자가 DB를 못 만듭니다. 최신 스키마를 만들려면 선배에게 덤프 파일을 받아야 합니다. 그 덤프가 언제 것인지는 아무도 모릅니다.
  • 배포 순서가 사람 머릿속에 있습니다. "이번 배포는 SQL 먼저 치고 앱 올리세요"가 슬랙 메시지로 전달됩니다. 새벽 배포에서 이 메시지는 잊힙니다.

코드에는 이런 문제가 없습니다. git이 변경 이력을 순서대로 갖고 있고, 어떤 커밋이 배포되었는지 알 수 있고, 새 사람은 clone 한 번으로 최신 상태를 받습니다. Flyway는 이것을 DB 스키마에 그대로 적용하는 도구입니다.

ddl-auto: update는 답이 아닙니다

Spring Boot를 쓴다면 spring.jpa.hibernate.ddl-auto: update가 떠오를 수 있습니다. 엔티티 클래스를 고치면 Hibernate가 알아서 테이블을 바꿔 주니 편합니다. 하지만 운영 환경에서는 쓰면 안 됩니다.

  • 컬럼을 추가할 뿐, 이름을 바꾸거나 지우는 변경은 반영하지 않습니다. 스키마에 쓰레기가 쌓입니다.
  • 어떤 DDL이 실행될지 배포 전에 알 수 없습니다. 리뷰할 대상이 없습니다.
  • 인덱스, 제약 조건, 데이터 이관 같은 실제로 중요한 변경을 표현할 수 없습니다.

Flyway를 도입하면 이 값은 validate로 바뀝니다. Hibernate는 스키마를 고치는 대신, 엔티티와 실제 테이블이 맞는지만 검사하고 어긋나면 애플리케이션을 띄우지 않습니다. 스키마를 바꾸는 권한은 Flyway 한 곳으로 모입니다.

Flyway가 하는 일

Flyway는 Redgate가 관리하는 DB 마이그레이션 도구입니다. 하는 일은 한 문장으로 요약됩니다.

버전이 붙은 SQL 파일을 버전 순서대로 한 번씩만 실행하고, 무엇을 실행했는지 DB 안의 테이블에 기록합니다.

핵심은 마지막 절반입니다. 기록이 DB 안에 있기 때문에, Flyway는 어떤 환경에 붙어도 "이 DB는 지금 몇 번까지 적용되었는가"를 스스로 알아냅니다. 사람의 기억이나 슬랙 메시지가 필요 없습니다.

db/migration/                     운영 DB
├── V1__create_users.sql          ┌──────────────────────┐
├── V2__add_phone.sql      ───►   │ 지금 V2까지 적용됨   │
├── V3__create_orders.sql         │ → V3, V4만 실행하면  │
└── V4__add_index.sql             │   된다               │
                                  └──────────────────────┘

flyway_schema_history 테이블

그 기록이 저장되는 곳이 flyway_schema_history 테이블입니다. Flyway가 처음 실행될 때 스스로 만듭니다. 컬럼은 다음과 같습니다.

컬럼의미
installed_rank적용된 순서. 1부터 증가합니다.
version마이그레이션 버전. 반복 실행 마이그레이션은 NULL입니다.
description파일 이름에서 뽑아낸 설명.
typeSQL, JDBC, BASELINE 등.
script실제 파일 이름.
checksum파일 내용의 체크섬. 파일이 바뀌었는지 판별하는 근거입니다.
installed_by실행한 DB 계정.
installed_on실행 시각.
execution_time실행에 걸린 시간(ms). 느린 마이그레이션을 찾을 때 씁니다.
success성공 여부.

운영 중 문제가 생기면 이 테이블부터 봅니다. 평범한 테이블이라 그냥 조회하면 됩니다.

SELECT installed_rank, version, description,
       success, execution_time, installed_on
FROM flyway_schema_history
ORDER BY installed_rank DESC
LIMIT 10;

마이그레이션 파일 규칙

Flyway는 파일 이름으로 모든 것을 판단합니다. 규칙은 접두사 + 버전 + 구분자 + 설명 + 확장자입니다.

V2__add_phone_to_users.sql
│ │  │                   └── 확장자 (.sql)
│ │  └── 설명 (밑줄은 공백으로 표시됨)
│ └── 구분자 (밑줄 두 개, __)
└── 접두사 + 버전

접두사는 세 종류입니다.

접두사이름언제 실행되나예시
VVersioned버전 순서대로 딱 한 번V3__create_orders.sql
RRepeatable내용이 바뀔 때마다, 버전 마이그레이션 이후에R__user_summary_view.sql
UUndo같은 버전을 되돌릴 때 (Enterprise 전용)U3__create_orders.sql

실무에서 V와 R만 씁니다. U는 유료 에디션 기능인데, 뒤에서 설명하겠지만 유료라서 안 쓰는 것이 아니라 애초에 롤백 전략으로 권하기 어렵습니다.

Repeatable은 언제 쓰나

R은 몇 번을 실행해도 결과가 같은 것에만 씁니다. 뷰, 저장 프로시저, 함수 같은 것들입니다. 이런 대상은 CREATE OR REPLACE로 다시 만들면 그만이라, 변경할 때마다 새 버전 파일을 만들 필요가 없습니다. 파일 하나를 계속 고치면 되고 git diff에 변경 내역이 그대로 남습니다.

CREATE OR REPLACE VIEW active_user_view AS
SELECT u.id, u.email, u.phone, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.deleted_at IS NULL
GROUP BY u.id, u.email, u.phone;

반대로 ALTER TABLE이나 INSERT는 절대 R에 넣으면 안 됩니다. 두 번 실행되면 깨지거나 데이터가 중복됩니다.

버전 번호는 어떻게 매기나

두 가지 방식이 있고, 팀 규모가 갈림길입니다.

  • 순차 번호(V1, V2, V3): 읽기 쉽고 순서가 명확합니다. 대신 두 사람이 동시에 V5를 만들면 merge 시점에 충돌합니다.
  • 타임스탬프(V20260903_1430): 충돌이 사실상 없습니다. 대신 파일 이름이 길고 순서를 눈으로 훑기 어렵습니다.

사람이 서너 명이면 순차 번호로 시작해도 충분합니다. 충돌이 실제로 귀찮아지는 시점에 타임스탬프로 바꾸면 됩니다. 이미 적용된 파일은 그대로 두고 새 파일부터 새 규칙을 쓰면 되므로, 나중에 바꿔도 비용이 크지 않습니다.

Spring Boot에 붙이기

의존성 두 줄과 설정 몇 줄이면 됩니다. Flyway 10부터 DB별 지원이 별도 모듈로 분리되었으므로, flyway-core만 넣으면 PostgreSQL이나 MySQL에서 동작하지 않습니다. 여기서 막히는 사람이 많습니다.

dependencies {
    implementation("org.flywaydb:flyway-core")

    // PostgreSQL을 쓴다면
    implementation("org.flywaydb:flyway-database-postgresql")

    // MySQL / MariaDB를 쓴다면
    // implementation("org.flywaydb:flyway-mysql")
}

Spring Boot의 의존성 관리가 버전을 맞춰 주므로 버전은 적지 않습니다. Maven이라면 같은 두 아티팩트를 <dependency>로 추가하면 됩니다.

spring:
  flyway:
    enabled: true
    locations: classpath:db/migration
    baseline-on-migrate: false
    validate-on-migrate: true
    out-of-order: false
  jpa:
    hibernate:
      ddl-auto: validate

각 값의 의미는 다음과 같습니다.

  • locations: 마이그레이션 파일을 찾을 경로입니다. 기본값이 classpath:db/migration이라 사실 생략해도 됩니다. 다만 이 값을 지정하면 기본값을 덮어씁니다. 테스트용 경로를 추가하려면 classpath:db/migration도 같이 적어야 합니다.
  • validate-on-migrate: 실행 전에 적용된 마이그레이션과 현재 파일이 일치하는지 검사합니다. 기본값이 true이고, 끄지 마세요. 이것이 꺼져 있으면 파일이 몰래 바뀐 것을 알 방법이 없습니다.
  • out-of-order: V5가 이미 적용된 DB에 뒤늦게 V4가 들어왔을 때 실행할지 여부입니다. 기본값 false를 유지하세요. 순서를 건너뛴 스키마는 환경마다 결과가 달라집니다.

디렉토리는 이렇게 만듭니다.

src/main/resources/
└── db/
    └── migration/
        ├── V1__create_users.sql
        ├── V2__add_phone_to_users.sql
        ├── V3__create_orders.sql
        └── R__active_user_view.sql

이제 애플리케이션을 띄우면 Flyway가 시작 시점에 자동으로 실행됩니다. 로그에 적용된 마이그레이션이 찍힙니다.

Flyway Community Edition 13.4.0 by Redgate
Database: jdbc:postgresql://localhost:5432/app (PostgreSQL 16.4)
Successfully validated 4 migrations (execution time 00:00.031s)
Creating Schema History table "public"."flyway_schema_history" ...
Migrating schema "public" to version "1 - create users"
Migrating schema "public" to version "2 - add phone to users"
Migrating schema "public" to version "3 - create orders"
Successfully applied 3 migrations (execution time 00:00.194s)

이미 운영 중인 DB에 도입하기

여기가 실제로 어려운 부분입니다. 지금까지의 설명은 빈 DB를 전제로 했습니다. 하지만 여러분이 Flyway를 도입하려는 이유는 이미 몇 년째 돌아가는 DB가 있고, 그 스키마를 아무도 통제하지 못하기 때문일 것입니다.

이 DB에 그냥 Flyway를 붙이면 V1__create_users.sql이 실행되면서 table already exists로 실패합니다. 필요한 것은 baseline입니다. "여기까지는 이미 되어 있는 것으로 친다"는 선언입니다.

1단계. 현재 스키마를 파일로 뽑는다

운영 DB의 현재 스키마를 데이터 없이 덤프합니다.

# PostgreSQL
pg_dump --schema-only --no-owner --no-privileges \
  -h prod-db -U app_user app_db > baseline.sql

# MySQL
mysqldump --no-data --skip-add-drop-table \
  -h prod-db -u app_user -p app_db > baseline.sql

덤프 파일을 열어 정리합니다. SET 구문, 소유자 지정, 주석 등 재현에 필요 없는 것들을 지웁니다. 그리고 이 파일을 V1__baseline.sql이라는 이름으로 db/migration에 넣습니다.

2단계. 빈 DB에서 검증한다

이 파일이 정말로 운영과 같은 스키마를 만드는지 확인해야 합니다. 로컬의 빈 DB에 V1__baseline.sql만으로 스키마를 만들고, 애플리케이션을 ddl-auto: validate로 띄웁니다. 뜬다면 엔티티 기준으로는 일치한다는 뜻입니다.

더 확실하게 하려면 두 스키마를 덤프해서 diff로 비교합니다.

pg_dump --schema-only --no-owner -h localhost app_db \
  | grep -v '^--' > local.sql
diff local.sql baseline.sql

3단계. 운영 DB에 baseline을 찍는다

이제 운영 DB에 "V1은 이미 적용된 것으로 간주하라"고 알려 줍니다. 두 가지 방법이 있습니다.

spring:
  flyway:
    baseline-on-migrate: true
    baseline-version: 1
    baseline-description: "existing schema"

baseline-on-migrate: true는 flyway_schema_history 테이블이 없을 때만 동작합니다. 테이블이 없으면 테이블을 만들고, baseline-version까지를 적용된 것으로 기록한 뒤, 그 다음 버전부터 실행합니다.

CLI를 쓴다면 명시적으로 한 번만 실행하는 쪽이 더 안전합니다.

flyway -baselineVersion="1" \
       -baselineDescription="existing schema" \
       baseline

4단계. 확인한다

flyway info는 상태를 표로 보여 줍니다. 도입 직후에는 이런 모습이어야 합니다.

+-----------+---------+-----------------+----------+------------+----------+
| Category  | Version | Description     | Type     | Installed  | State    |
+-----------+---------+-----------------+----------+------------+----------+
|           | 1       | existing schema | BASELINE | 2026-09-03 | Baseline |
| Versioned | 2       | add phone       | SQL      |            | Pending  |
| Versioned | 3       | create orders   | SQL      |            | Pending  |
+-----------+---------+-----------------+----------+------------+----------+

V1이 Baseline이고 그 뒤가 Pending이면 성공입니다. V1이 Pending으로 남아 있다면 baseline이 안 찍힌 것이니, 그 상태로 배포하면 안 됩니다.

팀에서 지킬 규칙 네 가지

도구를 붙이는 것보다 규칙을 합의하는 쪽이 어렵습니다. 최소한 이 네 가지는 도입 시점에 정해 두세요.

1. 적용된 마이그레이션 파일은 절대 수정하지 않는다

Flyway는 파일 내용의 체크섬을 flyway_schema_history에 저장합니다. 이미 적용된 파일을 고치면 다음 실행에서 검증에 걸립니다.

Migration checksum mismatch for migration version 3
-> Applied to database : 1284725619
-> Resolved locally    : -905442731
Either revert the changes to the migration, or run repair
to update the schema history.

이것은 버그가 아니라 Flyway가 제대로 일하고 있다는 신호입니다. "내 로컬에서는 아직 안 돌았으니까 그냥 고쳐도 되겠지"가 사고의 시작입니다. 여러분의 로컬에서는 안 돌았어도 동료의 로컬과 개발 서버에서는 이미 돌았습니다. 오타 하나를 고치더라도 새 파일을 만드세요.

예외는 딱 하나, 아직 어디에도 배포되지 않은 브랜치 안의 파일입니다. 이때는 로컬 DB를 지우고 다시 만들면 됩니다.

2. 롤백은 undo가 아니라 다음 마이그레이션으로 한다

Flyway의 U 접두사 undo 마이그레이션은 Enterprise 에디션 기능입니다. 하지만 유료가 아니더라도 실무에서 권하기 어렵습니다. DROP COLUMN을 되돌리는 undo 스크립트는 컬럼을 다시 만들 수는 있어도 거기 있던 데이터를 되살릴 수는 없기 때문입니다.

현실적인 전략은 앞으로 고치는 것입니다. V7이 잘못됐다면 V7을 되돌리는 대신 V8__fix_v7.sql을 만듭니다. 그리고 애초에 되돌릴 일이 없도록, 파괴적인 변경은 여러 배포에 나눠서 합니다.

컬럼 이름을 바꾸고 싶을 때 (한 번에 하면 배포 중 장애)

배포 1: 새 컬럼 추가            V10__add_new_column.sql
배포 2: 양쪽에 모두 쓰는 코드   (앱 배포만)
배포 3: 데이터 복사            V11__backfill_new_column.sql
배포 4: 새 컬럼만 읽는 코드     (앱 배포만)
배포 5: 옛 컬럼 삭제            V12__drop_old_column.sql

귀찮아 보이지만, 각 단계에서 앱의 옛 버전과 새 버전이 동시에 떠 있어도 안전합니다. 무중단 배포를 한다면 이 순서가 필수입니다.

3. 버전 충돌은 merge 전에 해결한다

두 브랜치가 각각 V8을 만들었다면, 나중에 merge하는 쪽이 자기 파일을 V9로 이름을 바꿉니다. git은 파일 이름이 다르므로 충돌을 알려 주지 않습니다. 사람이 봐야 합니다.

PR 체크리스트에 "새 마이그레이션 파일의 버전이 main과 겹치지 않는가"를 넣거나, CI에서 중복 버전을 검사하는 스크립트를 한 줄 돌리세요.

ls src/main/resources/db/migration/V*.sql \
  | sed 's#.*/V\([0-9]*\)__.*#\1#' | sort | uniq -d

출력이 있으면 중복된 버전이 있다는 뜻이니 CI를 실패시킵니다.

4. 마이그레이션도 코드 리뷰 대상이다

SQL 파일은 리뷰에서 자주 그냥 넘어갑니다. 하지만 앱 코드는 버그가 나면 롤백하면 되고, 마이그레이션은 롤백이 안 됩니다. 리뷰에서 최소한 이 세 가지는 봅니다.

  • 이 ALTER TABLE이 테이블을 잠그는가. 몇 만 행이면 순식간이지만, 수천만 행이면 몇 분에서 몇 시간 동안 쓰기가 막힙니다.
  • 지우는 것이 있는가. DROP과 NOT NULL 추가는 되돌릴 수 없습니다.
  • INSERT에 컬럼 이름이 명시되어 있는가. INSERT INTO t VALUES (...)는 나중에 컬럼이 추가되면 깨집니다.

알아 둘 명령어

Spring Boot에 붙이면 대부분 자동으로 돌지만, 문제가 생겼을 때는 CLI나 Gradle 플러그인으로 직접 쓰게 됩니다.

명령어하는 일언제 쓰나
info각 마이그레이션의 상태를 표로 출력가장 먼저 치는 명령어. 상태 파악
migrate대기 중인 마이그레이션 실행배포. 보통 앱 시작 시 자동
validate파일과 기록이 일치하는지 검사CI에서 배포 전 검증
baseline기존 DB에 시작점 기록도입 시점에 한 번
repair체크섬 재정렬, 실패 기록 제거사고 수습. 남용 금지
clean스키마의 모든 객체 삭제로컬 초기화 전용

clean은 스키마의 테이블, 뷰, 함수를 전부 지웁니다. 운영 DB에서 실행하면 그날로 끝입니다. 최근 버전의 Flyway는 이 명령을 기본으로 막아 두었고(cleanDisabled 기본값 true), 쓰려면 명시적으로 풀어야 합니다. 운영 설정에서는 절대 풀지 마세요. 로컬 초기화가 필요하면 차라리 DB 컨테이너를 지우고 다시 띄우는 편이 안전합니다.

실전에서 밟는 함정

MySQL에는 DDL 트랜잭션이 없습니다

PostgreSQL은 대부분의 DDL을 트랜잭션 안에서 처리합니다. 마이그레이션이 중간에 실패하면 그 파일의 변경이 통째로 롤백됩니다.

MySQL과 Oracle은 그렇지 않습니다. DDL 하나하나가 암묵적으로 커밋됩니다. 한 파일 안에 ALTER TABLE이 세 개 있고 두 번째에서 실패하면, 첫 번째는 적용된 채 남고 flyway_schema_history에는 실패로 기록됩니다. DB가 어중간한 상태가 됩니다.

대응은 두 가지입니다. 파일 하나에 변경 하나만 담아서 실패 지점을 명확하게 만들고, 실패했을 때는 남은 변경을 손으로 되돌린 뒤 repair로 실패 기록을 지우고 다시 실행합니다.

대용량 테이블의 ALTER는 락을 겁니다

스테이징에서 0.2초에 끝난 ALTER TABLE이 운영에서 40분 동안 테이블을 잠그는 일은 흔합니다. 데이터 양이 다르기 때문입니다. 마이그레이션은 운영과 비슷한 규모의 데이터에서 시간을 재 보고 배포해야 합니다.

규모가 크다면 Flyway 안에서 ALTER를 돌리지 않는 선택지도 있습니다. MySQL이라면 pt-online-schema-change나 gh-ost로 무중단 변경을 하고, Flyway에는 그 결과를 반영하는 기록용 마이그레이션만 남깁니다. PostgreSQL이라면 인덱스는 CREATE INDEX CONCURRENTLY를 씁니다. 다만 이 구문은 트랜잭션 안에서 실행할 수 없으므로 별도 파일로 분리하고 해당 마이그레이션의 트랜잭션을 꺼야 합니다.

테스트에서는 마이그레이션을 그대로 씁니다

테스트용으로 ddl-auto: create-drop을 쓰고 싶은 유혹이 있습니다. 빠르니까요. 하지만 그러면 테스트가 검증하는 스키마와 운영에 배포되는 스키마가 다른 것이 됩니다. 마이그레이션에 문법 오류가 있어도 테스트는 통과합니다.

Testcontainers로 실제 DB를 띄우고 Flyway를 그대로 돌리는 편이 낫습니다. 이렇게 하면 마이그레이션 자체가 매 테스트마다 검증됩니다.

spring:
  flyway:
    enabled: true
    locations:
      - classpath:db/migration
      - classpath:db/testdata
  jpa:
    hibernate:
      ddl-auto: validate

테스트 전용 데이터는 db/testdata에 따로 두고, 운영 설정에서는 이 경로를 넣지 않습니다. 앞서 말한 대로 locations는 기본값을 덮어쓰므로 classpath:db/migration을 반드시 함께 적어야 합니다.

여러 인스턴스가 동시에 뜰 때

Kubernetes에서 파드 세 개가 동시에 시작하면 Flyway도 세 번 실행됩니다. Flyway는 DB 락으로 이 상황을 처리하므로 마이그레이션이 중복 실행되지는 않습니다. 한 인스턴스가 실행하는 동안 나머지는 기다립니다.

다만 마이그레이션이 오래 걸리면 나머지 파드의 기동이 그만큼 늦어지고, 헬스체크 타임아웃에 걸릴 수 있습니다. 마이그레이션이 무거워지는 시점부터는 앱 시작에서 분리해 배포 파이프라인의 별도 단계(예: Kubernetes Job)로 빼는 것을 고려하세요.

Flyway와 Liquibase

같은 문제를 푸는 도구가 하나 더 있습니다. 고르는 기준은 대체로 단순합니다.

FlywayLiquibase
마이그레이션 작성SQL 파일 그대로XML/YAML/JSON changelog 또는 SQL
학습 비용낮음. SQL을 알면 끝changelog 문법을 익혀야 함
롤백Enterprise 전용, 수동 작성무료 버전에서 일부 자동 생성
DB 이식성SQL을 직접 쓰므로 DB에 종속추상화 계층이 DB 차이를 흡수
라이선스Community 무료(Apache 2.0), Enterprise 유료Community 무료, Pro 유료

DB를 바꿀 계획이 없고 팀이 SQL에 익숙하다면 Flyway가 편합니다. 배우는 데 하루면 충분하고, 마이그레이션 파일이 그냥 SQL이라 DBA와 같은 언어로 대화할 수 있습니다. 여러 DB 엔진을 동시에 지원해야 하거나 롤백 자동화가 요구 사항이라면 Liquibase를 봅니다.

도입 순서 정리

다음 주에 실제로 도입한다면 이 순서로 하면 됩니다.

  1. 로컬에서 먼저 익힙니다. 빈 DB에 V1, V2를 만들어 보고 flyway_schema_history를 직접 조회해 봅니다. 여기까지 한 시간이면 됩니다.
  2. 운영 스키마를 덤프해 V1__baseline.sql을 만듭니다. 빈 DB에서 재현되는지 diff로 검증합니다. 여기가 가장 오래 걸립니다.
  3. 개발 환경에 먼저 적용합니다. baseline을 찍고 flyway info로 상태를 확인합니다.
  4. 팀 규칙을 문서로 합의합니다. 앞의 네 가지를 팀 위키나 CONTRIBUTING.md에 적습니다. 도구보다 이쪽이 오래 갑니다.
  5. 운영에 적용합니다. 적용 후 baseline-on-migrate를 false로 되돌립니다.
  6. ddl-auto를 validate로 바꿉니다. 이제 스키마를 바꾸는 경로는 마이그레이션 파일 하나뿐입니다.

마치며

Flyway가 해 주는 일은 생각보다 소박합니다. SQL 파일을 순서대로 한 번씩 실행하고 기록을 남길 뿐입니다. 마법 같은 것은 없습니다.

그런데 이 소박한 규칙이 생기고 나면, DB 스키마가 "누군가 관리하고 있을 것으로 믿는 무언가"에서 "PR에서 리뷰하고 git으로 추적하는 코드"로 바뀝니다. 신규 입사자가 첫날 ./gradlew bootRun 한 번으로 최신 스키마를 갖게 되고, 배포 전에 어떤 DDL이 나갈지 미리 볼 수 있게 됩니다.

도입하기 가장 좋은 시점은 프로젝트 첫날이고, 그 다음으로 좋은 시점은 오늘입니다. 테이블이 늘어날수록 baseline을 뜨는 일만 어려워집니다.

참고 자료