ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot Flyway 적용하기(flyway, h2 DB test 에러 해결)
    프로젝트/선착순 쿠폰 발급 시스템 2023. 4. 30. 00:01

    개요

    DB 형상관리를 위해 Flyway를 도입하고자 합니다.

     

    Flyway란?

    git을 통하여 우리가 코드를 관리하는 것의 DB 버전입니다.

    데이터베이스의 DDL의 이력을 쌓아 DDL이 어떻게 변화되었는지 관리하는 툴으로 사용할 수 있습니다.

    실무에서는 local prod등 실제 서버와 개발환경이 나뉘어 있습니다.

    이때 local 에서 변경한 DB의 스키마나 데이터를 운영 DB에 반영할 때 누락하는 것을 막기 위해 사용합니다.

     

    Flyway Convention

    • 기본 위치는 main/reousrces/db/migration (커스텀 설정 가능)
    • Prefix
      • V(Versioned)
        • 현재 버전을 새로운 버전으로 업그레이드
      • U(Undo)
        • 현재 버전을 이전 버전으로 되돌리는 경우
      • R(Repetable)
        • 버전에 관계 없이 매번 실행하는 경우
    • Verison
      • V와 U는 버전을 명시해야 한다.
      • R은 버전을 명시할 필요가 없다.
      • 새로 스크립트를 작성한다면 스크립트의 버전을 이전보다 꼭 높게 적어야 한다.
        • 이전에 1.0이였다면 이후에는 2.0을 사용해야 한다.
        • 낮은 숫자를 쓰면 Flyway가 이를 무시한다
    • separator
      • 무조건 __(언더바 2개)로 작성해야 한다.
    • Description
      • 단어 구분은 _(언더바 1개)로 작성해야 한다.

     

    build.gradle 의존성 추가

    dependencies {
    	//flyway 의존성 추가
    	implementation ("org.flywaydb:flyway-core:6.4.2")
    }

     

    application-infra.yml 설정 추가

    spring:
      flyway:
        enabled: true
        baseline-on-migrate: true

    enable은 기본값이 true이지만 명시적으로 적어줍니다.

     

    baseline-on-migrate

    1. 기본값 false
    2. false로 하려면 히스토리 테이블(flyway_schema_history)이 생성되어 있어야 함
    3. true로 하면 히스토리 테이블이 없을 경우 생성함

     

    SQL 파일 작성

    디렉터리 계층구조

    resources    db

            migration

                  V1__init.sql

     

    resources/db/migration/V1__init.sql을 생성합니다.

    create table member (
        id bigint generated by default as identity,
        member_id varchar(255),
        password varchar(255),
        nick_name varchar(255),
        full_name varchar(255),
        primary key (id)
    );

     

    이는 JPA Entity와 맞춰줍니다.

    package com.demo.infrastructure.member.signup.entity
    
    import com.demo.domain.member.entity.Member
    import javax.persistence.Column
    import javax.persistence.Entity
    import javax.persistence.Table
    import javax.persistence.Id
    import javax.persistence.GeneratedValue
    import javax.persistence.GenerationType.IDENTITY
    
    @Entity
    @Table(name = "member")
    class MemberJpaEntity(
        @Column
        private val memberId: String,
    
        @Column
        private val password: String,
    
        @Column
        private val nickName: String,
    
        @Column
        private val fullName: String,
    ) {
        @Id
        @GeneratedValue(strategy = IDENTITY)
        private val id: Long = 0L
    }

     

    실행해 보기

    curl --location --request POST 'localhost:8080/member' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "memberId": "any",
        "password": "any",
        "nickName": "any",
        "fullName": "any"
    }'

    ddl-auto: none 임에도 불구하고 flyway로 인해 테이블이 만들어지게 됩니다.

    200 OK가 떨어집니다.

     

    테스트 코드

    Flyway를 활용하여 테스트 코드까지 돌려보려고 합니다.

    테스트 환경에서도 ddl-auto: none으로 설정합니다.

    또한 flyway설정도 추가해 줍니다.

     

    다음과 같은 에러가 떨어집니다.

    Unable to determine H2 compatibility mode
    -----------------------------------------
    SQL State  : 42001
    Error Code : 42001
    Message    : Syntax error in SQL statement "SELECT [*]VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE'"; expected "TOP, DISTINCT, ALL, *, INTERSECTS (, NOT, EXISTS, UNIQUE, INTERSECTS"; SQL statement:
    SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE' [42001-214]

     

    다음과 같이 해결해보려고 했습니다.

    spring:
      flyway:
        enabled: true
        baseline-on-migrate: true
        locations: classpath:/db/migration
        schemas: PUBLIC
        url: jdbc:h2:mem:reader

     

    이렇게 해결했습니다.

    //AS-IS
    implementation ("org.flywaydb:flyway-core:6.4.2")
    //To-be
    implementation ("org.flywaydb:flyway-core")

     

    다음글을 참고하였는데 버전 충돌이 원인 같습니다.

    https://stackoverflow.com/questions/71202470/h2-version-change-issue-from-1-4-200-to-2-0-202

     

    H2 version change issue from 1.4.200 to 2.0.202?

    I upgraded my springboot H2 dependency from 1.4.200 to 2.0.202 , but getting the below exception . Could you please help. Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL

    stackoverflow.com

     

    다른 에러 발견

    Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "MEMBER" not found (this database is empty); SQL statement:
    insert into member (id, full_name, member_id, nick_name, password) values (default, ?, ?, ?, ?) [42104-214]

     

    Member table이 생성되지 않은 것 같습니다.

     

    모든 설정을 제거하니 잘 실행됩니다.

    spring:
      flyway:
        enabled: true
        baseline-on-migrate: true

    localtion을 잘 잡지 못한 것 같습니다.

     

     

    참고자료

    https://www.youtube.com/watch?v=pxDlj5jA9z4&t=191s 

    https://tecoble.techcourse.co.kr/post/2021-10-23-flyway/

     

     

    댓글

Designed by Tistory.