| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- claude code
- Infra
- golang
- GIT
- go
- 티스토리챌린지
- 보안
- LLM
- EKS
- MSA
- GoF
- OpenClaw
- 구조체
- 감상문
- goland
- Kubernetes
- logging
- typescript
- NemoClaw
- esbuild
- RDS
- AWS
- elasticsearch
- 캡슐화
- Intellij
- AI
- 오블완
- javascript
- 디자인패턴
- DB
- Today
- Total
Fall in IT.
Flyway - DB 마이그레이션 전략 본문
들어가며
데이터베이스 스키마 변경은 애플리케이션 개발에서 피할 수 없는 일이다. 문제는 이 변경을 어떻게 관리하느냐에 있다. Flyway는 데이터베이스 스키마 변경을 코드처럼 버전 관리할 수 있게 해주는 오픈소스 DB 마이그레이션 도구로, 개발팀이 DB 구조 변경 사항을 체계적으로 추적하고 모든 환경에 일관되게 적용할 수 있도록 설계되었다.
1. 왜 Flyway가 필요한가
DB를 수동으로 관리하는 조직에서는 다음과 같은 문제가 반복적으로 발생한다.
문제 설명
| 스키마 불일치 | 팀원마다 로컬 DB가 달라 "내 환경에서는 정상 동작한다"는 상황이 발생한다 |
| 수동 실행 의존 | SQL을 직접 공유하거나 문서화해야 하며, 누락 위험이 상존한다 |
| 이력 불투명 | 특정 테이블이 언제, 왜 변경되었는지 추적이 불가능하다 |
| 환경 재현 불가 | 신규 팀원 온보딩이나 서버 셋업 시 스키마를 일치시키기 어렵다 |
Flyway는 이 문제들에 대해 명쾌한 해법을 제시한다. 모든 DB 변경을 번호가 붙은 SQL 파일로 관리하고, 애플리케이션 실행 시 자동으로 순서대로 적용하는 것이다. 즉, DB 변경 사항이 곧 SQL 파일이고, 이 파일은 Git으로 관리된다.
2. 핵심 개념
마이그레이션 파일 네이밍 규칙
V{버전}__{설명}.sql
실제 프로젝트에서는 다음과 같은 구조가 된다.
db/migration/
├── V1__init_schema.sql
├── V2__add_user_table.sql
├── V3__add_email_column.sql
└── V4__add_index_on_email.sql
버전 번호는 반드시 유니크해야 하며, 접두사와 설명 사이의 언더스코어는 두 개(__)라는 점에 유의해야 한다. 사소해 보이지만, 실무에서 한 개만 사용하여 마이그레이션이 인식되지 않는 실수가 의외로 빈번하다.
마이그레이션 파일 종류
접두사 이름 특징 예시
| V | Versioned | 한 번만 실행되며, 주력으로 사용한다 | V1__create_table.sql |
| U | Undo | 롤백 용도 (유료 기능) | U1__drop_table.sql |
| R | Repeatable | 내용이 변경되면 재실행된다 | R__create_view.sql |
실무에서는 V 접두사 파일이 대부분을 차지한다. R 접두사는 뷰(View)나 저장 프로시저처럼 매번 재생성해도 무방한 객체에 적합하다. U 접두사의 Undo 기능은 유료 플랜에서만 제공되므로, 무료 버전을 사용하는 경우 롤백 전략을 별도로 수립해야 한다.
flyway_schema_history 테이블
Flyway는 자체적으로 이력 관리 테이블을 생성하여 어떤 마이그레이션이 언제, 어떤 순서로 적용되었는지를 기록한다.
installed_rank version description script checksum success
| 1 | 1 | init schema | V1__init_schema.sql | 12345678 | true |
| 2 | 2 | add user table | V2__add_user_table.sql | 87654321 | true |
| 3 | 3 | add email column | V3__add_email_column.sql | 11223344 | true |
여기서 주목할 것은 checksum 컬럼이다. Flyway는 각 파일의 체크섬을 저장해두고, 이미 적용된 파일이 사후에 변경되면 즉시 오류를 발생시킨다. 이 메커니즘이 마이그레이션 이력의 무결성을 보장하는 핵심 장치이다.
3. 동작 방식
최초 실행
앱 시작
-> Flyway가 flyway_schema_history 테이블 부재를 확인
-> 테이블을 자동 생성
-> db/migration 폴더에서 V*.sql 파일을 탐색
-> 버전 순서대로 SQL을 실행
-> 각 실행 결과를 history 테이블에 기록
두 번째 이후 실행
앱 시작
-> flyway_schema_history 테이블을 확인
-> 이미 실행된 파일은 건너뜀
-> 새로 추가된 파일만 실행
-> 실행 완료 후 history에 기록
이 구조 덕분에 개발자는 새로운 마이그레이션 파일만 추가하면 된다. Flyway가 "어디까지 실행했는지"를 알고 있으므로, 나머지는 자동으로 처리된다.
파일 변조 감지
기존 V2__add_user_table.sql의 내용을 수정
-> Flyway가 체크섬 불일치를 감지
-> ERROR: Migration checksum mismatch!
-> 앱 실행을 중단
이 동작은 의도된 설계이다. 한번 적용된 마이그레이션을 사후에 수정하는 것은 환경 간 스키마 불일치를 초래하므로, Flyway는 이를 원천적으로 차단한다.
4. Spring Boot 연동
Spring Boot 프로젝트에서 Flyway를 도입하는 과정은 놀라울 정도로 간결하다.
의존성 추가 (build.gradle)
implementation 'org.flywaydb:flyway-core'
마이그레이션 파일 배치
src/main/resources/db/migration/
├── V1__init_schema.sql
├── V2__add_user_table.sql
└── V3__add_email_column.sql
application.yml 설정
spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true # 기존 DB에 처음 Flyway를 적용할 때
out-of-order: false # 버전 순서를 강제한다
validate-on-migrate: true # 체크섬 검증을 활성화한다
baseline-on-migrate 옵션은 이미 운영 중인 DB에 Flyway를 사후 도입할 때 필수적인 설정이다. 이 옵션이 true이면 Flyway는 현재 DB 상태를 기준선(baseline)으로 설정하고, 이후 추가되는 마이그레이션만 실행한다. 신규 프로젝트라면 이 옵션 없이 시작해도 무방하다.
Spring Boot에서는 애플리케이션 시작 시 마이그레이션이 자동으로 실행되므로, 별도의 수동 개입이 필요하지 않다.
5. 주요 CLI 명령어
명령어 설명
| flyway migrate | 미실행 마이그레이션을 순서대로 실행한다 |
| flyway info | 현재 마이그레이션 상태를 조회한다 |
| flyway validate | 파일 변조 여부 및 체크섬을 검증한다 |
| flyway repair | 실패한 마이그레이션 이력을 수정한다 |
| flyway baseline | 기존 DB를 특정 버전 기준으로 초기화한다 |
| flyway clean | 모든 테이블을 삭제한다 (운영 환경에서는 절대 사용 금지) |
repair 명령어는 마이그레이션 실행 중 오류가 발생하여 history 테이블에 실패 기록이 남았을 때 유용하다. 원인을 해결한 후 repair로 실패 이력을 정리하고, migrate를 다시 실행하는 것이 일반적인 복구 절차이다.
6. 실무 주의사항
Flyway를 운영하면서 체감한 규칙들을 정리한다.
- 기존 파일은 절대 수정하지 않는다. 체크섬 불일치로 애플리케이션 기동이 실패한다. 수정이 필요하면 반드시 새 버전 파일을 추가한다.
- 버전 번호는 유니크하게 유지한다. 동일한 버전 번호를 가진 파일이 두 개 이상 존재하면 오류가 발생한다. 여러 개발자가 동시에 작업할 경우, 타임스탬프 기반 버전 번호(예: V20260326_1430__description.sql)를 사용하면 충돌을 줄일 수 있다.
- flyway clean은 운영 환경에서 절대 사용하지 않는다. 이 명령은 모든 테이블을 삭제한다. Spring Boot 설정에서 spring.flyway.clean-disabled=true를 운영 프로파일에 명시해 두는 것이 안전하다.
- DB 접속 정보를 마이그레이션 파일이나 설정 파일에 직접 노출하지 않는다. 환경 변수나 Vault를 통해 주입하는 방식을 사용한다.
- 마이그레이션 파일에는 DDL만 포함하는 것을 원칙으로 한다. DML(데이터 조작)이 필요한 경우, 해당 파일의 설명에 데이터 변경임을 명시하고 트랜잭션 안전성을 반드시 확인한다.
7. Flyway vs Liquibase
DB 마이그레이션 도구를 선정할 때 Flyway와 함께 거론되는 것이 Liquibase이다.
항목 Flyway Liquibase
| 문법 | SQL 위주로 직관적이다 | XML, YAML, JSON, SQL을 모두 지원한다 |
| 학습 곡선 | 낮다 | 상대적으로 높다 |
| 롤백 | 유료 플랜에서 제공한다 | 무료로 지원한다 |
| 커뮤니티 | 활발하다 | 활발하다 |
| 적합한 상황 | 소~중규모 프로젝트에서 빠르게 도입할 때 | 복잡한 엔터프라이즈 환경에서 |
Flyway의 장점은 SQL을 그대로 사용한다는 점이다. 별도의 DSL을 학습할 필요 없이, DBA가 작성한 SQL을 그대로 마이그레이션 파일로 사용할 수 있다. 반면 Liquibase는 DB 벤더에 독립적인 추상화 레이어를 제공하므로, 다중 DB를 지원해야 하는 환경에서는 Liquibase가 더 적합할 수 있다.
마치며
Flyway의 본질은 단순하다. "DB 변경을 파일로 만들고, 순서대로 실행하고, 한번 실행한 것은 건드리지 않는다." 이 세 가지 원칙만 지키면 환경 간 스키마 불일치, 변경 이력 추적 불가, 수동 배포 의존이라는 고질적인 문제에서 벗어날 수 있다.
참고 자료
'데이터베이스' 카테고리의 다른 글
| DB에 JSON 데이터를 저장하는 두 가지 방법: JSON 타입 vs TEXT 타입 (0) | 2026.03.26 |
|---|---|
| 데이터베이스 식별관계와 비식별관계 (1) | 2022.07.02 |
