View

liquibase 개념 및 기본 사용법

rura6502 2021. 7. 3. 16:15

본 문서는 아래 버전을 사용하였음
liquibase-4.4.0
postgres 13.3
docker community

JHipster라는 자바 프로젝트 생성 툴을 사용했는데 자동으로 import해주는 여러 라이브러리들 중 모르는 것들이 많이 보여 그 중 하나인 liquibase가 어떤 것인지 찾아보았다.

Concept

데이터베이스의 스키마를 xml, sql, yaml, json으로 관리해주는 툴입니다. 원하는 데이터베이스의 스키마의 변화를 버전별로 관리할 수 있다.

예를들어 liquibase로 초기 데이터베이스부터 관리한다고 하면

  1. liquibase 툴의 포맷에 맞는, 테이블 생성/컬럼 설정 등 create 관련된 작업들이 기록된 xml을 생성한다. 대략적인 양식은 아래와 같다.

    <liqubase>
    <스키마 변화1>
     <테이블 생성>
       <컬럼1 생성/>
       <컬럼2 생성/>
     </테이블 생성>
    </스키마 변화1>
    </liqubase>
  2. 작업하다보니 컬럼3이 필요하다고 판단되어 liqubase 설정 파일에 컬럼3을 추가했다.

    <liqubase>
    <스키마 변화1>
     <테이블1 생성>
       <컬럼1 생성/>
       <컬럼2 생성/>
     </테이블1 생성>
    </스키마 변화1>
    
    <스키마 변화2>
        <컬럼추가 타겟테이블="테이블1">
       <추가할_컬럼 이름="컬럼3"/>
     </컬럼추가>
    </스키마 변화2>
    </liqubase>

위와같이 스키마의 변화, 데이터의 insert, update, delete를 기록할 수있으며 툴을 실행하여 어떤 변화로 돌아갈 것인지, 새로운 데이터베이스를 구축했는데 어떤 단계의 변화까지 실행할 것인지 툴을 통해 제어할 수 있다.

Community, Pro 두가지 버전을 제공하고 있다. 지원하는 데이터베이스 범위도 매우 넓어 NoSQL 등도 지원한다.

Test

먼저, 테스트를 위한 postgres docker를 실행하였다.

docker run --rm --name postgres-test -p 15432:5432 -e POSTGRES_PASSWORD=password -d postgres:latest

Liqubase download page에서 제공하는 zip 파일을을 받고 압축 파일을 푼다. , 해당 폴더에서 cmd 창을 실행하였다.

liquibase를 실행해서 데이터베이스 작업을 하려면 클래스패스에 jdbc와 같은 데이터베이스 드라이버 라이브러리가 있어야 하므로 maven repository에서 postgres jdbc를 다운로드받야 lib파일에 넣어두어야 한다.

동작에 필요한 다양한 정보들(데이터베이스의 url/user/password, liquibase의 다양한 설정들)은 liquibase.properteis 파일에 설정하는 방법이 있고, 명령어 실행 시 옵션을 입력하는 방법이 있는데 이번에는 간단한 테스트가 목적이라 바로 커맨드라인에서 입력하여 진행을 할 것이다.

스키마의 변경을 기록하는 작업 파일은 별도로 생성하여야 한다.

아직 데이터베이스에 아무것도 없는 상태이므로 스키마 생성을 위한 내용을 입력한다.

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
  http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
    <changeSet id="1" author="Liquibase">
      <createTable tableName="test_table">
        <column name="test_id" type="int">
          <constraints primaryKey="true"/>
        </column>
        <column name="test_column" type="varchar"/>
      </createTable>
    </changeSet>
</databaseChangeLog>

chageSet이 변경점을 기록하는 point라고 보면 되고 그 아래로 하고자하는 행위가 기록된다. 위는 간단하게 test_table이라는 테이블을 생성하는데 test_id라는 int형 컬럼을 생성하고 해당 컬럼을 private key로 지정하였다. 추가로 test_column이라는 컬럼도 같이 추가하였다.

