Skip to main content

Command Palette

Search for a command to run...

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

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

Hello, I am Korean. Welcome, visitor. You are very cool. 안녕하세요, 저는 한국어입니다. 방문자여 환영한다. 당신은 매우 시원해.

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 연결하기

More from this blog

클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? #42

이 아티클은 깃허브 nettee-space 조직의 디스커션 #42 항목을 옮겨 온 것입니다.관련 논의: nettee-space/backend-sample-hexagonal-simple-crud/discussions/42 Question: 클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? 여러 소스들을 접하면서 VO 객체 등에 Serializable를 구현받는 것을 많이 접했습니다. 저희 헥사고날(스터디 팀내 2단계 ...

Feb 7, 2025
클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? #42

개념 2. JWT 액세스 토큰의 생성과 전달, Stateful한 리프레시 토큰의 생성, 전달, 보존

이전 글에서 정리에 꽤 힘을 뺐기 때문에, 이번 글에서는 서두와 부연설명을 줄이고 필요한 정보를 담아 전달해 보겠습니다. JWT 액세스 토큰 JWT 액세스 토큰은 인가에 직접 사용되는 토큰이고, stateless 하다는 장점이 있었습니다. 액세스 토큰의 생성 JWT(JSON Web Token)로 생성합니다. 비밀번호 인증 등 자격 검토 후 JWT를 발급합니다. JWT는 헤더, 페이로드, 시그니처 세 영역을 점(.) 기호로 구분한다고 했습니다....

Oct 23, 2024
개념 2. JWT 액세스 토큰의 생성과 전달, Stateful한 리프레시 토큰의 생성, 전달, 보존

Merge Simpson의 매너 있고 다정한 한국어 개발자 블로그

37 posts