본문으로 바로가기
반응형

개요

실무에서는 데이터베이스 테이블을 생성하거나 수정하는 행위를 할 때 수동으로 관리하지않고 마이그레이션 라이브러리등을 사용한다. 파이썬은 Django의 경우 기본적으로 마이그레이션 기능이 제공되며 SQLAlchemy는 alembic이라는 대표적인 라이브러리가 존재한다. 스프링 또한 마찬가지인데 일반적으로 Flyway를 사용한다고 한다. 이런류의 라이브러리를 사용하면 히스토리를 버전별로 관리할 수 있고 디비 스키마를 코드로 관리할 수 있기 때문에 장점이 많다.

설치

implementation 'org.flywaydb:flyway-core:6.4.2'

build.gradle에 위 의존성을 추가한다.

How to

먼저 resources폴더 내부에 db폴더를 만들고 db내부에 migration이라는 폴더를 만들어준다. 해당 폴더에서 마이그레이션 스크립트를 관리하게 된다. 

@Entity
@Table(name = "users")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User extends BaseTimestampEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Builder
    public User(String name) {
        this.name = name;
    }
}

다음으로 테스트를 진행하기 위해 User 엔티티를 하나 생성한다.

jpa:
  hibernate:
    ddl-auto: none

hibernate를 사용하는 경우 ddl-auto를 none으로 설정하여 동작하지 않도록 한다. 우리는 flyway를 통해 데이터베이스를 관리할 예정이기 때문이다.

CREATE TABLE users (
    id int8 generated BY DEFAULT AS IDENTITY,
    name varchar(20) NOT NULL,
    create_time TIMESTAMP,
    update_time TIMESTAMP,
    PRIMARY KEY (id)
)

아까 생성한 resources/db/migration 폴더에 V1__init.sql 라는 제목으로 파일을 하나 생성하고 위 내용을 채워넣는다. (참고로 나는 PostgreSQL을 사용하고 있다. 각자의 데이터베이스에 맞게 DB statement를 작성하면 된다) 여기서 기억해야할점은 아래와 같다.

1. V숫자__ 형태로 시작해야한다. 숫자를 하나씩 늘려가며 버저닝을 한다고 생각하면 된다.

2. __(더블 언더스코어) 뒤에는 원하는 내용을 적으면 된다. 나는 첫 마이그레이션이므로 init을 작성했고 각자의 상황에 맞게, 예를 들어 product 테이블을 추가하는 경우 V1__create_product_table.sql 정도로 적어주면 되겠다.

spring:
  flyway:
    enabled: true
    baseline-on-migrate: true
    url: jdbc:postgresql://localhost:5432/test
    user: test
    password: test
    locations: classpath:db/migration

다음으로 application.yml 파일에 위 내용을 추가해준다. enabled속성을 통해 스프링이 뜰 때 자동으로 flyway를 실행시켜줄 지 설정할 수 있다. baseline-on-migrate는 true로 주는 경우 버전 정보를 저장하는 테이블이 없는 경우 새롭게 생성한다.

주의 사항

만약 테이블이나 컬럼에 변경사항이 생기면 어떻게 해야할까? 기존에 작성되어있는 파일에 들어가서 수정해야할까? 절대 그렇지 않다. 컬럼의 속성값이 바뀌는 등의 작은 변경사항도 무조건 새로운 sql파일을 생성하여 새로운 버저닝을 진행해줘야 한다.

데이터베이스를 들어가보면 flyway_schema_history라는 테이블이 하나 있다. flyway는 해당 테이블을 통해 리비전의 버전을 관리한다. 따라서 이미 데이터베이스 반영된 sql파일을 수정해준다고 해서 해당 사항을 detect하여 반영하지는 않는다. 변경사항이 생기면 반드시 새로운 sql파일을 생성해야 한다는 점을 꼭 기억하자.

아쉬운 점

파이썬의 경우 alembic을 사용하면 SQLAlchemy 모델을 자동으로 감지하여 새롭게 추가해야하는 테이블이나 변경되어야하는 컬럼이 있다면 변경이력을 만들어준다. 하지만 Flyway는 그런 기능은 없고 단순히 git처럼 데이터베이스의 이력 관리의 기능이 강한 것 같다. 이 부분은 상당히 아쉬운 점으로 작용한다. Data JPA는 위 기능을 제공하던데, Data JPA와 Flyway의 기능들을 합친 건 따로 없는 걸까?

반응형