Flyway란?
Flyway는 오픈소스 데이터베이스 마이그레이션 툴이다. 백엔드 시스템에서 데이터베이스 스키마를 변경하는데 굉장히 유용하게 활용할 수 있다.
Flyway를 알기 전, Flyway의 도입 없이 서비스 릴리즈를 한 상태였는데 요구사항 수정에 따른 유지보수 작업을 지속적으로 진행하면서 데이터베이스 스키마의 변경은 필수적이었다.
특히 릴리즈 이후에 production 환경(운영 DB)에는 데이터가 점차 쌓여가고 있는 상황이었고, 사용자의 데이터에 손상이 가지 않도록하며 데이터베이스 스키마를 변경하는 것은 처음 서비스를 운영해보는 입장에서 까다로운 부분이 있었다.
Flyway를 활용하기 이전에는 DataGrip을 활용해서 직접 데이터베이스에 접속하고 console에 직접 SQL 쿼리를 하나씩 날리며 수정 작업을 진행했었다. 사실 단순히 스키마를 변경하는 것은 어렵지 않은 일이다. 기존에 데이터가 존재하더라도 테이블 사이의 관계, 테이블 안의 컬럼을 잘 고려해서 SQL 쿼리를 잘 작성한다면 크게 문제가 될 일은 없다.
하나 중요한 문제가 됐던 부분은 SQL 쿼리를 실행시키고 서버의 CI/CD가 한 번 돌아가기까지 시간 간격동안, 서비스는 이용 불가능한 상태가 됐다. 즉, 소스 코드의 형상 관리 시점과 데이터베이스의 형상 관리 시점을 동일하게 가져가는 것이 필요했다.
개발 환경
Server | Java - Spring Boot |
Database | MySQL 8.0.36 |
Cloud Infra | Elastic Beanstalk |
CI/CD | Github Actions |
현재 내가 운영하고 있는 서비스는 Spring Boot 기반의 서버, MySQL을 활용한 데이터베이스, Github Actions와 Elastic Beanstalk을 활용해서 CI/CD, 인프라를 구축해둔 상태이다. 또한, local, dev, prod 환경 3개로 크게 나누어 서버와 데이터베이스를 관리하고 있다.
이런 상황에서 DB에 직접 쿼리를 날려 스키마를 수정하고, Github Actions를 통해 서버를 재배포하면 DB가 수정되고 서버가 재배포가 완료되는 시점까지 운영하고 있는 서비스는 정상적으로 작동하지 않았다. 그렇다면 이게 CI/CD를 구축한 의미 자체가 없어져 버린다고 생각했다. 그리고, 매번 local, dev, prod 환경 모두를 손수 관리할 수도 없는 노릇이었다.
결론적으로 로컬 환경에 존재하는 데이터베이스, 테스트 서버의 데이터베이스, 프로덕션의 데이터베이스가 모두 개별적으로 돌아가고 있기 때문에, JPA에서 변경되는 엔티티의 구조는 다른 배포 환경에서도 좋은 방법을 통해 관리 및 반영이 되어야한다.
그래서! Flyway를 도입하기로 결정했다. Flyway를 활용하면 CI/CD가 돌아가고 서버가 재배포될 때, DB에 대한 스키마 변경도 한번에 같이 이루어져서 앞서 발생했던 문제가 해결될 수 있었다.
서버 설정
# build.gradle
dependencies {
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
}
# application.yml
flyway:
enabled: true
baseline-on-migrate: true
baseline-version: 0
Migration Script 규칙
Flyway migration은 Versioned Migrations, Undo Migrations, Repeatable Migrations총 3가지이다. Prefix의 알파벳이 마이그레이션을 지정한다. 기본적으로 작은 숫자의 Version부터 큰 숫자의 버전 순서대로 실행된다.
Versioned Migrations
Flyway의 핵심 기능으로 마이그레이션 스크립트의 최신 버전과 현재 데이터베이스의 스키마 버전을 비교하고, 차이점이 있다면 마이그레이션 스크립트를 순차적으로 실행하여 최신 스키마로 업데이트를 진행한다. 그렇기 때문에 마이그레이션 스크립트를 추가할 때에는 항상 최신 마이그레이션 스크립트의 버전보다 큰 숫자로 버전을 설정해야합니다.
Undo Migrations
Flyway Teams라는 유료 버전에서 사용이 가능하다.
Repeatable Migrations
모든 마이그레이션 스크립트가 실행된 이후 실행되는 스크립트이며 Repeatable Migrations 끼리는 description 순서대로 실행된다. 1회실행되며, 파일이 변경되어 체크섬이 변경되면 반복해서 실행된다.
Flyway는 경로 기준으로 작동한다.
Spring Boot 파일 안에서 마이그레이션 스크립트는
/resources/db/migration에 존재하는 sql 파일 기준으로 작동한다.
만약 내가 릴리즈 이전에 Flyway에 대해서 알고 있었다면, V1__init.sql 파일을 통해서 새로운 테이블을 모두 생성했을 것이다. 그리고 아래 이미지와 같이 1.0 버전을 시작으로 스키마에 대한 관리가 가능해진다.
릴리즈 이후 기존 테이블과 데이터가 존재하는 경우라면?
baseline-on-migrate: true
baseline-on-migrate는 기본 값이 false이다. (false인 경우) 기존 스키마가 없어야 정상적으로 실행이 완료된다.
baseline-on-migrate를 true로 설정하면 기존의 데이터베이스 스키마를 Flyway의 버전 관리 아래로(초기 버전 설정) 가져올 수 있다.
baseline-version: 0
그리고 baseline의 버전이 0인 이유는 위의 baseline-on-migrate가 true인 설정만 들어가 있으면 flyway_schema_history내의 version 컬럼이 1부터 시작한다. 그래서 V1__Add_XXX_Column.sql처럼 Version 1부터 시작할 수 없다. (사소한 불편)
위 설정을 모두 적용하고 실행을 하면, 기존 테이블이 존재한 상태에서 flyway를 통해 형상 관리가 가능해진다.
References
https://documentation.red-gate.com/fd/why-database-migrations-184127574.html
Why database migrations - Flyway - Product Documentation
Why database migrations Page last updated 24 May 2023 Published 16 November 2022 Why database migrations? First, let's start from the beginning and assume we have a project called Shiny and its primary deliverable is a piece of software called Shiny Soft t
documentation.red-gate.com
https://parkmuhyeun.github.io/woowacourse/2023-08-06-flyway
실제 서비스 운영 중 DB 스키마가 변경되면 어떡하지?
실제 서비스 운영 중 DB 스키마가 변경되면 어떡하지? 06 Aug 2023 in woowacourse on Woowacourse, Flyway, Database What if the database changes while the service is running?이전 프로젝트들에서 배포 후에는 DB 스키마를 변
parkmuhyeun.github.io
https://hudi.blog/dallog-flyway/
달록의 데이터베이스 마이그레이션을 위한 Flyway 적용기
이 글은 우아한테크코스 4기 달록팀의 기술 블로그에 게시된 글 입니다. Flyway 란? Flyway는 오픈소스 데이터베이스 마이그레이션 툴 입니다. 데이터베이스 마이그레이션 툴이란 데이터베이스의
hudi.blog