Develop/database

flyway. DB 형상관리 및 다양한 기능을 제공! 재택근무 시 유용해요! 2탄

에디개발자 2020. 11. 24. 09:00
반응형

이전 글 ( flyway. DB 형상관리 및 다양한 기능을 제공! 재택근무 시 유용해요! 1탄 )에서 flyway에 대해서 간단하게 알아보았습니다. 

이번글에서는 실제 환경에서 어떻게 사용하는 지 소스기반으로 정리하겠습니다.

모든 소스는 github에 올려두었습니다.

 

 

요즘 코로나로 인해 재택근무가 많아지는 상황입니다. 저도 재택근무를 한번 해봤는데 집에서 로컬 db 환경으로 작업해야하는 상황이 있었습니다. 물론 슬랙으로 동료분들과 db 변경사항을 공유했지만 누락되는 내용도 있었고 각자 로컬 db 스키마 정보가 달라서 작업하는데 어려움이 있었습니다. 이럴경우 아주 유용한 것이 flyway입니다. ( 이전 글과 동일한 내용입니다. )

 

소스와 함께 정리하도록 하겠습니다. 이 글에서 다루는 Flyway 사용 방법은 plugin, application.yaml 두가지로 나누었습니다.

실제 환경을 구성해보겠습니다.

 

Flyway plugin 환경

  1. build.gradle 세팅
  2. 경로에 맞게 sql 파일을 생성
  3. gradle plugin 실행

build.gradle

plugins {
	id 'org.springframework.boot' version '2.3.4.RELEASE'
	id 'io.spring.dependency-management' version '1.0.10.RELEASE'
	id 'java'
	id "org.flywaydb.flyway" version "7.2.0"  // 1)
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.flywaydb:flyway-core'  // 2)
	implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.2'


	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'mysql:mysql-connector-java'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

flyway {  // 3)
	url = 'jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&characterEncoding=utf8'
	user = 'root'
	password = 'dladydxo0417!'
	// driver = 'com.mysql.jdbc.Driver'  기본으로 등록되어있다.
}

1) flyway에서 제공하는 기능을 편리하게 사용할 수 있는 플러그인입니다. 플러그인을 세팅하면 intellij 우측에 gradle tap에서 기능을 쉽게 사용할 수 있습니다.

 

flyway 관련 기능을 쉽게 사용할 수 있다.

2) flyway를 사용하기 위한 디펜던시 세팅입니다.

3) flyway 관련 설정입니다.  ( flyway document를 참조해주세요. )

 

resources 세팅

flyway는 경로 ( /resources/db/migration ) 에 존재하는 sql 파일을 기준으로 작동합니다. sql 파일 네이밍 룰은 이전글을 참조해주세요 :)

V1__init.sql 파일을 생성

V1__init.sql

먼저 처음 테이블을 생성한다고 가정하고 테이블을 2개 생성하는 쿼리를 만들었습니다.

-- auto-generated definition
create table staff
(
    id       bigint auto_increment
        primary key,
    age      int          null,
    name     varchar(255) null,
    store_id bigint       null
);

-- auto-generated definition
create table store
(
    id      bigint auto_increment
        primary key,
    address varchar(255) null,
    name    varchar(255) null
);

 

flyway plugin 실행

gradle 탭에서 flywayMigrate를 실행하면 스키마에 테이블이 생성되는 것을 확인하실 수 있습니다.

staff, store 는 제가 생성하려던 것이 맞지만 flyway_schema_history는 flyway 내부적으로 생성된 history 테이블입니다. 자세하게 보면 제가 생성한 스크립트 파일명version 관리 및 설명 그 외 메타정보를 담고 있는 테이블입니다.

스크립트를 기준으로 관리하므로 sql 스크립트 파일은 절대 수정하시면 안됩니다. 

 

다음으로 테이블이 추가적으로 첫날엔 meta_info 테이블이 생겼고, 둘째날에 meta_info2 테이블이 생겼다고 가정해보겠습니다. 그럼 아래 그림과 같이 생성될 것입니다. ( version 정보는 소숫점도 가능합니다. )

-- auto-generated definition
create table meta_info
(
    id       bigint auto_increment
        primary key,
    meta_data      varchar(255)          null
);
-- auto-generated definition
create table meta2_info
(
    id       bigint auto_increment
        primary key,
    meta_data      varchar(255)          null
);

 

