NYO_O

Flyway 실전 도입기 4편: Spring Boot 연동부터 마이그레이션 검증까지 완벽 가이드 본문

DevOps/Flyway

Flyway 실전 도입기 4편: Spring Boot 연동부터 마이그레이션 검증까지 완벽 가이드

NYO_O 2026. 5. 20. 06:14
반응형

전체 작업의 순서는 다음과 같습니다.

  1. 로컬 DB 초기화 및 V1 스키마 생성하기
  2. pg_dump로 순수 스키마 SQL 추출하기
  3. 하이버네이트가 만든 스키마의 5가지 문제점과 V1 스크립트 완벽 정제
  4. Spring Boot 연동부터 마이그레이션 검증까지 완벽 가이드 ← 오늘 다룰 내용

1. 서론: 준비된 스크립트, 이제 애플리케이션에 올릴 시간

지난 3편에서는 하이버네이트(Hibernate)가 자동으로 만들어준 엉성한 스키마를 꼼꼼하게 분석하고 정제하여, 실무 운영 기준에 맞는 완벽한 V1__init.sql 스크립트를 완성했습니다.

뼈대가 되는 첫 번째 마이그레이션 파일이 준비되었으니, 이제 이 스크립트를 관리하고 실행해 줄 주체인 Flyway를 Spring Boot 프로젝트에 본격적으로 연동할 차례입니다.

오늘은 build.gradle에 필수 의존성을 추가하는 방법부터, 환경별 application.yml 설정, 그리고 대망의 빈 데이터베이스 부팅과 JPA validate 통과 검증까지 진행해 보겠습니다.

2. build.gradle: 의존성 추가와 모듈 분리의 비밀

가장 먼저 프로젝트의 build.gradle 파일을 열고 의존성을 추가해야 합니다. dependencies 블록 안의 데이터베이스 관련 섹션에 다음 두 줄을 추가해 줍니다.

// Database & ORM
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
implementation 'org.flywaydb:flyway-core' // Flyway 핵심 엔진
implementation 'org.flywaydb:flyway-database-postgresql' // PostgreSQL 전용 어댑터

학습 포인트: 왜 Flyway 의존성이 2개나 필요할까요? 과거 버전에서는 flyway-core 하나만으로 충분했지만, Flyway 10 버전부터는 구조가 변경되었습니다. 데이터베이스별 지원 모듈이 코어 엔진에서 분리되었기 때문입니다.

  • flyway-core: 마이그레이션 실행, 히스토리 테이블 관리, 체크섬 검증 등을 담당하는 Flyway의 심장입니다.
  • flyway-database-postgresql: PostgreSQL에 특화된 SQL 처리와 트랜잭션 모드를 담당하는 어댑터입니다.

3. application.yml: 공통 환경 설정과 필수 옵션 파헤치기

다음은 모든 환경에서 공통으로 적용될 application.yml 파일에 Flyway 설정을 추가할 차례입니다. spring 블록 하위의 jpa 설정과 같은 레벨에 flyway 섹션을 작성합니다.

spring:
  # ... 기존 datasource 설정 ...
  jpa:
    # ... 기존 jpa 설정 ...
  flyway:
    enabled: true
    locations: classpath:db/migration
    baseline-on-migrate: false
    validate-on-migrate: true
    schemas: public

각 옵션이 어떤 역할을 하는지 짚고 넘어가겠습니다.

  • enabled (true): Flyway 기능을 활성화합니다. 기본값이지만, 명시적으로 적어두어 의도를 분명히 합니다.
  • locations (classpath:db/migration): 마이그레이션 SQL 파일들이 위치한 경로입니다. 새로 합류한 개발자가 설정 파일만 봐도 스크립트 위치를 단번에 알 수 있게 해줍니다.
  • baseline-on-migrate (false): 아주 중요한 옵션입니다. 이미 운영 중이던 데이터베이스에 Flyway를 처음 도입할 때 기존 데이터를 보존하기 위해 사용하는 옵션입니다. 우리는 기존 로컬 DB를 날리고 빈 깡통 상태에서 V1부터 처음 적용할 것이므로 반드시 false로 설정해야 합니다.
  • validate-on-migrate (true): 이미 데이터베이스에 적용된 마이그레이션 파일의 내용이 추후 수정되었는지 체크섬으로 검증합니다. 마이그레이션 파일은 한 번 적용되면 절대 수정해선 안 된다는 불문율을 강제하는 안전장치입니다.
  • schemas (public): Flyway가 관리할 대상 스키마를 지정합니다. PostgreSQL의 기본 스키마인 public을 명시하여 다른 스키마를 건드리는 사고를 방지합니다.

