[내일배움캠프] 22일 차 TIL Liquibase

2026. 3. 3. 20:20·내배캠

22일 차 TIL

코드에 Git이 있다면, DB에는 Liquibase가 있다.
Liquibase는 데이터베이스 버전 관리 툴이다.

DB 스키마 변경 이력을 코드처럼 관리하고,
협업 시 모든 팀원의 DB 상태를 동일하게 유지해 주는 Liquibase의 설정 방법을 살펴보자.

Liquibase를 스프링 부트에 적용하기

1. gradle에 Liquibase 의존성 추가 ( start.spring.io에서 Liquibase 검색 후 추가 )

// Liquibase
implementation 'org.liquibase:liquibase-core'

 

먼저 Liquibase 의존성을 gradle에 추가한다.

2. 디렉터리 구조

Liquibase의 DB 변경 이력을 저장하는 구조

changelog 폴더에 DB의 변경 이력을 저장하는 용도로
DDL을 적은 sql 파일을 저장한다.

 

따라서 resources 하위에 다음과 같이 구성한다.

- resources에 db폴더 추가

Liquibase 관련 파일 위치

3. db.changelog-master.yaml 추가

databaseChangeLog:
  - includeAll:
      path: db/changelog
      relativeToChangelogFile: false
      filter: com.git.prac.global.liquibase.LiquibaseIncludeFilter

모든 변경 사항을 일일이 등록하기 귀찮으므로, includeAll을 사용해 특정 폴더의 파일을 통째로 읽어오도록 설정한다.

 

아래의 공식 문서를 참고했다.
https://docs.liquibase.com/community/implementation-guide-5-0/set-up-your-changelog-structure

4. 필터 구현 (파일명 규칙 적용)

package com.git.prac.global.liquibase;

import java.nio.file.Paths;
import java.util.regex.Pattern;
import liquibase.changelog.IncludeAllFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

/**
 * LiquibaseIncludeAllFilter
 * [허용 패턴]
 * - 형식: {숫자}_{설명}.sql
 * - 예시: 001_create_users.sql, 02_add_column.sql, 1_init.sql
 */
@Slf4j
public class LiquibaseIncludeFilter implements IncludeAllFilter {
    private static final Pattern SEQUENCE_PATTERN = Pattern.compile("^[0-9]+_[a-zA-Z0-9_]+\\.sql$");

    @Override
    public boolean include(String changeLogPath) {
        if (!StringUtils.hasText(changeLogPath)) {
            return false;
        }

        String fileName = Paths.get(changeLogPath).getFileName().toString();

        if (fileName.startsWith(".")) {
            return false;
        }

        boolean matches = SEQUENCE_PATTERN.matcher(fileName).matches();

        if (!matches) {
            log.debug("[Liquibase] Skipped file (Invalid Name): {} | Path: {}", fileName, changeLogPath);
        }

        return matches;
    }
}

위 필터는 스키마를 생성할 때 사용할 파일명을 체크하는데,
{숫자}_{설명}.sql 형식으로 제한할 수 있다.
파일명 예시) 01_create_user.sql

5. SQL 파일 작성

파일 상단에 -- liquibase formatted sql과 -- changeset 작성자:ID를 적어줘야
Liquibase가 변경 이력으로 인식한다.

-- liquibase formatted sql