flywayMigrate 를 실행하면 경로에 있는 스크립트 파일과 실제 스키마 정보와 비교하여 변경내용을 추가해줍니다. 위 예제 기준으로는 스키마에 2개 테이블이 생성되고 history 테이블에 이력이 추가됩니다. ( V1은 추가되있으니 무시되겠죠? )

여기까지 plugin으로 flyway를 사용하는 방법에 대해서 알아보았습니다. 사용하기 정말 편리하네요!

 

application.yaml

다음으로는 application.yaml에 설정하여 tomcat을 띄울때마다 알아서 validation 체크하여 migrate 하는 설정을 살펴보겠습니다.

spring:
  profiles:
    active: local


--- #local
spring:
  profiles: local
  datasource:
    url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
    username: root
    password: dladydxo0417!!
    driver-class-name: com.mysql.jdbc.Driver

  jpa:
    database: mysql
    generate-ddl: false
    open-in-view: false
    hibernate:
      ddl-auto: none     # 항상 조심!!
  flyway:                 # flyway 설정
    enabled: true # 1)
    baseline-on-migrate: true # 2)
    baseline-version: 0 # 3)
    url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
    user: root
    password: dladydxo0417!! # 4)

1) flyway 사용 여부를 설정합니다.

 

2) baseline 설정을 합니다.

  - 스키마에 history 테이블이 생성되지 않고 이 설정을 false로 하면 history 테이블을 찾을 수 없다고 에러가 발생합니다. 

  - migrate를 할때 history 테이블이 없다면 생성해주는 설정입니다.

 

3) baseline-version 을 몇부터 세팅할지 세팅입니다. 

 

4) flyway가 바라보면 datasource 정보입니다.

 

application 실행

실행 후 의미있는 로그를 살펴보겠습니다. 

2020-11-23 08:59:48.427  INFO 70124 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 6.4.4 by Redgate
2020-11-23 08:59:48.739  INFO 70124 --- [           main] o.f.c.internal.database.DatabaseFactory  : Database: jdbc:mysql://localhost:3306/testdb (MySQL 8.0)
2020-11-23 08:59:48.789  INFO 70124 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.022s)
2020-11-23 08:59:48.822  INFO 70124 --- [           main] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table `testdb`.`flyway_schema_history` ...
2020-11-23 08:59:48.873  INFO 70124 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `testdb`: << Empty Schema >>
2020-11-23 08:59:48.882  INFO 70124 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `testdb` to version 1 - init
2020-11-23 08:59:48.938  INFO 70124 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `testdb` to version 2 - create meta info table
2020-11-23 08:59:48.994  INFO 70124 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `testdb` to version 3 - create meta2 info table
2020-11-23 08:59:49.029  INFO 70124 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 3 migrations to schema `testdb` (execution time 00:00.161s)

간단히 정리하자면..

  1. flyway database 설정한다.
  2. sql 스크립트 파일 3개 마이그레이션을 성공했다.
  3. 스키마 히스토리 테이블을 생성한다.
  4. 마이그레이션을 어떻게 실행했는지 보여준다.
  5. 성공했다. :)

 

주의할 사항

  • flyway plugin 중 baseline이 있다. 이 플러그인을 깨끗한 스키마에서 실행하면 flyway_schema_history을 생성하고 baseline row를 생성합니다. 보시는 것과 같이 version이 이미 1이 할당되었습니다. 그런데 여기서 V1__init.sql를 생성하고 실행한다면?? 실행되지 않습니다. 이미 동일한 버전의 파일이 있을 경우 무시됩니다. 이 부분을 주의해주시면 됩니다.

  • flyway clean은 정말 왠만하면 사용하지말자. 플러그인 실행하면 clean하겠습니까? 이런거 없습니다. 바로 스키마를 깨끗하게 비워줍니다. 정말 주의해주시요!

 

결론

이렇게 하면 재택근무할 때 각자의 로컬 디비에서 스키마를 세팅해놓고 변경될때마다 공지로 다들 1번 테이블 컬럼정보 변경되었습니다. 수정해주세요. 2번테이블 컬럼도 변경. 3번 테이블 추가.... 을 해도 되지 않는 아주 유용한 툴입니다 :) 

디비 형상관리는 flyway에게 맡기고 열심히 개발에 몰두 할 수 있습니다!!

 

 

 

 

 

 

 

 

 

반응형