flyway는 데이터베이스 스키마를 형상관리 해주는 데이터베이스 마이그레이션 도구입니다.
flyway를 사용함으로써 우리는 git
을 이용해 소스코드를 형상관리하며 버전을 관리하고 변동사항을 추적하고 기록하듯이, 데이터베이스 스키마의 변동사항을 확인하고 기록하며 이를 데이터베이스에 마이그레이션해줍니다.
스키마의 변동사항을 확인하고 기록할 수 있다는 것은 무엇을 의미할까요? 코드리뷰가 가능해진다는 미입니다. flyway를 사용함으로써 우리는 스키마 마저 코드리뷰를 할 수 있게 됩니다. 또한 DB 스키마에 문제가 발생했을 때 어느 시점에서 문제가 발생하였는 지 파악을 쉽게 할 수 있어 장애 대응을 빠르게 할 수 있습니다.
spring framework
에 JPA
를 사용하는 개발환경에서 flyway를 사용해보겠습니다.
<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>{원하는 버전}</version>
</dependency>
// https://mvnrepository.com/artifact/org.flywaydb/flyway-core
implementation group: 'org.flywaydb', name: 'flyway-core', version: '{원하는 버전}'
먼저 flyway-core
의존성을 추가해줍니다.
(!)해당 버전이 우리가 사용하는 데이터베이스를 지원하는 지 꼭 확인하여야 합니다!
spring:
...
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;mode=mysql
username: sa
password:
flyway:
enabled: true
baseline-on-migrate: true
jpa:
show-sql: true
generate-ddl: false
hibernate:
ddl-auto: validate
...
임베디드 H2 데이터베이스를 기준으로한 설정파일 예제입니다.
generate-ddl
을 false로 주어 애플리케이션이 동작하며 JPA가 자동으로 동작하며 DDL을 작성하여 DB에 적용하지 못하도록 합니다.
ddl-auto
를 validate로 주어 애플리케이션 동작 시 엔티티와 데이터베이스 스키마 간 매핑이 잘 이루어지는지 검증합니다.
스프링 애플리케이션 동작 시 기본 설정 경로로 resources/db/migration
하위의 스크립트 파일을 인식해 동작하며 파일 이름 규칙이 존재합니다. 그 규칙은 다음과 같습니다.
V{version}__name.sql
ex) resources/db/migration/V1__init_table.sql
flyway의 마이그레이션 규칙이 존재하는데 마이그레이션은 현재 데이터베이스에 적용된 버전보다 항상 높은 버전의 파일을 인식해 차례대로 적용하게 됩니다.
즉 V10
이 이미 데이터베이스에 마이그레이션 되어있는 상태에서 V9
파일을 만들면 마이그레이션이 이루어지지 않습니다.
V10
이 이미 데이터베이스에 마이그레이션 되어있는 상태에서 V11
, V12
, V8
스크립트 파일을 작성하였다면 V11
, V12
만 마이그레이션이 이루어지게 됩니다.
// resources/db/migration/V1__init_table.sql
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
my_column VARCHAR(100),
);
version이 1인 스크립트 파일을 작성하였습니다.
개발을 하다가 컬럼을 추가해야하는 일이 생겼습니다. 다음과 같이 스크립트 파일을 작성하면 됩니다
// resources/db/migration/V2__add_new_column.sql
ALTER TABLE my_table ADD COLUMN hello_new_column INTEGER DEFAULT 0
JPA
는 ORM
입니다. mysql
을 사용하다가 oracle
로 옮겨가고 싶을 때는 어떻게 해야할까요. location을 지정하여 벤더마다 별도의 디렉토리를 만들어 스크립트 파일을 관리하면 됩니다.
application-prod.yml
flyway:
...
locations: classpath:db/migration/{vendor}
...
이렇게 location을 지정해주면 h2 사용 시 db/migration/h2
디렉토리를, mysql 사용 시 db/migration/mysql
디렉토리를 찾아 하위에 작성된 스크립트 파일을 읽게 됩니다.
db seed값을 주어야할 일이 많습니다. 이럴 때 사용하면 고려할만한 것이 Repeatable Migration입니다. 일단 application-local.yml
에만 location을 별도로 또 지정해서 local에서만 seed를 줘보겠습니다.
application-local.yml
flyway:
...
locations: classpath:db/migration/{vendor},classpath:db/seed
...
네이밍 규칙은 다음과 같습니다.
// resources/db/seed/R__01_seed_member.sql
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
// resources/db/seed/R__02_....sql
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;