
프로젝트를 진행하다 보면, 데이터베이스 스키마가 계속해서 변경됩니다. 이때 로컬, 테스트, 운영 서버에서 각각 사용하고 있는 데이터베이스 스키마에도 변경 사항을 반영해야 합니다. JPA를 사용하는 경우, 엔티티 구조를 변경한 이후 모든 데이터베이스에도 이를 적용해야 합니다.
Spring Data JPA는 ddl-auto 옵션을 통해 애플리케이션 로딩 시점에 비교적 간단히 수정 사항을 반영할 수 있습니다. 하지만 운영 서버는 장애가 발생할 수 있으므로 create, create-drop, update 설정을 적용을 지양해야 합니다.
저는 사이드 프로젝트를 진행할 때, DDL을 실행시켜 스키마 구조를 직접 수정하곤 했습니다. 하지만 매번 스키마를 수정하는 일은 비용이 많이 드는 작업이었습니다. 휴먼 에러가 발생할 가능성이 있고, 작업 후 다른 팀원들에게도 수정 사항을 공유해야 하는 등 신경써야 할 부분이 많았습니다.
이런 문제를 해결할 수 있는 방법으로 데이터베이스 마이그레이션 툴인 Flyway에 대해 정리하고자 합니다.

V1__init.sql, V2__add_column.sql 등과 같은 파일명을 사용하여 순차적으로 실행됨프로젝트 환경은 다음과 같습니다.
Spring Boot는 기본적으로 Flyway와 Liquibase라는 고수준의 마이그레이션 도구를 지원합니다. 따라서 간단하게 Flyway를 프로젝트에 적용할 수 있습니다.(참고)
spring:
datasource:
url: jdbc:mysql://localhost:3306/transactional
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: validate # 데이터베이스 스키마와 JPA 엔티티의 일관성을 강제합니다. 다른 부분이 있다면 애플리케이션이 실행되지 않습니다.
flyway:
enabled: true
@Entity
@Table(name = "member")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
...
}
Flyway는 마이그레이션 스크립트 버전을 기준으로 스크립트를 실행합니다. 또한 스크립트 파일명은 아래 규칙을 따라야 합니다.
# V1__create_member.sql
CREATE TABLE member (
member_id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (member_id)
);
회원이 보유한 돈을 저장하기 위해 엔티티에 money 필드가 추가되었다고 가정하겠습니다.
@Entity
@Table(name = "member")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "money", nullable = false)
private int money; // 새로운 칼럼 추가
...
}
이후 애플리케이션을 실행하면 SchemaManagementException이 발생하며 실패합니다. 앞서 ddl-auto를 validate로 설정했기 때문에 스키마 불일치로 에러가 발생한 것입니다.
org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [money] in table [member]
기존 테이블에 money 칼럼을 추가하는 스크립트를 작성하겠습니다.
# V1_1__add_money_column.sql
ALTER TABLE member ADD COLUMN money INT NOT NULL;
이후 애플리케이션을 실행하면 Flyway는 1.1 버전 스크립트를 실행하여 스키마 구조가 변경된 것을 확인할 수 있습니다.

공식적으로는 prefix로 3가지의 마이그레이션 타입을 지정할 수 있습니다.
Undo는 롤백을 위해 사용되지만 유료 버전만 지원하는 기능이며, Repeatable은 특정 버전은 존재하지 않고 파일에 변경 사항이 있을 때마다 다시 실행되는 특징이 있습니다. 파일의 변경 여부는 flyway_schema_history 테이블에서 체크섬 비교를 통해 감지합니다.
이처럼 Flyway를 사용하면 데이터베이스의 변경 사항을 추적할 수 있고, 팀 내부적으로 스키마의 일관성을 유지하는데 편리할 것 같습니다.
좋은 포스트 잘 읽고갑니다^^