본문 바로가기
ETC/etc

[인프라] Flyway 데이터베이스 마이그레이션 툴

by 그적 2022. 11. 9.

프로젝트를 진행하면서 사용한 데이터베이스 마이그레이션 툴인 "Flyway"를 소개하려고 한다.

 

시스템을 운영하거나 개발하면서 DB 버전 업그레이드, 테이블 및 컬럼 변경 등의 상황이 발생한다.

그때마다 로컬 환경, 테스트 환경, 배포 환경 등에서 동일한 DB 스키마를 가져가야 하는데, 이때 Flyway를 통해 DB 변경 이력을 관리할 수 있고 단순히 스프링 어플리케이션을 다시 구동시키기만 하면 변경된 스키마가 디비에 적용된다.

 

목차

1. 사용하려면 알아야 할 기본 내용

2. Flyway 다운로드

3. Flyway 사용 방법

4. 꿀팁

 

 

사용하려면 알아야할 기본 내용 (필수!)

1. Flyway는 작성된 SQL 기반, JAVA 기반, Script 기반 등 다양한 방법으로 DB에 마이그레이션 될 수 있다.

해당 포스팅에서 사용할 방법은 SQL 기반으로 마이그레이션을 진행하는 방법이다.

 

공식 홈페이지를 보니까 사실상 자바 기반도 SQL문을 자바 코드에 작성하는 걸 보니 그냥 SQL로 진행했다.

DDL 변경, 단순한 CRUD를 진행하기 위해서는 SQL 기반으로 진행하고, 재계산(?)과 같은 복잡한 데이터 변경 등이 진행될 수 있는 마이그레이션이 발생할 것 같다면 자바 기반을 추천한다.

 

2. 작성할 SQL 파일을 담아야 할 경로는 classpath: 에 존재하면 된다.

네이밍 규칙에 맞는 파일들을 자동으로 찾아서 반영해주는 것 같지만, classpath: db/migration 해당 경로를 추천한다.

 

3. JPA Entity 클래스와 SQL 파일은 동시에 변경되어야 한다.

Entity에 칼럼 하나가 추가되거나 삭제되었다면, SQL 문에서 ALTER TABLE로 동일 칼럼을 추가하거나 삭제해주자.

만약 데이터가 들어있는 상태에서 칼럼을 추가했다면 아무 데이터도 들어가 있지 않고, 칼럼을 삭제했다면 데이터들이 모두 날아간다. 따라서 칼럼을 추가한다면 디폴트 값을 설정해 SQL을 작성하자.

 

새로운 Entity 클래스를 생성하거나 삭제했다면, SQL 문에서도 CREAT TABLE, DROP TABLE을 해준다.

Entity 클래스를 수정했다면 반영해주는 것이 필수이다. 안 그러면 스프링 구동도 실패한다.

 

4. 반영할 SQL 파일은 Flyway 파일 네이밍 규칙을 따라야 한다.

  • Prefix (접두사) : 대문자 V - 버전 지정 / 대문자 U - 실행 취소 / 대문자 R - 반복
  • Version (버전) : 점(.)이나 언더바(_)를 이용해 버전을 지정해준다.
  • Seperator (구분) : 언더바 두번(__)은 필수이다.
  • Description (설명) : 어떤 내용이 반영되었는지 알기 쉽게 작성한다.
  • Suffix (접미사) : .sql 

(ex) V1__init.sql 

(ex) V2_1__init.sql

(ex) V2_2__init.sql

 

5. Flyway이 적용되었다면 DB에 flyway_schema_history 테이블이 생성된다.

마지막 success 칼럼이 t 로 되어있다면 정상적으로 반영된 것이다.

 

 

Flyway 다운로드

필자가 사용한 버전은 아래와 같으나 https://mvnrepository.com/artifact/org.flywaydb/flyway-core 에서 원하는 버전을 찾아서 복붙하도록 하자.

gradle

implementation group: 'org.flywaydb', name: 'flyway-commandline', version: '6.4.2'

application.yml

spring:
  flyway:
    enabled: true
    out‑of‑order: true
    baseline-on-migrate: true

 

 

Flyway 사용 방법

Entity 클래스에서 ORM으로 자동으로 생성해주는 테이블명, 컬럼명, 데이터 타입을 그대로 따라야 한다.

간단하게 설명하면

Entity 클래스명을 Notice라고 할 경우, ORM을 통해 생성되는 테이블명은 notice이다.

Entity 클래스명을 NoticeAttachement라고 할 경우, ORM을 통해 생성되는 테이블명은 notice_attachement이다.

 

Entity 칼럼을 String picturePath; 라고 할 경우, ORM을 통해 생성되는 칼럼은 picture_path VARCHAR(255); 이다.

Entity 칼럼을 LocalDateTime dateTime; 라고 할 경우, ORM을 통해 생성되는 칼럼은 date_time TIMESTAMP; 이다.

Entity 칼럼을 LocalDate date; 라고 할 경우, ORM을 통해 생성되는 칼럼은 date DATE 이다.

 

결론은!

1. JAVA 코드 상에서 카멜 형식은 데이터베이스에서 언더바(_)로 들어간다.

2. JAVA 타입과 매핑되는 데이터베이스 타입을 찾아보면서 작성해야 한다.

정리된 사이트 : https://docs.oracle.com/cd/E19501-01/819-3659/gcmaz/

 

 

 

꿀팁

마이그레이션 버전이 충돌되면 안된다. 당연한 말이면서 무엇을 말하고 싶었냐면, 마이그레이션되는 sql을 작성하는 것을 팀원들과 공유해야 한다는 것을 말씀드리고 싶었다.

다른 사람이 V_1_3__update_table.sql을 만들어서 젠킨스가 연동된 깃에 코드를 반영했는데, 내가 그걸 늦게 안 상태에서 내 로컬에는 V_1_3__create_table.sql을 만들었다면 당연히 머지는 정상이지만, 내 로컬에서 빌드가 안되네? ㅎ

이러한 상황을 겪을 수도 있는 분들을 위해..

 

flyway_schema_history 테이블에 올라가 적용된 버전은 재작업이 이뤄지지 않는데, 그럼에도 내가 버전 3의 SQL 파일을 변경하고자 한다면, 데이터베이스를 버전 2 상태로 수동으로 되돌린 후, 그다음에 flyway_schema_history에 올라간 버전 3을 지워주면 된다. (위와 같은 상황이 아니면, 사실 버전을 새로 파는 것이 적합하다.)

 

 

Flyway를 사용하면서 ORM 공부가 됐었다.

자바 데이터 타입과 실제 디비 데이터 타입을 비교할 수 있었고, 카멜 형식은 디비에서 언더바로 표현되는 것을 알게 됐다.

 

여담이지만, Entity 클래에서 작성한 컬럼명 그대로 sql문에 작성하지 말자..

팀원이 빌드 안된다고 해서 코드를 봤는데.. 대문자 그대로 옮겨진 sql문을 보고 놀랐다.. 허허..

자바 카멜 형식은 언더바로.. SQL 상에서 대문자는 그냥 소문자로 들어가는 것도.. 꼭 기억하자..

댓글