본문 바로가기
dev/spring

[Spring] Flyway DB Migration

by igooo 2024. 8. 5.
728x90

개요

수년 전 개발했던 프로젝트 중 mysql 5.x 버전으로 개발된 프로젝트의 Mysql 버전을 8.x 버전으로 올리고, 간단한 마이그레이션이 필요하여 Spring sql init으로 사용하던 DB 스키마 정의를 Flyway를 적용하여 마이그레이션 한다.

 

Flyway

Database migrations made easy

  • Free - API/CLI and Desktop GUI
  • Buil on Open Source
  • Version control your database migration scripts
  • Powered by the Flyway commnity and Redgate

Flyway는 DB 마이그레이션을 지원하는 도구로 API/CLI와 GUI 툴을 제공하며 다양한 데이터베이스를 제공한다.

또한 Spring Boot와 통합되어 애플리케이션의 마이그레이션 도구로 사용할 수 있다.

 

동작 방식

Spring에서 Flyway에 동작 방식은 마이그레이션 정보를 관리할 flyway_schema_history 테이블을 생성하고, 버전별로 생성된 SQL 파일을 읽어서 마이그레이션 한다.

flyway_schema_history 생성

Spring에서 Datasource를 설정하고 flyway 설정을 추가하면 기본적으로 flyway에서 사용하는 관리용 테이블을(flyway_schema_history)  생성한다.

DB Migraion 실행

관리 테이블이(flyway_schema_history) 생성되면 리소스 디렉터리(src/main/resources) 하위에 db.migraion 디렉토리 하위에 있는 sql 파일 들을 조회하여 버전별로(파일 이름으로 정의) 마이그레이션을 실행한다.

Migraion 정보 저장

위에서 SQL 파일로 마이그레이션을 실행하면 처음에 생성한 관리 테이블에(flyway_schema_history) 마이그레이션을 실행한 결과를 저장한다.

 

자세한 동작 방식은 공식 문서를 참고한다. (https://documentation.red-gate.com/fd/getting-started-with-flyway-184127223.html)

 

 

Spring Boot에서 Flyway 연동

Flyway Dependencies 추가

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
	implementation 'org.flywaydb:flyway-core'
	implementation 'org.flywaydb:flyway-mysql'
	
	runtimeOnly 'com.mysql:mysql-connector-j'	
}

 

Migraion SQL  추가(Ver 1)

리소스 디렉토리(src/main/resources) 하위에 db.migration 디렉터리를 생성하고 SQL 파일을 작성한다.

SQL  파일 형식은 아래와 같다.

V<Version>__<Name>.sql

ex) V1__init_schema.sql (V1 다음 언더바 2개)

# V1__init_table.sql

CREATE TABLE `user` (
	`id` SEERIAL PRIMARY KEY,
	`name` VARCHAR(255) NOT NULL,
	`created` DATE NOT NULL
)

Spring Datasource를 설정한다.

# application.properties

spring.flyway.enabled=true
spring.datasource.url={jdbc url}
spring.datasource.username={user name}
spring.datasource.password={password}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

 

애플리케이션 실행

[flyway-test] [ restartedMain] org.flywaydb.core.FlywayExecutor       : Database: jdbc:mysql~~ (Mysql 8.0)
[flyway-test] [ restartedMain] o.f.core.internal.command.DbValidate   : Successfully validataed 1 migraion (execution time 00:00.041s)
[flyway-test] [ restartedMain] o.f.core.internal.command.DbMigrate    : Cuurrent version of schema 'flyway' << Empty Schema >>
[flyway-test] [ restartedMain] o.f.core.internal.command.DbMigrate    : Migrating schema 'flyway' to version "1 - init table"
[flyway-test] [ restartedMain] of.core.internal.command. DbMigrate    : Successfully applied 1 migraion to schema 'flywway', not at version v1 (execution time 00:00.088s)

 

SHOW tables;

flyway_schema_history
user

 

Migraion SQL  추가(Ver 2)

아래 파일을 db.migration 디렉토리에 추가하고 애플리케이셔을 다시 실행한다.

# V2__add_item_table.sql

CREATE TABLE `item` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`name` VARCHAR(255) NOT NULL,
	`created` DATE NOT NULL
)

신규로 추가한 item 테이블까지 생성된 모습을 볼 수 있다.

SHOW TABLES;

flyway_schema_history
user
item

 

기존 SQL 스크립트 변경하기

이미 스키마가 반영된 SQL 파일을 수정하여 애플리케이션을 재 실행하면 SQL이 변경되었다는 오류를 발생하고 애플리케이션은 실행에 실패한다.

# V2__add_item_table.sql

CREATE TABLE `item` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`name` VARCHAR(255) NOT NULL,
	`created` DATE
)

버전 2로 작성한 item테이블에 created 칼럼에 NOT NULL 조건을 삭제하고 실행하면 아래와 같은 오류가 발생한다.

Migraion checksum mismatch for migraion version 2
-> Applied to database : 1777652537
-> Resolved locally    : 191147207

 

 

Spring 기본 SQL 스크립트를 사용한 DB 초기화

Spring boot에서도  spring.sql하위의 설정으로 데이터베이스의 스키마를 초기화하거나(schema.sql) 데이터를 입력하는(data.sql) 기능을 지원하지만 Flyway와 같은 마이그레이션 도구를 사용하는 경우 위 설정들에 대하여 사용하는 것을 권장하지는 않는다.

참고 : https://docs.spring.io/spring-boot/how-to/data-initialization.html#howto.data-initialization.using-basic-sql-scripts

 

 

참고