나만 모르고 있던 - Flyway (DB 마이그레이션 Tool)

flyway-logo-tm

2016년 00월 00일 서울 모처의 OO프로젝트 운영 배포현장

개발PL: 소스 운영 배포 합니다.

개발팀원: 네~

개발PL: 운영서버 배포 끝냈습니다.

개발팀원 : PL님 계속 NullpointerException 에러 떨어지고 있는데요...

개발PL :  "이리 저리~ 확인! 확인!" 헉!  길동아 이번에 추가된 상태코드 운영DB에 추가 안했냐?

홍길동 : 허어어어억... 개발DB까진 다 insert했는데... 제가 깜빡했습니다.

개발PL : 아... 이런 시베리안 헉스키 같은 @#$!%#$%!@%!@#%!@%! ...

우리는 이런 상황을 심심치 않게 직접 겪거나 지인들의 술,담배 자리 에피소드로 듣곤 한다.

단순 상태코드 몇개 추가 되는거야 일이 아니겠지만

만약 다수의 table 변경이나 data 추가, 삭제, 변경등을 처리하지 않았다고 한다면....

모르긴 몰라도 이 글을 읽는 분들도 이런 당황스런 순간을 한번 쯤은 겪어 봤을거라고 생각한다.

단편적인 얘기였지만 database를 다루면서 발생할 수 있는 골치아픈 작업과 문제점을 해결 해 줄 수 있는것이 바로 flyway (플라이 웨이) 이다.

소개

Flyway는 오픈소스 Database 마이그레이션 Tool이다.

왜 database 마이그레이션이 필요할까?

일반적으로 대 부분의 Project는 다음 그림처럼 다수의 배포 환경을 가지고 있다.

environments

참여한 각 개발자의 Local환경, 통합환경, 테스트 환경, 그리고 운영환경 정도로 구성되어 있고

개발자 Local에서 구현되어 테스트 되어진 프로그램의 Source Code는 형상관리 Tool(git, svn, etc...)을 이용하여 변경이력을 관리하고 있지만 database는 어떠한가? 각 개발자의 Local환경에서 개발시 사용되는 database의 schema 변경에 대한 마땅한 이력관리 방법이 존재하지 않는다.

즉 Local개발환경의 database 변경사항을 다른 배포단계의 database에 적용 하려면 어쩔 수 없이 배포전 변경사항을 수동으로 처리 해야줘야 한다. 이런 수동적인 처리방법 때문에 글의 첫 부분과 같은 에피소드들이 발생하게 되는것이다.

flyway는 이런 수동관리의 불편함을 손 쉽게 해결해주는 Tool이다.

동작방식

flyway가 schema와 data변경사항을 어떻게 관리하는지 동작방식에 대해 알아보자.

emptydb

우리는 두개의 마이그레이션(database schema변경 sql문이 기록된) 을 가지고 있고 우리의 database는 비워져 있다.

우리가 flyway를 통해서 마이그레이션을 처리하고자 할때 대상 database에 SCHEMA_VERSION (flyway가 변경이력을 관리하는 meta table) table이 존재하는지 판단하고  없다면 flyway가 자동으로 신규로 생성한다.

emptyschemaversion

SCHEMA_VERSION 이 생성되거나 기 존재한다면 flyway는 마이그레이션을 위해 지정된 파일(sql or Java)을 지정된 classpath에서 탐색하여 버전 순서대로 실행한다. 

migration-1-2

마이그레이션이 실행되고 나면 SCHEMA_VERSION table에 실행이력을 저장하게 된다.

schemaversion-1-2

여기서 중요한것은 flyway는 마이그레이션 대상파일의 version을 파일명을 통해서 구분하게 되는데 파일명 작성규칙은 다음과 같다.

sqlmigrationnaming

