Flyway 도입으로 정리한 데이터베이스 마이그레이션 관리

2026. 6. 1. 16:32·Programming/Spring

들어가며

 

 

회사 서비스 리뉴얼을 진행하면서 데이터베이스 변경 이력을 더 잘 관리할 필요가 생겼습니다.

 

스타트업에서는 요구사항이 자주 바뀝니다.
저희 회사도 예외는 아니었습니다.
기능이 바뀔 때마다 테이블과 컬럼도 계속 수정해야 했습니다.

 

처음에는 직접 SQL을 관리하며 대응했습니다.
하지만 변경이 쌓일수록 한계가 분명해졌습니다.
무엇을 언제 왜 바꿨는지 다시 찾는 일이 점점 어려워졌습니다.

 

그래서 데이터베이스 변경 이력을 더 체계적으로 관리하기 위해 Flyway를 도입하게 되었습니다.
이 글에서는 데이터베이스 마이그레이션의 기본 개념과 Flyway를 선택한 이유, 그리고 우리 프로젝트에

어떻게 적용하려고 했는지를 정리해보겠습니다.

 

DB 마이그레이션이 필요한 이유

 

 

왜 DB 마이그레이션 관리가 필요했는가?

처음에는 수동으로도 충분하다고 생각했습니다.
필요한 SQL을 작성하고, 변경 사항을 따로 기록해 두면 된다고 봤습니다.

 

하지만 협업 과정에서 데이터베이스 구조 변경이 반복되면서 문제가 생기기 시작했습니다.
변경이 쌓일수록 현재 구조가 어떤 과정을 거쳐 만들어졌는지 파악하기 어려워졌고, 직접 기록하며 관리

하는 방식에도 점점 한계를 느끼게 되었습니다.

(회사 문서의 상당수를 나 혼자 관리하는 부분의 한계가 너무 명확했음.....)

 

특히 어떤 변경이 왜 들어갔는지, 지금의 스키마가 어떤 흐름으로 만들어졌는지를 추적하는 비용이 점점 커졌습니다.

결국 필요한 것은 단순한 SQL 실행이 아니라, 변경 이력을 일관된 방식으로 관리할 수 있는 기준이었습니다.

 

그래서 데이터베이스 마이그레이션 관리가 필요하다고 판단했고, 그 해결 방법으로 Flyway를 도입하게 되었습니다.

 

데이터베이스 마이그레이션이란?

Flyway를 이야기하기 전에, 먼저 데이터베이스 마이그레이션이 무엇인지부터 짚고 넘어갈 필요가 있었습니다.


Flyway는 결국 데이터베이스 변경 이력을 관리하기 위한 도구이기 때문에, 먼저 데이터베이스 마이그레이션

이라는 개념 자체를 이해해야 도입 이유도 더 자연스럽게 받아들일 수 있다고 생각했습니다.

 

데이터베이스 마이그레이션은 데이터베이스 구조나 데이터를 변경하고, 그 변경 과정을 이력으로 관리

하는 방식을 의미합니다.

 

예를 들어 새로운 기능이 추가되면서 테이블을 생성하거나, 기존 테이블에 컬럼을 추가하거나, 인덱스

를 생성하는 작업이 모두 마이그레이션에 포함됩니다.

또 단순한 구조 변경뿐 아니라, 기존 데이터를 새로운 구조에 맞게 보정하거나 옮기는 작업도 넓은 의미

에서는 마이그레이션이라고 볼 수 있습니다.

 

중요한 점은 단순히 데이터베이스를 수정하는 것에 있지 않습니다.
어떤 변경이 언제 적용되었는지, 어떤 순서로 반영되었는지, 그리고 현재 구조가 어떤 과정을 거쳐 만들

어졌는지를 함께 관리하는 것이 핵심입니다.

 

즉, 데이터베이스 마이그레이션은 단순한 SQL 실행이 아니라, 데이터베이스 변경 이력을 체계적으로 관

리하는 방법이라고 볼 수 있습니다.

 

