상세 컨텐츠

본문 제목

Spring Boot에서 Flyway로 DB Migration 관리하기

Programming/BackEnd

by Dal_pang 2026. 7. 1. 09:04

본문

백엔드 프로젝트를 만들다 보면 테이블을 만들고, 컬럼을 추가하고, 인덱스를 붙이는 일이 계속 생긴다.

처음에는 DB에 직접 접속해서 SQL을 실행해도 괜찮아 보인다.

CREATE TABLE users (
  id BIGINT PRIMARY KEY,
  name VARCHAR(100)
);

하지만 프로젝트가 커지거나 환경이 늘어나면 문제가 생긴다.

  • 내 로컬 DB(개발 DB)에는 테이블이 있는데 검증 or 운영 DB에는 없다. 
  • 언제 어떤 테이블이 추가됐는지 추적하기 어렵다.
  • 배포할 때 DB 변경을 누가, 언제, 어떤 순서로 해야 하는지 헷갈린다.

이 문제를 해결하기 위해 사용하는 도구가 Flyway다.

Flyway란?

Flyway는 DB schema 변경 이력을 관리하는 migration 도구다.

코드 변경 이력을 Git으로 관리하듯이,
DB 변경 이력을 SQL 파일로 관리하게 해준다.

Spring Boot 프로젝트에서는 보통 다음 위치에 migration SQL 파일을 둔다.

src/main/resources/db/migration/

예를 들면 이런 식이다.

src/main/resources/db/migration/V1__create_birth_profiles.sql
src/main/resources/db/migration/V2__create_counseling_sessions.sql
src/main/resources/db/migration/V3__add_prompt_version.sql

파일 이름에는 규칙이 있다.

V번호__설명.sql

예:

V1__create_users.sql
V2__add_email_to_users.sql

Flyway는 이 파일들을 버전 순서대로 실행한다.

Flyway는 어떻게 동작할까?

Spring Boot 애플리케이션이 실행될 때 Flyway가 함께 실행되도록 설정할 수 있다.

앱이 뜰 때 Flyway는 다음 과정을 수행한다.

  1. DB에 연결한다.
  2. DB 안의 flyway_schema_history 테이블을 확인한다.
  3. 이미 적용된 migration과 아직 적용되지 않은 migration을 비교한다.
  4. 아직 적용되지 않은 SQL 파일만 순서대로 실행한다.
  5. 실행 결과를 flyway_schema_history에 기록한다.
  6. 애플리케이션이 계속 시작된다.

즉, 이미 실행된 migration은 다시 실행하지 않는다.

예를 들어 DB에 V1만 적용되어 있고 프로젝트에는 V1, V2, V3가 있다면, Flyway는 V2, V3만 실행한다.

Docker 환경에서도 적용될까?

적용된다.

Spring Boot 애플리케이션을 Docker 이미지로 빌드하면, migration SQL 파일도 애플리케이션 리소스에 포함된다.

예를 들어 이미지 안에 다음 파일들이 들어 있다고 하자.

db/migration/V1__create_birth_profiles.sql
db/migration/V2__create_sessions.sql

이 이미지를 dev 환경에서 실행하면 dev DB에 migration이 적용된다.
staging 환경에서 실행하면 staging DB에 migration이 적용된다.
prod 환경에서 실행하면 prod DB에 migration이 적용된다.

중요한 점은 migration 상태는 DB별로 따로 관리된다는 것이다.

같은 Docker 이미지를 사용하더라도 연결하는 DB가 다르면, 각 DB의 flyway_schema_history를 기준으로 migration이 적용된다.

dev app     -> dev PostgreSQL     -> dev DB의 flyway_schema_history
staging app -> staging PostgreSQL -> staging DB의 flyway_schema_history
prod app    -> prod PostgreSQL    -> prod DB의 flyway_schema_history

Spring Boot 설정 예시

Gradle 의존성은 다음과 같이 추가할 수 있다.

implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-database-postgresql'

PostgreSQL을 사용하는 경우 flyway-database-postgresql을 함께 추가한다.

설정 예시는 다음과 같다.

spring:
  datasource:
    url: jdbc:postgresql://postgres:5432/app
    username: app
    password: app

  flyway:
    enabled: true

이렇게 설정하면 Spring Boot 애플리케이션이 실행될 때 Flyway가 자동으로 migration을 수행한다.

예시 migration 파일

-- src/main/resources/db/migration/V1__create_birth_profiles.sql

CREATE TABLE birth_profiles (
  id UUID PRIMARY KEY,
  birth_date DATE NOT NULL,
  birth_time TIME,
  calendar_type VARCHAR(20) NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

다음 변경이 필요하면 새 파일을 추가한다.

-- src/main/resources/db/migration/V2__create_counseling_sessions.sql

CREATE TABLE counseling_sessions (
  id UUID PRIMARY KEY,
  birth_profile_id UUID NOT NULL REFERENCES birth_profiles(id),
  topic VARCHAR(50) NOT NULL,
  prompt TEXT NOT NULL,
  response TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

기존 V1 파일을 수정하는 대신, V2 파일을 추가하는 것이 중요하다.

이미 다른 환경에 적용된 migration 파일을 수정하면 환경 간 schema 이력이 꼬일 수 있다.

운영 환경에서는 자동 실행해도 될까?

개인 프로젝트나 MVP 단계에서는 앱 시작 시 Flyway가 자동으로 migration을 실행하게 두는 방식이 편하다.

Docker image 실행
-> Spring Boot app 시작
-> Flyway migration 자동 적용
-> app 구동

하지만 운영 환경에서는 더 조심해야 한다.

운영 DB에 schema 변경이 들어가는 일은 위험할 수 있기 때문에, 실무에서는 migration을 애플리케이션 시작과 분리하기도 한다.

예를 들면:

1. 배포 파이프라인에서 migration job 실행
2. migration 성공 확인
3. 새 애플리케이션 버전 배포

이 방식은 조금 더 번거롭지만, DB 변경 실패와 애플리케이션 배포 실패를 분리해서 볼 수 있다.

정리

Flyway는 DB 변경 이력을 코드처럼 관리하게 해주는 도구다.

Spring Boot와 함께 사용하면 애플리케이션 실행 시 migration을 자동 적용할 수 있고, Docker로 다른 환경에 배포해도 각 환경의 DB 상태에 맞게 필요한 migration만 실행할 수 있다.

개인 프로젝트에서는 앱 시작 시 자동 migration으로 시작해도 충분하다.
운영 환경에서는 배포 파이프라인에서 migration을 별도 단계로 분리하는 방식을 고려할 수 있다.

핵심은 이것이다.

테이블 변경을 DB에 직접 손으로 반영하지 말고, migration 파일로 남기자.
그래야 로컬, 개발, 운영 환경의 DB schema를 일관되게 관리할 수 있다.

 
728x90

관련글 더보기