Flyway: JDBC 프로젝트에 Flyway 적용하기

Flyway: JDBC 프로젝트에 Flyway 적용하기

Flyway는 DDL 버전 관리를 위해 사용할 수 있는 DB Migration 도구입니다.

🇰🇷 Kor
🌐 Eng: Coming Soon
🇯🇵 Jap: すぐに参ります。

Flyway란?

Flyway는 DDL 버전 관리를 위해 사용할 수 있는 DB Migration 도구입니다. 자바 애플리케이션을 실행하기만 해도 생성되어 있는 데이터베이스 테이블들과 시드 데이터, 더미 데이터를 경험하세요!

우리가 마치 Git을 통해 소스 코드의 형상 관리를 하듯이, Flyway로 DDL 파일(.sql)의 형상 관리를 할 수 있습니다. 그리고 DB 마이그레이션 도구답게, 우리가 작성해 둔 SQL 파일들을 자동으로 실행해 데이터베이스 스키마의 변경을 관리하죠.

또한 Flyway를 통해서 우리는 JPA 등 ORM에 종속되는 데이터베이스 사용이 아니라, 데이터베이스에 종속되는 ORM 사용을 추구할 수 있습니다! 예를 들어, JPA를 적용한 프로젝트에서, JPA로부터 DDL 책임을 없애고 Flyway에게 그 역할을 넘길 수 있습니다.

i.e.

  • DDL: Flyway로 관리

  • DML: JPA로 관리 (Auto-DDL 기능을 꺼 두거나(none)validate로 함.)

또한 데이터베이스 스키마의 변경 이력을 알 수 있기 때문에 개발자도 DBA도 모두 편하게 일하기 위한 구성을 할 수 있습니다!

JDBC 프로젝트에 Flyway 추가

저는 예시에서 빌드 도구를 사용합니다. 빌드도구가 없다면 IDE(이클립스, STS, 인텔리제이 등)를 통해 라이브러리를 인식시켜 주면 됩니다. IDE도 안 쓴다면 class path를 적절히 추가하세요.

Gradle 사용 시 의존성 추가

두 가지가 모두 되어 있어야 합니다. 다음 중 JDBC는 이 글에서 직접 다루지 않습니다.

  • JDBC 라이브러리 추가

  • Flyway 라이브러리 추가

MySQL 사용 시

  • group name: org.flywaydb

  • artifact name: flyway-mysql

  • version: 9.22.3

dependencis {
    implementation 'org.flywaydb:flyway-mysql:9.22.3'
}

MySQL이 아닌 데이터베이스 사용 시

  • group name: org.flywaydb

  • artifact name: flyway-core

  • version: 9.22.3

dependencis {
    // 여러 DB 버전 호환을 위해 아직 9 버전대를 추천합니다.
    implementation 'org.flywaydb:flyway-core:9.22.3'
}

버전은 초심자의 시행착오를 줄이기 위해 9 버전대로 권장했습니다. 자신의 데이터베이스와 Flyway의 버전 호환성을 스스로 찾아서 적용해 보아도 됩니다. (예를 들어 Postgresql 14 버전은 Flyway 코어 10 버전과 호환되지 않음.)

빌드도구 없이 IDE에서 구성 시

실행 환경 관련 설정에 Add Libraries ...를 해야 합니다. 실행할 때 라이브러리를 인식할 수 있어야 하기 때문에 주로 실행 환경에 밀접한 설정에 있습니다! (IDE 없이 사용하는 경우는 class path에 실행 시 라이브러리 경로를 입력해 주어야 하거든요.)

커스텀 Flyway 클래스 작성

필요한 곳에서 org.flywaydb.core.Flyway 객체를 바로 사용해도 되지만, 우리는 기본적으로 깔끔한 설계 관점을 위해서 가급적 역할에 따라 클래스를 구분해 두고 사용합시다.

import org.flywaydb.core.Flyway;

public class MyFlyway {
    private final Flyway flyway;

    public MyFlyway(String url, String username, String password) {
        flyway = Flyway.configuration()
                // DB 접속 정보
                .dataSource(url, username, password)
                // (Flyway 처음 적용 시 필요) Flyway 스키마 히스토리 테이블이 없다면 생성해 준다.
                .baselineOnMigrate(true)
                .load();
    }

    public void migrate() {
        // delegation (위임): 필드에 갖고 있는 객체가 이 클래스의 업무를 대행함.
        flyway.migrate();
    }
}

Flyway 실행

애플리케이션의 초기 동작으로 추가하는 것이 좋습니다. JDBC 라이브러리가 잘 추가되어 있어야 하고, Flyway 버전과 DB의 버전이 서로 호환되어야 합니다. DB 접속 정보가 올바른지 DB 접속 툴(MySQL Workbench, HeidiSQL, DBeaver, SQL Developer 등) 등 다른 접속 수단으로 확인해 보세요.

public static void Main {

    public static void main(String[] args) {
        MyFlyway flyway = new MyFlyway(
                "jdbc:로_시작하는_DB_URL",
                "DB사용자이름",
                "DB사용자암호"
        );

        flyway.migrate();

        // 이제 이곳에 다른 실행문을 작성하면 됩니다.
        // ex:
        //  MyApplication application = new MyApplication();
        //  application.run();
    }

}

참고: H2 데이터베이스 사용 시

H2 데이터베이스를 임베드로 사용하고 있다면, DB 접속 정보에 다음 옵션을 추가하는 것이 좋습니다. 복잡한 관리 방식을 사용하고 있지 않다면 필수로 넣어야 합니다.

// ex) String dbUrl = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
String dbUrl = DB_URL + ";DB_CLOSE_DELAY=-1";
  • ;DB_CLOSE_DELAY=-1은 애플리케이션이 돌아가는 동안 H2 데이터베이스의 수명을 유지합니다.

SQL 파일 만들어 두기

일반적으로 IDE가 관리하는 프로젝트라면, resources 폴더가 class path로 등록되었을 것입니다.

Flyway를 적용하려면 resources 폴더 하위에 db/migration 폴더를 만들어 두고, DDL을 작성해 둔 SQL 파일을 나열하면 됩니다.

Flyway 파일 규칙

구분자는 __(언더바 두 개)입니다. V로 시작하는 파일이 우리가 주로 관심을 갖게 되는 파일입니다.

  • V버전__설명.sql: DDL 작성 파일입니다. 기본적으로 수정할 수 없는 파일입니다. 대신 개발자 PC 로컬 환경에만 적용되어 있는 버전 파일은 수정할 수 있고, 파일을 수정한 경우 Flyway 히스토리 내용과 안 맞기 때문에 차라리 모든 테이블을 삭제한다고 생각하는 것이 편리합니다. (어차피 모두 Flyway가 다시 만들어 주니까요.)

    • ex: V1.0.1__add_tb_user.sql

    • ex: V1_0_1__add_tb_user.sql

    • ex: V202401011030__add_tb_user.sql

  • R__설명.sql: 주로 시드데이터 작성에 사용합니다. 로컬에서는 더미 데이터 삽입에도 사용합니다.

    • 파일 내용이 바뀔 때마다 Flyway가 실행합니다.