DB 마이그레이션 도구와 Flyway 선택 이유

DB 마이그레이션 도구에는 어떤 것들이 있을까?

저희는 그전까지 별도의 기준 없이 데이터베이스를 수정해왔습니다.
필요한 변경이 생기면 직접 수정하고, 필요한 경우에만 내용을 공유하는 방식이었습니다.

 

처음에는 이 방식으로도 큰 문제가 없어 보였습니다.
하지만 구조 변경이 반복되고 협업이 늘어나면서, 점점 현재 데이터베이스가 어떤 과정을 거쳐 지금의

구조가 되었는지 파악하기 어려워졌습니다.

 

특히 어떤 변경이 언제 들어갔는지, 어떤 SQL이 반영되었는지, 그리고 지금의 스키마가 어떤 흐름으로

만들어졌는지를 일관되게 추적하기가 쉽지 않았습니다.
변경 이력을 사람이 기억하거나 문서로만 관리하는 방식에는 분명한 한계가 있었습니다.

 

결국 필요한 것은 단순히 데이터베이스를 수정하는 방법이 아니라,
변경 이력을 기준에 맞게 남기고, 순서대로 관리할 수 있는 체계였습니다.

 

이런 이유로 데이터베이스 마이그레이션 도구를 검토하게 되었습니다.
대표적으로 많이 언급되는 도구는 Flyway와 Liquibase입니다.

 

두 도구 모두 데이터베이스 변경 이력을 관리할 수 있다는 공통점이 있습니다.
다만 관리 방식에는 차이가 있습니다.

  • Flyway는 SQL 파일을 기준으로 마이그레이션을 관리합니다.
  • Liquibase는 XML, YAML, JSON, SQL 등 다양한 형식으로 변경 이력을 표현할 수 있습니다.

즉, 두 도구 모두 목적은 같지만, 변경 이력을 관리하는 방식과 도입 복잡도에는 차이가 있습니다.

왜 Flyway를 선택했는가?

여러 도구 중에서 이번에 Flyway를 선택한 이유는 비교적 분명했습니다.

 

저희에게 필요한 것은 복잡한 기능보다,
반복되는 데이터베이스 구조 변경을 명확한 기준 아래에서 관리할 수 있는 방식이었습니다.

 

Flyway는 실제로 실행할 SQL을 그대로 파일로 남길 수 있고,
어떤 변경이 어떤 순서로 적용되는지도 함께 관리할 수 있습니다.
즉, 지금 저희에게 가장 필요했던 변경 이력의 기록, 추적, 버전 관리에 더 잘 맞는 도구라고 판단했습니다.

 

또 SQL 기반이라 이해하기 쉽고, 도입 부담이 비교적 적다는 점도 장점이었습니다.
처음부터 복잡한 추상화보다, 우선 데이터베이스 변경을 일관된 방식으로 남길 수 있는 구조를 만드는

것이 더 중요하다고 봤습니다.

 

결국 Flyway를 선택한 이유는 단순합니다.

 

지금 저희에게 필요했던 것은 새로운 도구 자체가 아니라,
누가 무엇을 수정했는지, 어떤 변경이 어떤 순서로 들어갔는지를 더 효율적으로 관리할 수 있는 기준이었

기 때문입니다.

 

Flyway의 기본 개념

 

 

이전에는 Flyway를 선택한 이유를 정리 했다면, 이제는 Flyway가 실제로 어떤 방식으로 동작하는지 살펴볼 차례입니다.

 

공식 문서에서는 Flyway를 데이터베이스 변경을 버전 관리하고, 데이터베이스 배포를 더 안전하고 쉽게 자동화할 수 있도록 

돕는 도구라고 설명합니다. 

 

즉, 단순히 SQL을 실행하는 도구가 아니라, 데이터베이스 변경을 이력과 순서 기준으로 관리할 수 있게 해주는 도구에 가깝습니다.

 

Flyway는 어떻게 동작할까?

 

 