4. 환경별 YAML 설정 다듬기 (Local & Test)

4-1. application-local.yml (로컬 환경)

이제 로컬 개발 환경 전용 설정을 수정해야 합니다. 기존에는 하이버네이트가 테이블을 맘대로 주무르도록 ddl-auto: update가 설정되어 있었습니다.

변경 전:

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
    hibernate:
      ddl-auto: update # 삭제 대상

여기서 hibernate: 블록과 그 아래의 ddl-auto: update 두 줄을 과감하게 삭제해 줍니다. 이제 데이터베이스 스키마의 통제권은 JPA가 아닌 Flyway에게 넘어갔습니다. 이 설정을 삭제하면 공통 설정 파일에 정의되어 있을 ddl-auto: validate 설정을 자연스럽게 상속받게 됩니다.

이렇게 설정해 두면, 향후 개발자가 엔티티(Entity) 클래스에 필드를 하나 추가하고 무심코 앱을 띄웠을 때 JPA validate가 실패하게 되며 "마이그레이션 SQL 파일을 작성하세요!"라는 강력한 강제력을 얻을 수 있습니다.

4-2. application-test.yml (테스트 환경)

이전 'Flyway 도입 딜레마!' 포스팅에서 논의했던 '옵션 4(테스트 환경에서는 H2 유지 및 Flyway 비활성화)' 전략을 실제 코드로 반영할 시간입니다.

spring:
  datasource:
    url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1
    # ...
  flyway:
    enabled: false # H2와의 충돌을 막기 위해 비활성화
  jpa:
    hibernate:
      ddl-auto: create-drop

테스트 환경은 여전히 H2 인메모리 데이터베이스를 사용하며, JPA의 create-drop 기능으로 스키마를 생성합니다. PostgreSQL 방언으로 작성된 Flyway 마이그레이션 스크립트가 H2에서 실행되면 문법 오류로 충돌이 발생하므로, 테스트 프로필에서는 Flyway를 끄는(enabled: false) 것이 핵심입니다.

5. 대망의 부팅 검증: Flyway V1 적용 확인

의존성 추가부터 각 환경에 맞는 YAML 설정까지 모든 준비가 끝났습니다. 이제 실제로 애플리케이션을 부팅하여 우리의 V1__init.sql이 잘 적용되는지 두 눈으로 확인할 차례입니다.

가장 먼저, 혹시 모를 기존 데이터와의 충돌을 막기 위해 로컬 데이터베이스를 완전히 초기화해 줍니다. 터미널에서 다음 명령어를 실행합니다.

docker compose down -v
docker compose up -d postgres redis

볼륨까지 깨끗하게 삭제된 빈 데이터베이스가 준비되었다면, 통합 개발 환경(IDE)에서 local 프로필을 활성화하여 애플리케이션을 부팅합니다. 그리고 올라가는 콘솔 로그를 유심히 살펴봅니다.

성공적인 부팅 로그의 흐름

  1. Flyway 마이그레이션 실행: 로그 중간에 Flyway가 개입하여 V1__init.sql 스크립트를 실행하는 과정이 출력됩니다. Migrating schema "public" to version "1 - init" 같은 로그가 보인다면 Flyway가 정상적으로 테이블 23개를 만들어낸 것입니다.
  2. JPA Validate 검증 통과: Flyway의 작업이 끝나면 뒤이어 하이버네이트(Hibernate)가 작동합니다. 하이버네이트는 자바 코드에 작성된 엔티티(Entity) 구조와 데이터베이스에 생성된 테이블 구조가 완벽히 일치하는지 비교(Validate)합니다. 우리가 스크립트를 정교하게 다듬었기 때문에 에러 없이 조용히 넘어갈 것입니다.
  3. 부팅 완료: 최종적으로 Started ToktotApplication in X seconds 로그가 찍혔다면 완벽하게 성공한 것입니다.
반응형