Intellij) JDBC 프로젝트 (3) Flyway 도입하기

Intellij) JDBC 프로젝트 (3) Flyway 도입하기

Simple JDBC Project (kor)
(1) 
Java, DB 설치 + Docker Compose로 쉽게 해 보기
(2) 프로젝트 생성, Postgresql 컨테이너 게시
(3) Flyway 도입하기
(4) JDBC 연결하기

Flyway란 무엇입니까?

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

더 자세한 설명이 궁금하다면 <Flyway: JDBC 프로젝트에 Flyway 적용하기\>를 참고하세요.
(https://letsdev.hashnode.dev/flyway-onto-jdbc-kor)


Flyway 적용하기

적용하고 나서 이해하는 것이 빠를 것입니다.

Flyway를 사용하기 전에 Main 클래스 작성

  • 추천 package: com.example
package com.example;

public class Main {
    public static void main(String[] args) {

    }
}

의존성 라이브러리(Dependencies) 추가

build.gradle에서 dependencies를 찾아서 다음 느낌으로 추가해 줍니다. 추가해 주고 나면 반드시 우측 상단에 뜨는 코끼리(sync gradle 또는 refresh gradle 등으로 부름) 버튼을 누릅니다.

dependencis { // <<< 원래 적혀 있습니다.

    // ...

    // 다음 세 줄을 적당한 위치에 추가합니다. dependencies 중괄호 내부에 추가되어야 합니다.
    // db
    implementation 'org.postgresql:postgresql:42.7.3'
    implementation 'org.flywaydb:flyway-mysql:9.22.3'

    // ...
}

버튼은 다음처럼 코끼리 모양으로 생겼습니다. 실수로 닫았다면, IDE상에서 gradle 탭을 찾아 새로고침 모양을 눌러 줍니다. 이제부터 이 버튼이 보이면 당신은 누르고 싶게 됩니다. 항상 누르고 보십시오.

실수로 닫은 경우 누르는 버튼은 아래 그림 중 회전하는 화살표 쌍입니다. (gradle 탭을 열었을 때)

이로써 gradle이 의존성 라이브러리 목록을 다운로드받아 주며, 프로젝트에서 사용할 수 있습니다.

사용하기 편하도록 클래스를 생성

  • 추천 package: com.example.common.flyway.config

이 클래스는 외부에서 사용하기 위해서 일반화해 작성하는 것입니다. 따라서 데이터베이스 접속 정보(DB URL, DB username, DB password 등)는 외부에서 파라미터를 통해 입력하도록 설계합니다.

  • Data source: Flyway 마이그레이션을 적용할 데이터베이스를 말합니다. 접속 정보를 넣습니다.

  • Baseline on migrate: Flyway는 Flyway Schema History 테이블을 통해 DDL 히스토리를 관리합니다. 이 옵션을 true로 하면 Flyway Schema History 테이블이 없을 때 생성됩니다. 즉 Flyway를 처음 적용하는 환경이라면 켜 두어야 하는 옵션입니다.

package com.example.common.flyway.config;

import org.flywaydb.core.Flyway;

public class MyFlyway {
    private final Flyway flyway;

    public MyFlyway(String dbUrl, String username, String password) {
        flyway = Flyway.configuration()
                // 외부에서 전달받은(= 파라미터로 받은) DB 접속 정보를 넣습니다.
                .dataSource(dbUrl, username, password)
                .baselineOnMigrate(true)
                .load();
    }

    public void migrate() {
        flyway.migrate();
    }
}

메인 함수에서 확인해 보기

메인 함수에서는 위에서 만든 MyFlyway 클래스의 객체를 생성하여 사용합니다. 이때 DB 접속 정보를 MyFlyway의 생성자에 넣어 줄 필요가 있습니다.

우리의 DB 접속 정보는 다음과 같습니다.

DB URLDB USERNAMEDB PASSWORD
jdbc:postgresql://localhost:5442/demorootroot

이 내용을 그대로 MyFlyway 클래스의 생성자에 넣어 줍니다.

import com.example.common.flyway.config.MyFlyway;

public class Main {
    public static void main(String[] args) {
        // MyFlywy 인스턴스를 생성합니다.
        MyFlyway myFlyway = new MyFlyway(
                "jdbc:postgresql://localhost:5442/demo",
                "root",
                "root"
        );

        myFlyway.migrate();
    }
}

이제 애플리케이션을 실행할 때마다 Flyway를 실행하게 됩니다.

DB 접속 정보 상수 관리

  • 추천 package: com.example.common.support.db

메인 함수에서 리터럴 상수 대신 기호 상수를 사용할 수 있습니다. 이런 상수를 한 클래스에 작성합시다.

package com.example.common.support.db;

// 상속할 필요가 없는 클래스를 `final` 클래스로 사용합니다. (권장)
public final class DatabaseAccessConstants {
    public static final String DB_DRIVER_CLASS_NAME = "org.postgresql.Driver";
    public static final String DB_URL = "jdbc:postgresql://localhost:5442/demo";
    public static final String DB_USERNAME = "root";
    public static final String DB_PASSWORD = "root";

    // 생성자의 외부 사용을 막으면 불필요한 객체 생성을 방지할 수 있습니다. (권장)
    private DatabaseAccessConstants() {}
}

이제 이 상수들을 메인 함수에서 import 하여 사용합니다. 예시는 static import를 사용했습니다. IDE 설정에서 static import를 허용할 것인지 체크해 둘 수 있을 것입니다. 자주 사용하는 상수만 static한 임포트를 사용하고, 일반적인 경우 static한 import를 삼가는 것이 좋습니다.

import com.example.common.flyway.config.MyFlyway;

import static com.example.common.support.db.DatabaseAccessConstants.DB_PASSWORD;
import static com.example.common.support.db.DatabaseAccessConstants.DB_URL;
import static com.example.common.support.db.DatabaseAccessConstants.DB_USERNAME;

public class Main {
    public static void main(String[] args) {
        MyFlyway myFlyway = new MyFlyway(DB_URL, DB_USERNAME, DB_PASSWORD);
        myFlyway.migrate();
    }
}

Flyway로 테이블 만들기

우리는 DDL 파일을 만들 것입니다. 주로 CREATE, ALTER, DROP 등을 담은 SQL 파일을 뜻합니다.

Flyway는 클래스 패스에 db/migration이라는 폴더를 만들어 그 안에 DDL 파일을 관리해야 합니다. 표기로는 classpath:/db/migration 폴더입니다. 이중에서 스킴 자리의 classpath:는 대표적으로 resources 폴더가 있습니다. 그래서 다음 경로에 DDL 파일들을 모아 두면 됩니다.

  • DDL 파일 저장 경로: resources/db/migration 폴더

DDL 파일 만들기

우선 첫 번째 파일은 이 데이터베이스에 몇 가지 설정을 활성화하는 데 사용할 수 있습니다. 그렇게 해야 하는 것은 아닙니다. 첫 번째 파일부터 CREATE TABLE ...을 작성해도 됩니다.

이 예시 파일은 Postgresql에서 UUID를 활성화하는 예시입니다. (이번 프로젝트에서 실제 사용하진 않지만, Postgresql 사용 시 습관적으로 작성해 두면 좋습니다.)

  • 경로: resources/db/migration

  • 이름: V1_0_0__init_schema.sql (중간에 언더바 두 개가 연속으로 오는 것에 유의하세요.)

-- Enable UUID
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

두 번째 파일은 user 테이블을 만들 것입니다. 이때 user는 Postgresql에서 키워드이니, 큰따옴표를 앞뒤에 붙여서 식별자로서 사용한 것임을 명시합시다. (변수명, 테이블명, 컬럼명 등 우리가 마음대로 쓸 수 있는 이름들이 식별자입니다.)

  • 경로: resources/db/migration

  • 이름: V1_0_1__add_tb_user.sql (중간에 언더바 두 개가 연속으로 오는 것에 유의하세요.)

CREATE TABLE IF NOT EXISTS "user" (
    username                VARCHAR(255),
    password                VARCHAR(255),
    nickname                VARCHAR(255),

    status                  VARCHAR(255),
    created_at              TIMESTAMP               DEFAULT now(),
    updated_at              TIMESTAMP,

    CONSTRAINT pk_user PRIMARY KEY (username),
    CONSTRAINT uq_user_nickname UNIQUE (nickname)
);

COMMENT ON TABLE "user" IS '회원';
COMMENT ON COLUMN "user".username IS '사용자 ID';
COMMENT ON COLUMN "user".password IS '비밀번호';
COMMENT ON COLUMN "user".nickname IS '닉네임';
COMMENT ON COLUMN "user".status IS '계정 상태';
COMMENT ON COLUMN "user".created_at IS '생성일(가입일)';
COMMENT ON COLUMN "user".updated_at IS '최종 수정일';

Flyway의 파일 이름 규칙과 특징

V 파일 작성 양식 (Version 파일)

  • V버전__설명.sql 양식입니다.

  • 기본적으로 수정할 수 없는 파일입니다. 대신 개발자 PC 로컬 환경에만 적용되어 있는 버전 파일은 수정할 수 있고, 파일을 수정한 경우 로컬에서는 모든 테이블을 삭제하는 것이 편합니다.
    (어차피 모두 Flyway가 다시 만들어 주니까요.)

  • 구분자는 언더바 두 개(__)입니다. (버전 영역과 설명 영역을 구분하는 기호 묶음)

  • 버전은 V1_0_1, V1.0.1, V202401010000 등 다양한 양식을 사용할 수 있습니다.

R 파일 작성 양식 (Repeatable 파일)

  • R__설명.sql 양식입니다.

  • 파일이 수정될 때마다 Flyway가 다시 실행하는 파일입니다.

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

  • 구분자는 마찬가지로 언더바 두 개(__)입니다.


< Prev

(2) 프로젝트 생성, Postgresql 컨테이너 게시

Next >

(4) JDBC 연결하기