Flyway는 먼저 데이터베이스에서 flyway_schema_history 테이블을 확인합니다.

공식 문서에 따르면, 빈 데이터베이스라면 Flyway는 이 테이블을 새로 생성하고 이를 기준으로 변경 이력을 추적합니다.

 

그 다음 Flyway는 파일시스템이나 애플리케이션의 클래스패스에서 마이그레이션 파일을 찾습니다.

그리고 각 파일을 버전 번호 기준으로 정렬한 뒤 순서대로 적용합니다. 마이그레이션이 하나씩 적용될 때마다 

flyway_schema_history 테이블도 함께 갱신됩니다.

 

즉, Flyway의 기본 동작은 다음과 같이 이해할 수 있습니다.

  • 이력 테이블을 확인한다
  • 마이그레이션 파일을 찾는다
  • 버전 순서대로 적용한다
  • 적용 결과를 다시 이력 테이블에 기록한다

결국 핵심은 데이터베이스 변경을 순서와 이력 중심으로 관리한다는 점입니다.

 

Versioned Migration

Flyway에서 가장 기본이 되는 개념은 Versioned Migraion입니다.

 

Versioned Migration은 버전이 있는 마이그레이션 파일입니다.

테이블 생성, 컬럼 추가, 익덱스 생성처럼 한 번 적용되고 이력으로 남아야 하는 변경을 관리할 때 사용합니다.

 

예를 들면 아래와 같은 형태입니다.

V20260601_1015__create_users_table.sql
V20260601_1030__add_status_to_users.sql

 

공식 문서에서는 이 테이블을 데이터베이스 변경을 추적하기 위한 테이블로 설명합니다.

Flyway는 각 마이그레이션이 적용될 때마다 이 테이블을 갱신하고, 이를 기준으로 현재 어느 버전까지 반영되었는지

를 판단합니다.

 

즉, Versioned Migration은 데이터베이스가 어떤 순서로 변경되어 왔는지를 기록하는 방식이라고 이해하면 됩니다.

 

flyway_schema_history

Flyway를 이해할 때 빠질 수 없는 개념이 flyway_schema_history 테이블입니다.

 

 

공식 문서에서는 이 테이블을 데이터베이스 변경을 추적하기 위한 테이블로 설명합니다.

Flyway는 각 마이그레이션이 적용될 때마다 이 테이블을 갱신하고, 이를 기준으로 현재 어느 버전까지 반영되었는지를 판단합니다.

 

즉, 이 테이블이 있기 때문에 다음과 같은 관리가 가능해집니다.

  • 어떤 마이그레이션이 이미 적용되었는지 확인
  • 새로 추가된 migration만 pending 상태로 판별
  • 적용 순서를 일관되게 유지
  • 변경 이력을 데이터베이스 내부에서 추적

수동으로 SQL을 실행하던 방식과 가장 크게 다른 점도 바로 여기 있습니다.
단순히 “수정했다”에서 끝나는 것이 아니라, 무엇이 언제 반영되었는지 기준점이 생긴다는 점입니다.

 

Flyway가 관리하는 대상은 무엇일까? 

공식 문서에서는 Flyway가 데이터베이스의 구조 변경뿐 아니라 데이터 변경도 새로운 migration으로 관리할 수 있다고 합니다.

즉, DDL 뿐 아니라 DML도 필요하다면 마이그레이션으로 함께 다룰 수 있습니다.

 

이 말은 결국 Flyway가 단순히 테이블 생성 도구가 아니라,

데이터베이스에 반영되는 변경 자체를 버전 단위로 관리하는 도구라는 뜻에 가깝습니다.

 

예를 들어 다음과 같은 작업이 모두 대상이 될 수 있습니다.

  • 테이블 생성
  • 컬럼 추가
  • 인덱스 생성
  • 제약조건 변경
  • 데이터 보정
  • 기준 데이터 추가

