🔥 Flyway?
DB 스키마도 애플리케이션 코드처럼 ‘버전, 히스토리, 리뷰, 배포 파이프라인’ 안에서 관리해야 한다. 다양한 환경에서 데이터베이스의 상태가 불확실하거나 스크립트 적용 여부에 대해 혼란스럽다면, 또 새로운 데이터베이스 설정에 어려움이 있다면 Flyway 를 통해 해결할 수 있다. Flyway를 통해 데이터베이스 형상관리를 어떻게 할 수 있는지 알아보자.
🔥 Core concepts
Getting started with Flyway - Redgate Flyway - Product Documentation
Getting started with Flyway - Redgate Flyway - Product Documentation
Flyway helps you version your database changes and automate your database deployments safely and easily.
- 1: 마이그레이션 파일(스크립트)로 실행할 DDL/DML 을 정의한다. Flyway 는
classpath:db/migration
경로를 스캔해 버전 순서대로 적용할 목록을 만든다.
- 2: 처음 실행할 때
flyway_schema_history
테이블을 만들고 적용한 각 마이그레이션의 메타데이터(버전, 설명, 체크섬 등)을 한 행씩 기록한다.
- 3: 히스토리와 파일의 체크섬/버전을 비교해 아직 적용 안 된 스크립트만 실행한다. 이미 기록된 버전은 재실행하지 않고 파일이 바뀌면
validate
단계에서 체크섬 불일치로 실패하게 된다. (필요시repair
)
우리가 작성한 스크립트를 기반으로 형상관리가 되는 것이지 테이블의 변경 사항을 직접 추적하지는 않는다. (스크립트에 테이블 변경 사항을 기록하면 추적이 되겠지만) 위의 컨셉을 기억하고 실전으로 가보자.
🔥 Flyway 간단 사용
docker-compose 를 참고하여 MySQL 서버를 띄우고 최소한의 의존성으로 flyway 의 동작을 살펴본다.
🚀 의존성
상황에 맞게 버전을 선택하면 된다. 본 글에선
11.12.0
버전을 선택했으며 implementation
로 의존성을 추가했는데 컴파일시에 필요가 없거나 테스트에서 사용하지 않을거라면 runtimeOnly
로 추가해도 무방하다.🚀 Yeah! Empty!
비어있는 데이터베이스에 Flyway 를 실행시켜보자
resources/db/migration
에 스크립트는 하나도 없으며 어떻게 동작하는지 아래의 로그로 알 수 있다./* 생략.. */ HikariPool-1 - Start completed. Database: jdbc:mysql://localhost:13306/lkdcode-flyway (MySQL 8.0) Schema history table `lkdcode-flyway`.`flyway_schema_history` does not exist yet Successfully validated 0 migrations (execution time 00:00.014s) No migrations found. Are your locations set up correctly? Creating Schema History table `lkdcode-flyway`.`flyway_schema_history` ... Current version of schema `lkdcode-flyway`: << Empty Schema >> Schema `lkdcode-flyway` is up to date. No migration necessary. Tomcat started on port 18080 (http) with context path '/'
익숙한 히카리 풀 로그부터 톰캣 사이에 Flyway 로그가 있는데 살펴보면..
MySQL 에 잘 접속했고 마이그레이션 파일을 0개 찾았다고 한다. 기본 경로인
db/migration
에서 찾지 못했다고 친절하게 알려주고 flyway_schema_history
테이블을 만들었다. 그리고 스키마 버전은 적용된게 없다. 이제 적용할 스크립트가 없으니 종료한다는 로그다.실제 데이터베이스를 확인하면
flyway_schema_history
가 생성되었고 텅 비어있는 것을 확인할 수 있다.🚀 My first migration
이제 DDL 을 작성한 뒤
resources/db/migration
에 올려보자. DDL/DML 은 데이터베이스 제품에 맞게 작성하면 되지만 파일명은 Flyway 의 규칙을 따라야 한다. 파일명에 대한 규칙을 먼저 살펴본다.🚀 V1__my_first_migration.sql
파일명 규칙은
접두사
+ version
+ 구분자
+ 내용 + 확장자
형식으로 이루어져 있다.V1__my_first_migration.sql
는 올바른 규칙을 가진 파일명인데V
: 접두사
1
: 버전
__
: 구분자
my_first_migration
: 내용
.sql
: 확장자
파일명의 언더스코어 2개로(
spring.flyway.sql-migration-separator
를 통해 설정가능) 접두사+버전과 내용을 구분한다. 접두사에 따라 기능을 달리 수행하게 되므로 접두사에 대해 좀 더 살펴보자!🚀 접두사
접두사로 올 수 있는 값은 총 4개이며 각각 다르게 동작한다.
🎯 V - Versioned migration
- 사용 예시:
V1__my_first_migration.sql
버전 오름차순으로 딱 한 번 실행된며 실행 결과는
flyway_schema_history
테이블에 기록된다.테이블/인덱스/제약조건/컬럼 변경 등 순차적 변화를 남기는 모든 작업을 해당 접두사로 수행하면 된다.
🎯 R - Repeatable migration
- 사용 예시:
R1__my_first_migration.sql
위의 Versioned 가 끝난 뒤 검사한다. 파일의 체크섬이 바뀌면 재실행하게 되는데 반복 가능한 쿼리를 사용하면 된다. 예를 들어 뷰/프로시저/함수/권한처럼 정의(DDL)할 값을 최신으로 유지시키고 싶을 때 사용하면 된다.
(대량의 DML 를 R로 두면 수정 때마다 수행되니 전량 재실행 될 수 있음)
🎯 U - Undo migration
- 사용 예시:
U1__my_first_migration.sql
V버전을 되돌리는 스크립트이다.
flyway undo
등으로 직전 버전부터 역순 적용된다.🎯 B - Baseline migration
- 사용 예시:
B1__my_first_migration.sql
Flyway 가
Yeah!Empty!
에서 시작하지 않는다면 해당 접두사를 통해 이미 존재하는 레거시 스키마를 시작점으로 잡을 수 있다. 히스토리가 없을 때 상태를 정의할 수 있고 파일 없이도 baselineOnMigrate=true
등으로 설정할 수 있다.Yeah!Empty!
에서 시작하여 flyway_schema_history
테이블만 생성했으니 다시 작은 시나리오 실전을 통해 어떻게 동작하는지 살펴보자🚀 착실한 버저닝
kiwi 테이블을 추가해보자 DDL 이며
resources/db/migration
에 두면 Flyway 가 잘 읽고 반영한다.- Flyway 가 마이그레이션된 스크립트를 읽어 반영하는 로그다. 이때
flyway_schema_history
에 기록하게 되는데 이 중checksum
컬럼은 파일 바이트 내용을 기반으로 계산한 CRC32 값이다.
- 실제 테이블에 값이 추가됨을 확인할 수 있다.
이후 tomato, banana 마이그레이션도 잘 추가됨을 확인할 수 있다.
🚀 기존 Migration Script 수정하기
Flyway 는
flyway_schema_history
기록된 checksum 을 토대로 migration script 와 비교하게 되는데 새로 버저닝을 하지 않고 수정하면 어떻게 될까?V2__tomato.sql
을 그냥 수정하고 서버를 실행하면 아래와 같이 MySQL 연결 후 바로 셧다운 되는 것을 볼 수 있다.🚀 DB로 가서 컬럼 삭제하기
Flyway 는 migration script ↔
flyway_schema_history
로만 비교한다니, 테이블로 이동해서 컬럼을 삭제해보자. 기존에 컬럼은 총 6개인데 2개만 남기고 모두 지웠다.Flyway 는 변경사항이 없다고 말하고 있고 서버도 잘 기동됐다. 하지만 실제 데이터베이스에 테이블은 migration script 와 다르게 변경되었다.
Flyway 는 버전 스크립트를 기록하고 순서대로 적용하여 이력을 기록하고 기존 스크립트를 바꾸지 않는다가 원칙이기 때문에 DB 상태의 차이 탐지는 기본 기능이 아니다.
Flyway 가 migration script 를 읽어 DDL 을 다시 수행하게 하고 싶다면
flyway_schema_history
로 이동해 해당 레코드를 지워주면 된다. (DDL 을 원한다면 테이블도 지워야한다.)🚀 Flyway 의 다양한 Properties
spring.flyway.~
설정들이 다양하므로 상황에 맞게 설정하고 싶다면 아래의 문서에서 확인할 수 있다.Common Application Properties :: Spring Boot
Common Application Properties :: Spring Boot
Various properties can be specified inside your application.properties file, inside your application.yaml file, or as command line switches. This appendix provides a list of common Spring Boot properties and references to the underlying classes that consume them.