인프라

Flyway 적용기

newwisdom 2021. 8. 15. 16:50
반응형

2021-07-21 작성

Flyway란?

  • 오픈 소스 데이터베이스 마이그레이션 도구 
  • 버전별 DB 스크립트 파일을 열거 해 두면 알아서 SQL 파일을 수행해 주고 DB 변경 이력에 대한 관리를 해 주는 녀석

Flyway와 JPA

spring.jpa.hibernate.ddl-auto

  • create, update, create-drop 은 prod 환경에서 절대 비추
  • validate
    • Entity 와 테이블의 정합성이 맞는지 검증한다. (안맞으면 오류를 냄)
    • 배포 환경에서는 validate 옵션으로 테이블이 변경될 시 애플리케이션을 가동시키지 않고 수동으로 테이블 변경사항을 맞추어야 한다.

현재 우리는 DEV, PROD 두 개의 환경에서 MariaDB를 사용하고 있다.
엔티티가 변경될 때마다 해당 변경 사항을 일일히 쿼리를 날려서 변경하는 것은 굉장히 번거롭고, 소스코드는 git 상에서 형상 관리를 하지만 DB에는 그런 툴을 쓰고 있지 않더라.

여기서 Flyway를 쓰면,
DB 스크립트는 Flyway에만 의존하여 이 마이그레이션 스크립트만으로 테이블이 관리되어 엔티티 변경 후 validate 옵션일 지라도 애플리케이션이 멀쩡히 구동된다! 

 

흐름

  • Flyway를 의존성에 추가한다.
  • resources/db/migrationV + 버전 + __ + 설명.sql 이라는 규칙으로 파일명을 작성
    • ex) V1__init.sql
    • V2_changeColumn.slq
    • V1스크립트에는 Flyway를 적용할 시점의 테이블 히스토리 (DDL)을 작성
  • Flyway Plugin 이 flyway_schema_history 내부 스키마를 이용하여 파일 버전을 관리하는데, 
    DB랑 처음 커넥션이 일어나면 flyway_schema_history 라는 테이블 생성
  • checksum을 확인하여 해당 history가 적용 되었는지 확인하고 안되었다면 해당 sql을 실행

 

build.gradle 추가

implementation('org.flywaydb:flyway-core:6.4.2')

 

application.yml 추가

spring:
  jpa:
      hibernate:
          ddl-auto: validate
      generate-ddl: false
       
  flyway:
      enabled: true // flyway로 형상 관리를 하겠다~
      baseline-on-migrate: true // 이 시점의 DB의 DDL이나 테이블이 아예 날라가도 기록해놓아야 하는 sql을 기록

 

베이스라인(V1) 스크립트 추가 

flyway로 db를 관리할 시점에서, 모든 테이블의 ddl을 기록한 베이스라인 스크립트(V1)를 추가한다. 

애플리케이션 실행

이후 애플리케이션을 실행 시키고 연결 시킨 DB를 확인해보면 이렇게 flyway_schema_hisotry 테이블이 생긴다.

엔티티 변경

이제 엔티티 필드를 변경해본다.

  • (우리가 겪은 문제는 Long에서 String으로 바꾸는 이슈였지만, 그 이후 flyway 실습을 위해 다시 String을 Long으로 변경하는 실습)

여기서 그냥 애플리케이션을 다시 구동한다면 아래와 같은 오류가 발생한다.

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory

 

validate옵션일 경우 엔티티와 DB 엔티티 구조가 달라서 다음과 같이 컬럼을 찾을 수 없다고 에러가 발생한다.

이제부터 변경되는 테이블의 이력을 스크립트로 관리해 나가면 된다! 

변경된 스크립트(V2) 추가

엔티티 변경으로 인한 테이블의 변경된 컬럼 반영 쿼리를 V2 스크립트에 다음과 같이 적어준다.

alter table `user` MODIFY soscial_id bigint(20);

 

다시 애플리케이션 실행

애플리케이션을 다시 실행시키면 validate 옵션에 엔티티가 변경되어도 플라이웨이가 스크립트를 읽어 변경 사항을 DB에 적용하기 때문에 정상작동하며, 테이블도 이에 따라 알맞게 변경된다. 

flyway_schema_hisotry

DB를 확인하면 추가로 작성한 스크립트 이력이 기록된걸 확인할 수 있고, 성공 유무도 확인할 수 있다.

 

실습하면서 내가 겪은 오류

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Validate failed. Migration Checksum mismatch for migration 1

 

베이스 라인 스크립트가 현재 존재하는 테이블들의 DDL과 다를 경우

그냥 초기 테이블을 생성할 때 나왔던 DDL만 베이스라인으로 지정한 V1 스크립트에 박으면 되겠지 했지만, 
기존 테이블에 데이터가 존재하는 경우 해당 테이블의 DDL을 까보면 다음과 같이 auto_increment값도 지정되어 있는 것을 확인할 수 있다.

CREATE TABLE `tech` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_61sbcb7t9ej3nihlu4wtynsio` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

때문에 해당 내용들도 다함께 베이스라인 스크립트에 반영해주어야 한다.

참고 자료

반응형