다만 모든 데이터 작업을 무조건 Flyway에 넣는 것은 아닙니다.
대량 데이터 이전이나 장시간 실행이 필요한 작업은 별도 배치나 운영 스크립트로 분리하는 편이 더 안전합니다.
그래도 적어도 “무엇을 언제 반영했는가”를 기준으로 남겨야 하는 작업이라면 Flyway가 좋은 출발점이 됩니다.

Spring Boot에 Flyway 적용하기

앞에서 Flyway의 기본 개념을 정리했다면, 이제는 이를 실제 프로젝트에 어떻게 적용할지 살펴볼 차례입니다.

 

저희 회사 프로젝트는 Spring Boot 기반으로 구성되어 있기 때문에,

이번 도입 과정도 단순한 예제 수준이 아니라 현재 레포 구조에 맞춰 정리할 필요가 있었습니다.


그래서 이 파트에서는 일반적인 사용법보다는, 실제로 저희 레포에 적용하려고 하면서 어떤 기준으로

구조를 잡았는지를 중심으로 정리해보려고 합니다.

의존성 추가

저희 회사 서비스는 build.gradle 기반의 Spring Boot 프로젝트이기 때문에, 이 글에서도 그 구조

를 기준으로 설명하겠습니다.

 

Flyway를 적용하기 위해서는 먼저 관련 의존성을 추가해야 합니다.
저희 서비스는 MySQL을 사용하고 있어 flyway-core와 flyway-mysql을 함께 추가했습니다.

dependencies {
	implementation 'org.flywaydb:flyway-core'
	implementation 'org.flywaydb:flyway-mysql'
}

 

의존성 추가 자체는 어렵지 않습니다.

 

다만 중요한 것은 여기서부터 데이터베이스 구조 변경을 더 이상 수동 수정이나 기억에 의존하지 않고,

Flyway 기준으로 관리하기 시작한다는 점입니다.

 

즉, 의존성 추가는 시작점일 뿐이고,
이후에는 마이그레이션 파일을 어떤 규칙으로 관리할지와 설정을 어떻게 맞출지가 더 중요했습니다.

 

마이그레이션 파일명 규칙 정리

 

 

다음으로 정리해야 했던 것은 마이그레이션 파일명 규칙이었습니다.

 

Flyway는 파일명을 기준으로 마이그레이션을 인식하고 적용 순서를 판단하기 때문에, 처음부터 일관된

규칙으로 맞추는 것이 중요했습니다.


특히 저희는 아직 어떤 환경에서도 Flyway를 실행하지 않은 상태였기 때문에, 이 시점에서 파일명 규칙

을 정리하는 것이 가장 안전하다고 판단했습니다.

 

초기에는 V001__... 같은 단순 증가 방식도 생각할 수 있었습니다.
하지만 추후 협업 가능성까지 고려하면 날짜시간 기반 형식이 더 적절하다고 봤습니다.

 

그래서 아래와 같은 형태를 기준으로 잡았습니다.

VyyyyMMdd_HHmm__description.sql

 

예를 들면 아래와 같습니다.

V20260601_1015__add_user_status.sql

 

이 방식을 선택한 이유는 분명했습니다.

  • 언제 생성된 변경인지 바로 파악할 수 있다
  • 여러 사람이 동시에 작업하더라도 버전 충돌 가능성을 줄일 수 있다
  • 변경 흐름을 시간 기준으로 따라가기 쉽다

즉, 파일명 규칙은 단순한 형식 통일이 아니라,
변경 이력을 더 쉽게 추적하기 위한 기준이었습니다.

 

마이그레이션 디렉토리 구조

파일명 규칙을 정리한 뒤에는, 이 파일들을 어디에서 어떻게 관리할지 디렉토리 구조도 함께 고민해야

했습니다.

 

처음에는 모든 SQL을 한곳에 모아둘 수도 있겠다고 생각했습니다.
하지만 실제로는 Flyway가 직접 적용해야 하는 SQL과, 운영 중 수동으로 확인하거나 별도로 실행해야

하는 SQL을 같은 위치에서 관리하는 것은 적절하지 않다고 판단했습니다.

 