File Naming

  • prefix: default로 V 는 버전 마이그레이션, R은 반복 마이그레이션용 접두사이다. 반드시 V또는 R로 시작해야만 flyway가 인식함.
  • version: version은 버전 마이레이션에서만 사용되며 숫자와 Dots(점)이나 underscore(언더바) 조합으로 구성. (반복 마이그레이션에서 (version을 명시하면 filename제약 위반으로 에러 발생함)
  • separator: 설명부분을 구분하기 위한 구분자이며 반드시 undersocre(언더바)를  2개( __  ) 써야함.
  • description: 이 부분은 schema_version테이블에 저장시 설명으로 사용됨.
  • suffix: 확장자 기본은 .sql

SQL Syntax

migration 대상파일에 사용할 수 있는 sql script구문은 다음과 같다.

  • Single 또는 multi-line 구문 지원.
  • 유연한 placeholder 치환 지원.
  • Single( -- ) 또는 multi-line ( /* */ ) 주석 지원.
  • Database별 SQL구문 확장 지원 ( PL/SQL, T-SQL, ...)

Sample Script

스크린샷-2016-11-15-오전-1-01-29

Command (실행명령)

flyway는 총 6개의 명령을 지원하며 이를 실행하는 방법은 Execution Mode에 따라 달리 사용된다.

  • Migrate : database 마이그레이션. command-migrate
  • Info : 모든 마이그레이션 상세정보를 출력한다. command-info
  • Validate : database에 적용된 마이그레이션 정보의 유효성을 검증한다. command-validate
  • Baseline : flyway로 관리하기 이전에 database가 기 존재시 해당 database를 flyway baseline 으로 설정할 수 있다. command-baseline
  • Repair : 메타 데이터 테이블 문제를 해결하기 위해 사용하는데 두가지 용법이 존재한다. - 실패한 마이그레이션 항목 제거( DDL 트랜잭션을 지원하지 않는 database에만 해당) - 적용된 마이그레이션의 체크섬을 사용 가능한 마이그레이션의 체크섬으로 재정렬. command-repair
  • Clean : database의 schema_version테이블 포함한 모든 objects(tables, views, procedures, ...)를 drop시킨다.  ( production(운영환경) 에선 절대 실행 금지 ) command-clean

Execution Modes (실행방법)

실행방법에는 총6가지를 지원한다.

  • Command-line : 콘솔에서 명령을 입력하여 실행하는 방법
  • API(Java/Android) : Java로 작성된 프로그램내에서 API를 이용하여 실행.
  • Maven : Maven에 통합하여 실행.
  • Gradle : Gradle에 통합하여 실행.
  • Ant : Ant에 통합하여 실행.
  • SBT : SBT(Scala 빌드 도구)에 통합하여 실행.

형상관리를 사용하는 Project에서는 maven, gradle에 flyway를 통합하여 실행하는것이 Build Phase별로 Command를 선택 실행/관리 있으므로 추천한다.  필자는 maven에 flyway를 통합하여 실행하는 예제를 다뤄보겠다.

Maven기반 실행

  1. pom.xml에 flyway관련 의존성 & build 설정 추가

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <dependencies>
       <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>1.4.193</version>
       </dependency>
    </dependencies>
    <build>
       <plugins>
          <plugin>
             <groupId>org.flywaydb</groupId>
             <artifactId>flyway-maven-plugin</artifactId>
             <version>4.0.3</version>
             <configuration>
                <url>jdbc:h2:tcp://192.168.56.101:9092/~/test,h2.version=1.4.193</url>
                <user>sa</user>
                <locations>
                   <location>classpath:db/migration</location>
                </locations>
             </configuration>
          </plugin>
       </plugins>
    </build>

  2. 마이그레이션 sql파일 생성.

    필자는 ${project_root}/src/main/resources/db/migration 하위에 생성했으나, 위치는 classpath or filesystem 기반으로 읽을 수 있는 어떤 경로라도 상관없음.

    스크린샷-2016-11-15-오후-4-51-10

  3.  console에서 migration 실행

    mvn flyway:migrate 를 실행하면 db/migration 하위에 .sql파일들이 version에 따라 실행됨을 확인 할 수 있다.

    스크린샷-2016-11-15-오후-4-55-52

  4. migration 확인

    mvn flyway:info 를 통해서 확인시 SCHEMA_VERSION에 실행한 마이그레이션 이력이 등록된걸 확인 할수 있다.

    스크린샷-2016-11-15-오후-4-57-41

마치며

무슨 말이 필요한가?

테스트해보면 flyway의 간결함과 강력함을 직접 느낄 수 있을 것이다.


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.