해당 파일을 chage_log.xml이라는 파일로 저장하고 updateSQL을 실행시키면 liquibase에서 실행하려고 하는 쿼리문을 확인할 수 있다.

.\liquibase --url jdbc:postgresql://localhost:15432/postgres `
--username=postgres `
--password=password `
--changeLogFile=changelog.xml `
updateSql

명령어의 구성을 보면 --로 옵션을 입력하였고 맨 마지막에 행위에 대한 명령어를 입력하였다. updateSql은 단순 쿼리만 출력하고 실제 실행은 하지 않으며 update 명령어를 입력하면 데이터베이스에 바로 적용된다.

.\liquibase --url jdbc:postgresql://localhost:15432/postgres `
--username=postgres `
--password=password `
--changeLogFile=changelog.xml `
update

위 명령어를 실행하고 데이터베이스를 확인하면 원하는 모양을 가진 test_table이 생성된 것을 확인할 수 있다. 참고할 만한 것은 같은 위치에 databasechangelog, databasechangeloglock 테이블이 자동으로 생성된 것을 확인할 수 있는데 이는 liquibase에서 기록을 저장하고 엑세스를 제어하는 테이블이다.

changeSet 생성하기

컬럼을 변경하기 위해 changeSet을 하나 더 입력해보자.

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
  http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
    <changeSet id="1" author="Liquibase">
      <createTable tableName="test_table">
        <column name="test_id" type="int">
          <constraints primaryKey="true"/>
        </column>
        <column name="test_column" type="varchar"/>
      </createTable>
    </changeSet>

    <changeSet id="2" author="abcd">
      <addColumn tableName="test_table">
        <column name="name" type="varchar"></column>
      </addColumn>
    </changeSet>
</databaseChangeLog>

test_table 이라는 테이블에 name이라는 컬럼을 추가하하고 update를 실행하면 컬럼이 하나 더 추가된 테이블을 확인할 수 있다.

.\liquibase --url jdbc:postgresql://localhost:15432/postgres `
--username=postgres `
--password=password `
--changeLogFile=changelog.xml `
update

이전 변경으로 돌아가고 싶을 때 chageSetid 속성을 이용하 특정 포인트의 시점으로 바로 돌아갈 수 있다.

Caution

single side management

해당 작업들은 기존의 테이블, 칼럼에 영향을 미치지 않는다. 그리고 liquibase로 변경된 스키마 이외는 신경쓰지 않는다. 따라서 아래와 같은 상황이 발생할 수 있다.

  1. liquibase로 테이블 1, 컬럼 a, b, c를 만들었는데 이후에 liquibase를 사용하지 않고 DB 툴을 사용하여 컬럼 d를 추가하였다.
  2. 개발자는 liquibase의 xml 파일을 보고 테이블1의 컬럼이 a, b, c인줄 알았는데 실제로 확인해보니 컬럼 d도 있었다.

이와같은 특성으로 인해 liquibase로 변경하지 않는 변경과 섞여서 개발자가 원하지 않는 형태로 관리될 수 있으므로 한쪽으로만 관리가 필요하다.

Lock

자동으로 생성된 테이블 중 databasechangeloglock 테이블은 여러개의 liquibase 인스턴스가 동시에 작업하는 것을 막기 위한 lock 용도로 사용되는 테이블이다. kubernetes와 같은 환경에서 여러개의 liquibase가 하나의 데이터베이스에 접근할 경우 lock으로 인해 문제가 발생할 수 있다.

Conclusion

스프링의 경우 import.sql, data.sql 또는 jpa의 ddl generation 등 스키마, 데이터를 관리할 수 있는 기능을 제공하지만 liquiside는 훨씬 더 넓은 범위에서 체계적으로 관리할 수 있는 데이터베이스 버저닝 관리 도구이다. 관련 정책, 개발 플로우등을 잘 적용해서 사용한다면 유용한 도구가 될 수 있을 것으로 판단된다.

Refer

Liquibase Database Tutorials

Share Link
reply