그래서 Flyway 대상 파일과 운영성 작업을 분리해서 관리하는 방향으로 정리했습니다.

 

현재 기준으로는 아래와 같은 구조를 생각했습니다.

src/main/resources/db/migration
ops/db/backfill
ops/db/online
ops/db/runbooks

 

이 구조에서 각 디렉토리의 역할은 다음과 같습니다.

  • src/main/resources/db/migration
    Flyway가 직접 읽고 적용하는 마이그레이션 파일을 관리하는 위치
  • ops/db/backfill
    대량 데이터 이전이나 백필 작업처럼 별도 실행 전략이 필요한 SQL을 관리하는 위치
  • ops/db/online
    운영 중 수동 대응이 필요한 작업이나 온라인 DDL 관련 문서를 관리하는 위치
  • ops/db/runbooks
    배포 절차, 실행 순서, 체크리스트 같은 운영 문서를 관리하는 위치

저희는 이 구분이 중요하다고 판단했습니다.
모든 SQL을 Flyway에 넣는 것이 아니라, Flyway가 관리해야 하는 변경과 운영성 작업을 역할에 맞게

나누는 것이 실제 레포 관리에 더 적합했기 때문입니다.

application-local.yml 설정 정리

Flyway를 도입하면서 설정 파일도 함께 정리할 필요가 있었습니다.
특히 application-local.yml에서 datasource와 Flyway가 어떤 값을 바라보는지 명확하게 맞

추는 작업이 중요했습니다.

 

Flyway를 붙였다고 해도, 애플리케이션이 보는 데이터베이스와 Flyway가 마이그레이션을 적용하는 데

이터베이스가 다르면 바로 문제가 생깁니다.
겉으로는 로컬에서 잘 실행되는 것처럼 보여도, 실제로는 다른 DB에 마이그레이션이 반영되는 상황

이 생길 수 있기 때문입니다.

 

그래서 저희는 local 환경 기준으로도 datasource와 Flyway가 같은 환경변수를 바라보도록 정리하려

고 했습니다.
이 과정에서 중요했던 것은 단순한 설정 추가가 아니라, Flyway가 실제로 어느 DB에 적용되는지 명확

히 보이게 만드는 것이었습니다.

 

즉, application-local.yml에서는 다음과 같은 점을 함께 정리할 필요가 있었습니다.

  • datasource와 Flyway가 같은 DB를 바라보는지
  • 환경변수 참조 방식이 일관된지
  • Flyway 활성화 여부가 명확한지
  • 마이그레이션 위치가 올바르게 지정되어 있는지

결국 이 설정 정리는 Flyway 사용 여부를 결정하는 설정이 아니라,
Flyway를 실제로 안전하게 동작시키기 위한 기준을 맞추는 작업에 가까웠습니다.

ddl-auto 설정과 역할 분리

마지막으로 함께 정리해야 했던 것은 Hibernate의 ddl-auto 설정이었습니다.

 

기존처럼 ddl-auto=update에 의존하면 엔티티 변경에 따라 데이터베이스 구조가 자동으로 바뀔 수

있습니다.


하지만 그렇게 되면 실제 데이터베이스는 바뀌는데, 정작 Flyway에는 그 변경 이력이 남지 않는 문제가 생깁니다.

 

저희가 Flyway를 도입하려는 이유는 단순히 데이터베이스를 수정하기 위해서가 아니었습니다.
무엇이 언제 왜 바뀌었는지를 이력으로 남기기 위해서였습니다.

 

그래서 이 시점부터는 역할을 분리해서 보는 것이 중요했습니다.

  • Flyway는 데이터베이스 구조 변경 이력을 관리한다
  • Hibernate/JPA는 애플리케이션과 엔티티 매핑을 담당한다

즉, 데이터베이스 구조를 실제로 변경하는 기준은 Flyway로 가져가고, JPA는 그 구조를 사용하는 쪽

에 집중하도록 역할을 나누는 방향이 더 적절하다고 판단했습니다.

 