-- changeset Jaehyun-Kim:01-create-p-store-table
CREATE TABLE p_store
(
    store_id       BIGINT        NOT NULL AUTO_INCREMENT COMMENT '가게 ID',
    user_id        BIGINT        NOT NULL COMMENT '사장님 ID',
    address_id     BIGINT        NOT NULL COMMENT '가게 주소 ID',
    name           VARCHAR(100)  NOT NULL COMMENT '상호명',
    rating_avg     DECIMAL(2,1)  NOT NULL DEFAULT 0.0 COMMENT '가게 평점',
    review_count   INT           NOT NULL DEFAULT 0 COMMENT '리뷰 수',
    detail_address VARCHAR(255)  NOT NULL COMMENT '상세 주소',

    created_at     TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '레코드 생성 시간',
    created_by     VARCHAR(100)  NOT NULL COMMENT '레코드 생성자',
    updated_at     TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '레코드 수정 시간',
    updated_by     VARCHAR(100)  NOT NULL COMMENT '레코드 수정자',
    deleted_at     TIMESTAMP     NULL COMMENT '레코드 삭제 시간',
    deleted_by     VARCHAR(100) NULL COMMENT '레코드 삭제자',

    -- Constraints
    CONSTRAINT pk_store PRIMARY KEY (store_id),
    CONSTRAINT ck_store_rating_range CHECK (rating_avg BETWEEN 0.0 AND 5.0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- rollback DROP TABLE p_store;

-- Indexes
CREATE INDEX idx_store_user_id ON p_store (user_id);
CREATE INDEX idx_store_address_id ON p_store (address_id);

-- rollback DROP INDEX idx_store_user_id;
-- rollback DROP INDEX idx_store_address_id;

 

스키마 구조를 변경하고 싶다면 새로운 sql 파일을 저장하면 된다.

컬럼 추가 예시)

-- liquibase formatted sql
-- changeset your.name:4
ALTER TABLE person ADD nickname VARCHAR(30);

 

또는 yaml 파일을 변경할 수도 있다.

databaseChangeLog:
  - includeAll:
      path: db/changelog
      # ... (기존 설정)
      
  # includeAll 아래에 추가 가능
  - changeSet:
      id: 4
      author: your.name
      changes:
        - addColumn:
            tableName: person
            columns:
              - column:
                  name: nickname
                  type: varchar(30)

6. Application 설정 (YML)

Liquibase가 master 파일을 어디서 찾을지 알려줘야 한다.

spring:
  liquibase:
    enabled: true # 기본적으로 활성화	
    change-log: classpath:db/db.changelog-master.yaml

7. 결과 확인

애플리케이션을 실행하면 콘솔에 Liquibase 로그가 찍히며 DB에 두 개의 테이블이 추가로 생성된다.

  • DATABASECHANGELOG: 어떤 SQL이 실행되었는지 기록 (여기에 기록된 파일은 다시 실행 안 됨)
  • DATABASECHANGELOGLOCK: 동시에 여러 명이 배포할 때 DB 충돌 방지용 잠금장치

'내배캠' 카테고리의 다른 글

[내일배움캠프] 24일 차 TIL 클린 아키텍처와 DDD  (0) 2026.03.05
토스 사용 시, 결제 시나리오  (0) 2026.03.04
[내일배움캠프] 21일 차 TIL QueryDSL 적용 방법  (0) 2026.03.02
[내일배움캠프] 20일 차 TIL Github Rules, Code Convention  (0) 2026.03.01
[내일배움캠프] 19일 차 TIL 도메인 중심 아키텍처  (0) 2026.03.01
'내배캠' 카테고리의 다른 글
  • [내일배움캠프] 24일 차 TIL 클린 아키텍처와 DDD
  • 토스 사용 시, 결제 시나리오
  • [내일배움캠프] 21일 차 TIL QueryDSL 적용 방법
  • [내일배움캠프] 20일 차 TIL Github Rules, Code Convention
MvA
MvA
백엔드 개발자 김재현입니다. 주로 공부하면서 느낀점을 기록합니다.
  • MvA
    Man vs Ai
    MvA
  • 전체
    오늘
    어제
    • 분류 전체보기 (94)
      • Java (6)
      • Python (8)
        • 딥러닝 (1)
        • 머신러닝 (7)
      • JavaScript (2)
      • 내배캠 (60)
      • 개인 프로젝트 (11)
      • 책 후기 (5)
      • 기타 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Riot API
    내일배움캠프
    배포
    머신러닝
    아키텍처
    TiL
    딥러닝
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
MvA
[내일배움캠프] 22일 차 TIL Liquibase
상단으로

티스토리툴바