| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- GCP
- dockercompose
- CS
- 공통모듈
- 트러블슈팅
- github actions
- 백엔드면접준비
- springboot
- GitHub Packages
- PostgreSQL
- Java 8
- 분산시스템
- MSA
- 아키텍처
- 인프라
- 자바
- java
- gradle
- 마이그레이션
- SpringCloud
- Database
- docker
- Flyway
- ci/cd
- 멀티모듈
- 컨테이너
- 마이크로서비스
- 마이크로서비스아키텍처
- 도커
- 백엔드
- Today
- Total
NYO_O
Flyway 도입 딜레마! 테스트 환경 H2와 PostgreSQL 충돌 해결 과정 본문
지난 시간 'JPA ddl-auto는 이제 그만! 실무에서 쓰는 DB 마이그레이션 툴 비교 (Flyway vs Liquibase)' 포스팅에서는 실무에서 DB 마이그레이션 툴을 사용해야 하는 이유와 각 툴의 장단점을 알아보았는데요.
2026.05.20 - [기술 스택] - JPA ddl-auto는 이제 그만! 실무에서 쓰는 DB 마이그레이션 툴 비교 (Flyway vs Liquibase)
그 결론에 따라, 현재 진행 중인 Spring Boot 프로젝트에 직관적이고 가벼운 Flyway를 도입하기로 결정했습니다. 하지만 기분 좋게 설정 파일을 작성하고 마이그레이션 스크립트를 추가하자마자 예상치 못한 벽에 부딪히고 말았습니다. 바로 '테스트 환경'과의 충돌이었죠.
오늘은 Flyway 도입 과정에서 마주친 H2 데이터베이스와의 충돌 문제, 그리고 이를 해결하기 위해 어떤 선택지들을 두고 고민했는지 그 생생한 트러블슈팅 과정을 공유해 보려고 합니다.
1. 문제의 발단: PostgreSQL과 H2의 불협화음
현재 제 프로젝트의 데이터베이스 구성은 다음과 같이 나누어져 있습니다.
- 운영(Prod) / 로컬(Local) 환경: PostgreSQL
- 테스트(Test) 환경: H2 Database (In-Memory)
Flyway를 세팅하면서 첫 번째 마이그레이션 스크립트(V1__init.sql)를 작성했습니다. 운영 환경에 맞추어 PostgreSQL 문법과 고유 기능들을 사용해 스크립트를 짰습니다.
문제는 테스트 코드를 실행할 때 터졌습니다. 테스트 환경에서는 H2가 구동되는데, Flyway가 이 H2 데이터베이스에 PostgreSQL 문법으로 쓰인 스크립트를 밀어 넣으려고 하니 문법 오류를 뱉어내며 모든 테스트가 실패해 버린 것입니다.
2. 해결을 위한 4가지 선택지와 딜레마
이 충돌을 어떻게 해결할 수 있을까요? 관련 자료를 찾아보며 크게 4가지 선택지를 두고 각각의 장단점을 꼼꼼히 비교해 보았습니다.
옵션 1. Testcontainers 도입 (실무 표준 방식)
실제 PostgreSQL 컨테이너를 도커(Docker)로 띄워서 테스트하는 방식입니다.
- 장점: 운영 환경과 100% 동일한 DB를 사용하기 때문에 마이그레이션 스크립트가 깨지는 현상을 완벽히 방지할 수 있습니다. "테스트 통과 = 운영 통과"라는 가장 높은 신뢰도를 줍니다.
- 단점: Docker 환경이 필수적이고, 첫 컨테이너를 띄우는 데 약간의 시간이 소요됩니다. 당장 도입하기엔 설정이나 의존성 추가 등 작업 규모가 커집니다.
옵션 2. 테스트 환경에서 Flyway 비활성화 (가장 빠른 회피)
테스트 환경 설정 파일(application-test.yml)에서만 Flyway를 끄고, 기존처럼 H2의 ddl-auto 기능을 사용하는 방식입니다.
- 장점: 코드를 거의 건드리지 않고 가장 빠르게 문제를 해결할 수 있습니다. 테스트 속도도 여전히 빠릅니다.
- 단점: Flyway를 도입한 목적을 절반쯤 잃어버리게 됩니다. 스크립트에 문제가 있어서 실제 운영 배포가 실패할 상황이라도, 테스트는 통과해 버리는 케이스가 발생할 수 있습니다.
옵션 3. H2용 마이그레이션 스크립트 분리
운영용(PostgreSQL)과 테스트용(H2) 스크립트 폴더를 나누어 별도로 관리하는 방식입니다.
- 장점: Docker 없이도 테스트 환경에서 마이그레이션 검증이 가능합니다.
- 단점: 스키마가 변경될 때마다 두 가지 버전의 SQL을 모두 작성해야 합니다. 둘 중 하나라도 동기화를 하지 않을 경우 시스템 안정성이 무너지게 되며, 불필요한 유지보수 비용만 증가합니다.
옵션 4. 현재는 H2 유지 + 추후 Testcontainers 도입
당장은 옵션 2처럼 테스트에서 Flyway를 비활성화하여 운영 스키마 관리에만 집중하고, 추후 '통합 테스트'를 본격적으로 작성할 때 옵션 1(Testcontainers)로 완전히 넘어가는 단계적 접근 방식입니다.
3. 나의 선택: 단계적 도입 (옵션 4 -> 옵션 1)
저는 "우선 H2를 유지하며 테스트에서 Flyway를 끄고, 추후 통합 테스트 작성 시점에 Testcontainers를 도입한다"는 4번 옵션을 선택했습니다.
이런 결정을 내리게 된 가장 큰 이유는 '현재 테스트 코드의 상태' 때문이었습니다.
현재 제 프로젝트에는 기본으로 생성되는 contextLoads() 테스트 단 하나뿐입니다. 즉, 당장 복잡한 설정을 거쳐 Testcontainers를 완벽하게 구축해 둔다고 해도, 그 인프라가 보호해 줄 실질적인 통합 테스트 코드가 없는 상황이었죠.
어차피 도입할 거라면 한 번에 세팅하는 게 낫지 않나 생각할 수도 있습니다. 하지만 Flyway 도입, Testcontainers 세팅, 통합 테스트 작성이라는 큼직한 주제들을 한 번에 묶어서 진행하면 작업 단위가 너무 커지고 학습의 초점이 흐려질 위험이 높았습니다.
그래서 작업의 단위를 다음과 같이 명확하게 나누기로 했습니다.
- 현재 단계: 운영/로컬 환경의 스키마 버전 관리(Flyway)를 안정적으로 안착시키는 데 집중한다.
- 다음 단계: 유의미한 통합 테스트를 작성하는 시점에 맞춰 Testcontainers를 도입한다.
4. 실제 적용 코드
방향이 정해졌으니 코드를 수정해 볼까요? 테스트 환경의 설정 파일(application-test.yml 또는 application-test.properties)에 아래와 같이 설정을 추가해 테스트 구동 시에는 Flyway가 개입하지 않도록 처리했습니다.
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=PostgreSQL
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
flyway:
enabled: false # 테스트 환경에서는 Flyway 비활성화
이렇게 설정해 두면 운영 환경에서는 Flyway가 스키마를 안전하게 관리해주고, 테스트 환경에서는 가벼운 H2와 ddl-auto를 이용해 개발을 이어갈 수 있습니다.
마치며
이번 트러블슈팅을 통해, 무조건 '가장 완벽한 기술(Best Practice)'을 당장 한 번에 도입하는 것만이 정답은 아니라는 것을 다시 한번 느꼈습니다. 현재 프로젝트의 상황과 리소스를 고려해 단위를 쪼개고 단계적으로 개선해 나가는 것이 오히려 실용적인 엔지니어링 접근이 될 수 있음을 배웠습니다.
물론 "테스트는 통과했는데 운영 서버 부팅은 실패하는" 상황을 막기 위해서 추후 운영 DB와 동일한 테스트 환경이 필수적입니다.
'DevOps > Flyway' 카테고리의 다른 글
| Flyway 실전 도입기 4편: Spring Boot 연동부터 마이그레이션 검증까지 완벽 가이드 (0) | 2026.05.20 |
|---|---|
| Flyway 실전 도입기 3편: 하이버네이트가 만든 스키마의 5가지 문제점과 V1 스크립트 완벽 정제 (0) | 2026.05.20 |
| Flyway 실전 도입기 2편: pg_dump로 순수 스키마 SQL 추출하기 (0) | 2026.05.20 |
| Flyway 실전 도입기 1편: 로컬 DB 초기화 및 V1 스키마 생성하기 (0) | 2026.05.20 |