결국 ddl-auto 설정을 그대로 두는 것은 단순한 편의 문제가 아니라,
Flyway 도입 목적과 충돌할 수 있는 부분이었기 때문에 함께 정리해야 하는 항목이었습니다.

마무리

이번에 Flyway를 정리하면서 가장 크게 느낀 점은, 데이터베이스 변경도 결국 관리 가능한 형태로 남아

야 한다는 점이었습니다.

 

지금 단계에서 저희가 한 일은 Flyway를 완전히 활용한 운영이라기보다,
레포 안에서 데이터베이스 변경 이력을 관리하기 위한 기준과 정책을 먼저 정리한 것에 가깝습니다.
의존성 추가부터 파일명 규칙, 디렉토리 구조, 설정 정리까지 하나씩 기준을 맞추면서 이제야 도입의 출

발점을 만든 셈입니다.

 

앞으로는 이 기반 위에서 실제 마이그레이션 작성 방식, baseline 전략, 운영 중 활용 방법처럼 Flyway

를 더 효율적으로 사용하는 방법도 계속 정리해보려고 합니다.
이번 글이 도입을 위한 기준을 세우는 기록이었다면, 다음 글에서는 실제 활용과 운영 관점에서 더 구체

적으로 다뤄볼 생각입니다.

 

https://documentation.red-gate.com/fd/redgate-flyway-documentation-138346877.html

 

Redgate Flyway Documentation - Redgate Flyway - Product Documentation

Experience Flyway Autopilot: Test our Flyway tool’s capabilities in under 30 minutes with ease! Get everything installed and configured on your own infrastructure—no hassle, just results. Spin up personalized test environments based on your schema and

documentation.red-gate.com

 

'Programming > Spring' 카테고리의 다른 글

@Component, @Controller, @Service, @Repository의 차이점은 무엇일까  (1) 2026.04.10
'Programming/Spring' 카테고리의 다른 글
  • @Component, @Controller, @Service, @Repository의 차이점은 무엇일까
Code with yc
Code with yc
아직 부족하지만 조금씩 배우고자 하는 Back-end 개발자
  • Code with yc
    성장하는 개발 노트
    Code with yc
  • 전체
    오늘
    어제
    • 분류 전체보기 (30)
      • Programming (6)
        • Java (3)
        • Spring (2)
        • Python (0)
        • Go (0)
        • JavaScript (1)
        • React (0)
      • Data Infra (1)
        • Database (1)
        • Mysql (0)
        • Redis (0)
        • PostgreSQL (0)
        • ClickHouse (0)
        • RabbitMQ (0)
        • Kafaka (0)
      • DevOps (2)
        • Amazon AWS (2)
        • CI & CD (0)
        • Docker & k8s (0)
        • Oracle OCI (0)
      • AI (0)
      • Git (2)
      • CS (4)
        • Architecture (0)
        • Tools (3)
      • 회고 (9)
        • 일상 회고 (9)
        • 자격증 (0)
        • 책 후기 (0)
      • Side Project (6)
        • Yule Studio (1)
        • Synapse Talk (0)
        • Go utility box (1)
        • Spring Sandbox (2)
        • Front Sandbox (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • git
  • 공지사항

    • 새로운 브랜치로 이사 왔습니다!
  • 인기 글

  • 태그

    aws profile
    lg유플러스부트캠프
    Spring Sandbox
    회고록
    Java 16
    Secret Access Key
    회고
    Hephaistos
    JavaScript
    프론트엔드 공부
    한 달 회고록
    GIT
    회사 기술 고민
    Java
    회사 서비스 리뉴얼
    사이드 프로젝트
    AWS CLI 사용법
    AWS configure
    AWS CLI 인증
    부족한 점
    성장하자
    db
    한 주 회고
    front-end
    Tools
    회사
    커리어로그
    Access key
    게으름 극복하기
    백엔드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Code with yc
Flyway 도입으로 정리한 데이터베이스 마이그레이션 관리
상단으로

티스토리툴바