๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

INFRA/DB

[๋ฌผ๊นœ] Flyway๋ฅผ ๊ณ ๋ฅด๊ธฐ๊นŒ์ง€ - DB ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋„ ์—์ž์ผํ•ด์•ผ ํ•ด

๐Ÿค” ์™œ DB ์Šคํ‚ค๋งˆ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ์˜ ๋„์ž…์„ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋˜์—ˆ๋Š”๊ฐ€

์—์ž์ผ ํ•œ ๋ฐฉ์‹์œผ๋กœ 1์ฐจ ๋ฐ๋ชจ๋ฐ์ด / 2์ฐจ ๋ฐ๋ชจ๋ฐ์ด๋ฅผ ๊ฑฐ์น˜๋ฉด์„œ ๊ฐœ๋ฐœ์— ์ž„ํ•˜๊ณ  ์žˆ๋Š” ํ˜„์žฌ, ๊ณ„์†ํ•ด์„œ ์—”ํ‹ฐํ‹ฐ์˜ ๊ตฌ์„ฑ์ด ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์€ ๋‹น์—ฐํ•˜๋‹ค. ์šฐ๋ฆฌ ํŒ€์˜ ๊ฒฝ์šฐ์—๋„ ๊ธฐํš์— 2-3๋ฒˆ์€ ์—Ž์–ด์ง€๊ณ , ์ผ๋ถ€๊ฐ€ ์กฐ๊ธˆ์”ฉ ์ˆ˜์ •๋˜๊ธฐ๋„ ํ–ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŒ€์› ๊ฐ„์˜ ์ดํ•ด๊ฐ€ ์กฐ๊ธˆ์”ฉ ์–ด๊ธ‹๋‚˜์„œ ์—”ํ‹ฐํ‹ฐ์˜ ๊ตฌ์กฐ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ๊ฒฝ์šฐ๋„ ํ—ˆ๋‹คํ–ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— DB ์Šคํ‚ค๋งˆ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ์ด๋ผ๋Š” ์˜ˆ์ƒ์€ ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒ๊ฐ๋ณด๋‹ค ๋นจ๋ฆฌ ํ•„์š”์„ฑ์„ ๋А๋ผ๊ฒŒ ๋˜์—ˆ๋‹ค. ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ 500 ์—๋Ÿฌ๊ฐ€ ํ„ฐ์กŒ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

์™œ ๋ฌธ์ œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ์„๊นŒ?

๊ธฐ์กด์— amount ๋ผ๋Š” ํ•„๋“œ๊ฐ€ ์กด์žฌํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์˜ ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด cupAmount ๋ผ๋Š” ํ•„๋“œ๋ช…์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šด์˜ ํ™˜๊ฒฝ์˜ ddl-auto ๊ฐ€ update ์˜€๊ธฐ์— amount ๋ผ๋Š” ํ•„๋“œ๋Š” ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ณ , cupAmount ๋ผ๋Š” ํ•„๋“œ๊ฐ€ ์ถ”๊ฐ€ ๋๋‹ค.

 

์ด๋Š” ํ•ด๋‹น API ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ–‰์ด ๋  ๋•Œ, ๋Ÿฐํƒ€์ž„์— 500 ์—๋Ÿฌ๋ฅผ ๋ฑ‰์–ด๋ƒˆ๊ณ  ์šฐ๋ฆฌ๋Š” ํŒจ๋‹‰์ด ์™”์—ˆ๋‹ค. ๊ทธ ๋•Œ ๋ฐ”๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ๋ฅผ ๋„์ž…ํ•ด์•ผ๊ฒ ๋‹ค๋Š” ๊ฒฐ๋ก ์„ ๋‚ด๋ ธ๋‹ค!

ddl-auto ๋กœ๋Š” ์ถฉ๋ถ„์น˜ ์•Š์€๊ฐ€?

create ์‹คํ–‰ ์‹œ ํ…Œ์ด๋ธ”์„ ๋ชจ๋‘ ์ œ๊ฑฐ ํ›„ ์ƒˆ๋กœ ์ƒ์„ฑ โŒ ์šด์˜ ๋ฐ์ดํ„ฐ ์‚ญ์ œ
create-drop ์ข…๋ฃŒ ์‹œ์ ์— ํ…Œ์ด๋ธ”๋„ ์‚ญ์ œ โŒ ํ…Œ์ŠคํŠธ ์™ธ ๋ถˆ๊ฐ€
update ๊ตฌ์กฐ ๋ณ€๊ฒฝ ๊ฐ์ง€ ์‹œ DB์— ๋ฐ˜์˜ โš ๏ธ ๋ณ€๊ฒฝ ๋‚ด์—ญ ์ถ”์  ๋ถˆ๊ฐ€ / ์ผ๋ถ€ ๋ณ€๊ฒฝ ๋ˆ„๋ฝ ๊ฐ€๋Šฅ
validate DB์™€ Entity์˜ ์ผ์น˜ ์—ฌ๋ถ€๋งŒ ํ™•์ธ โœ… ์•ˆ์ „ํ•˜์ง€๋งŒ ๋ณ€๊ฒฝ ๋ฐ˜์˜์€ ์ง์ ‘ ํ•ด์•ผ ํ•จ
none ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Œ โœ… ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ ์‚ฌ์šฉ ์‹œ ์ ํ•ฉ

 

์ ˆ๋Œ€ ์ถฉ๋ถ„์น˜ ์•Š๋‹ค. ddl-auto ๋ฅผ ์•„๋ฌด๋ ‡๊ฒŒ๋‚˜ ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๋ฉด ์—„์ฒญ๋‚œ ์œ„ํ—˜์ด ๋”ฐ๋ฅธ๋‹ค.

์œ„์˜ ํ‘œ์— ์ •๋ฆฌํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด ์šด์˜ํ™˜๊ฒฝ์—์„œ๋Š” validate ํ˜น์€ none ์œผ๋กœ ์„ค์ •ํ•ด๋‘๊ณ , ์ง์ ‘ ๋ณ€๊ฒฝ์„ ๋ฐ˜์˜ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

๐Ÿค” Liquibase vs Flyway

์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์„ ๋„์ž…ํ•  ๋•Œ์—๋Š” ๋ญ๋“  ์ด์œ ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ๊ธฐ์กด์— ์‚ฌ์šฉํ•ด๋ณธ ๊ฒฝํ—˜์ด ์žˆ๋Š” Flyway ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์— ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋‹ค๋ฅธ ํˆด๊ณผ ๋น„๊ตํ•ด๋ณด์•˜๋‹ค.

 

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๋„๊ตฌ๋Š” Liquibase ์™€ Flyway ์˜€๋‹ค. ์ด๋ฅผ ํ† ๋Œ€๋กœ ๋น„๊ต๋ฅผ ์‹œ์ž‘ํ–ˆ๋‹ค.

๋‹ค์Œ์€ ํŒ€์›๋“ค๊ณผ ๋…ผ์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋‚จ๊ฒจ๋’€๋˜ discussions ๋‚ด์šฉ์˜ ์ „๋ฌธ์ด๋‹ค.


 

https://github.com/woowacourse-teams/2025-mul-kkam/discussions/122

 

๐Ÿ’ฌ DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ ๋น„๊ต: `Flyway` vs `Liquibase` · woowacourse-teams 2025-mul-kkam · Discussion #122

์•ˆ์ „ํ•œ ์—”ํ‹ฐํ‹ฐ์˜ ๋ณ€๊ฒฝ ๋ฐ ์œ ์ง€๋ฅผ ์œ„ํ•ด DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ๋ฅผ ๋„์ž…ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” flyway ๊ฐ€ ๋” ์ ํ•ฉํ•  ๊ฒƒ์ด๋ผ๋Š” ๊ฒฐ๋ก ์„ ๋‚ด๋ ธ์–ด์š”! ๋‹ค๋ฅธ ์˜๊ฒฌ์ด๋‚˜ ๋ฐ˜๋ฐ• ํ™˜์˜ํ•ด์š” ๐Ÿค— ๋‹ค์Œ ๊ธ€์„ ์ฝ์–ด๋ณด๊ณ , ์ž

github.com

 

 

๐Ÿ”Ž ์„ ์ • ๊ธฐ์ค€

  • ์‹ค๋ฌด์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ
  • ๋‘ ๋„๊ตฌ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋น„๊ตํ•œ ๋ธ”๋กœ๊ทธ๋‚˜ ๋ฌธ์„œ๊ฐ€ ๋‹ค์ˆ˜ ์กด์žฌํ•จ

1. ์„ ์–ธ ๋ฐฉ์‹ ์ฐจ์ด

โœ… Liquibase ์˜ˆ์‹œ (XML DSL)

<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-3.8.xsd">

  <changeSet id="1" author="jinseunghui">
    <createTable tableName="member">
      <column name="id" type="BIGINT" autoIncrement="true">
        <constraints primaryKey="true"/>
      </column>
      <column name="nickname" type="VARCHAR(50)">
        <constraints nullable="false"/>
      </column>
      <column name="gender" type="VARCHAR(10)">
        <constraints nullable="false"/>
      </column>
      <column name="weight" type="DOUBLE"/>
    </createTable>
  </changeSet>
</databaseChangeLog>

๐Ÿ’ก ์œ„ XML์€ ์•„๋ž˜ SQL๊ณผ ๋™์ผ
```sql
CREATE TABLE member (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  nickname VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  weight DOUBLE
);
 

Liquibase XML๋Œ€์‘๋˜๋Š” SQL

<createTable> CREATE TABLE ...
<column name="x" type="..."/> ๊ฐ ์ปฌ๋Ÿผ ์ •์˜
<constraints primaryKey="true"/> PRIMARY KEY, NOT NULL, UNIQUE ๋“ฑ ์ œ์•ฝ์กฐ๊ฑด
<changeSet id="1">...</changeSet> ํ•˜๋‚˜์˜ ๋ฒ„์ „ ๋‹จ์œ„. Git ์ปค๋ฐ‹์ฒ˜๋Ÿผ ๊ด€๋ฆฌ๋จ

โœ… Flyway ์˜ˆ์‹œ (SQL ๊ธฐ๋ฐ˜)

-- V1__create_member.sql
CREATE TABLE member (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  nickname VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  weight DOUBLE
);
 

๐Ÿ“Œ ์ •๋ฆฌ

  • Flyway: SQL ์ง์ ‘ ์ž‘์„ฑ → ํ•™์Šต ๋น„์šฉ ๋‚ฎ์Œ, ์ง๊ด€์ 
  • Liquibase: DSL ํ˜•ํƒœ → ๋„๋ฉ”์ธ ์–ธ์–ด์— ๊ฐ€๊นŒ์›€ (์ถ”์ƒํ™” ๋†’์Œ), ๋Ÿฌ๋‹์ปค๋ธŒ ์กด์žฌ

2. ๋กค๋ฐฑ ์ง€์› ์—ฌ๋ถ€

โœ… Liquibase

<changeSet id="2" author="jin">
  <addColumn tableName="member">
    <column name="age" type="int"/>
  </addColumn>
  <rollback>
    <dropColumn tableName="member" columnName="age"/>
  </rollback>
</changeSet>
 
  • Liquibase๋Š” ๋กค๋ฐฑ์ด ๊ฐ€๋Šฅ

โŒ Flyway

-- V3__remove_age.sql
ALTER TABLE member DROP COLUMN age;
 
  • ์ง์ ‘ DROP COLUMN SQL ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ƒˆ ํŒŒ์ผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•จ
  • ๋ฒ„์ „์„ “๋˜๋Œ๋ฆฌ๋Š” ๊ฒƒ”์€ ๋ถˆ๊ฐ€๋Šฅ → ์ƒˆ๋กœ์šด ๋ฒ„์ „์œผ๋กœ ๋ฎ๋Š” ๋ฐฉ์‹

๐Ÿ“Œ ์ •๋ฆฌ

  • Liquibase๋Š” rollback ๋ฌธ๋ฒ• ๋‚ด์žฅ
  • Flyway๋Š” ๋กค๋ฐฑ ์‹œ ์ƒˆ๋กœ์šด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•จ (๋˜๋Œ๋ฆผ์ด ์•„๋‹ˆ๋ผ ‘๋ฎ์–ด์“ฐ๊ธฐ’)

3. Java API ์ œ๊ณต ์—ฌ๋ถ€

โœ… Flyway (์ง์ ‘ ์‹คํ–‰ ๊ฐ€๋Šฅ)

Flyway flyway = Flyway.configure()
    .dataSource("jdbc:mysql://localhost:3306/test", "user", "pw")
    .locations("classpath:db/migration")
    .load();

flyway.clean();
flyway.migrate();
 

Java ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ๋„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์šฉ์ด

  • ํ…Œ์ŠคํŠธ์—์„œ ์ง์ ‘ DB ์ดˆ๊ธฐํ™”/์žฌ์ ์šฉ
  • ๋‹ค์ค‘ DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋™์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ๋•Œ
  • ํŠน์ • ์กฐ๊ฑด/ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋™์  ์‹คํ–‰ํ•  ๋•Œ

ํ…Œ์ŠคํŠธ ์‹œ์— ํŠนํžˆ ์šฉ์ด

@BeforeEach
void setUp() {
    flyway.clean();
    flyway.migrate();
}
 

์œ„์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ํ…Œ์ŠคํŠธ ์‹œ ํ•„์š”ํ•˜๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅ

โœ… Liquibase (SpringLiquibase ์‚ฌ์šฉ)

@Configuration
public class LiquibaseConfig {
  @Bean
  public SpringLiquibase liquibase(DataSource dataSource) {
    SpringLiquibase liquibase = new SpringLiquibase();
    liquibase.setDataSource(dataSource);
    liquibase.setChangeLog("classpath:db/changelog/db.changelog-master.yaml");
    liquibase.setContexts("dev,test");
    return liquibase;
  }
}
 

LiquiBase ๋Š” Java API ๋Š” ์ œ๊ณต๋˜์ง€ ์•Š์ง€๋งŒ, Spring ๊ณผ ํ†ตํ•ฉ๋œ ์ƒํ™ฉ์—์„œ๋Š” ์šฉ์ดํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

@LisuiBaseBean ์ด ์กด์žฌ

Spring Boot ํ™˜๊ฒฝ์—์„œ Liquibase๋ฅผ Java Bean์œผ๋กœ ์ˆ˜๋™ ๊ตฌ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” Spring์šฉ ์„ค์ • ํด๋ž˜์Šค

  • ๋ณดํ†ต์€ application.yml๋กœ Liquibase๋ฅผ ์ž๋™ ์‹คํ–‰ํ•˜์ง€๋งŒ, ํŠน๋ณ„ํ•œ ์„ค์ •์ด ํ•„์š”ํ•  ๋•Œ ์ง์ ‘ SpringLiquibase ๋นˆ์„ ๋“ฑ๋กํ•ด ์ œ์–ด ๊ฐ€๋Šฅ
  • ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ SpringLiquibase ๋นˆ์„ ์ฃผ์ž…ํ•ด ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ˜•ํƒœ ์ œ๊ณต

โŒ flyway ๋Š” RDBMS ๋งŒ ์ œ๊ณต
โœ… LiquiBase ๋Š” NoSQL ์ค‘ MongoDB ๋งŒ ๊ณต์‹์ ์œผ๋กœ ์ง€์›

Spring Boot ํ†ตํ•ฉ

โœ… ๋‘ ๋„๊ตฌ ๋ชจ๋‘ Spring Boot ์—์„œ ๊ณต์‹์ ์œผ๋กœ ์ง€์›

์ž๋™ ์‹คํ–‰ Spring Boot ์‹œ์ž‘ ์‹œ ์ž๋™์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆ˜ํ–‰
JDBC ์—ฐ๋™ DB URL, username/password ์ง€์ • ๊ฐ€๋Šฅ
Profile์— ๋”ฐ๋ผ ๋ถ„๊ธฐ ๊ฐ€๋Šฅ ์˜ˆ: application-dev.yml, application-prod.yml๋กœ ๋ถ„๋ฆฌ
ํ…Œ์ŠคํŠธ ์‹œ ์œ ์šฉ H2 ๋“ฑ ๋‚ด์žฅ DB ํ…Œ์ŠคํŠธ์—์„œ๋„ ์ž๋™ ๋ฐ˜์˜ ๊ฐ€๋Šฅ
spring:
  flyway:
    enabled: true
    locations: classpath:db/migration
    baseline-on-migrate: true
    user: myuser
    password: secret
    url: jdbc:mysql://localhost:3306/mydb
 
spring:
  liquibase:
    enabled: true
    change-log: classpath:db/changelog/db.changelog-master.yaml
    contexts: test
    default-schema: public
    user: myuser
    password: secret
    url: jdbc:postgresql://localhost:5432/mydb
 

์Šคํ‚ค๋งˆ ์ž๋™ ์ƒ์„ฑ

flyway ์™€ LiquiBase ๋ชจ๋‘ ๋ถˆ๊ฐ€๋Šฅ
์ˆ˜๋™์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•ด์ค˜์•ผ ํ•จ

๊ทธ๋Ÿฌ๋‚˜ flyway ๋Š” ์ง์ ‘ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜์ง€๋งŒ, Liquibase ๋Š” DSL ๊ณผ ๊ฐ™์ด ๋„๋ฉ”์ธ์— ๋” ๊ฐ€๊น๊ฒŒ ์ •์˜ํ•˜๋ฉด ์ด๋ฅผ SQL ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค๋Š” ์ฐจ์ด์ ์€ ์กด์žฌ.

์กฐ๊ธˆ ๋” LiquiBase ๊ฐ€ ๋„๋ฉ”์ธ ์ธก๋ฉด์— ๊ฐ€๊นŒ์šด ์ถ”์ƒํ™”๋œ ํ˜•ํƒœ

databaseChangeLog:
  - changeSet:
      id: 1
      author: jin
      changes:
        - createTable:
            tableName: member
            columns:
              - column:
                  name: id
                  type: bigint
                  autoIncrement: true
                  constraints:
                    primaryKey: true
              - column:
                  name: name
                  type: varchar(255)
 

์œ„์™€ ๊ฐ™์ด ์กฐ๊ธˆ ๋” '์–ธ์–ด'์— ๊ฐ€๊นŒ์›Œ ๋น„๊ฐœ๋ฐœ์ž๋„ ์ดํ•ดํ•˜๊ธฐ ์šฉ์ดํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿ”š ์ตœ์ข… ํŒ๋‹จ

โœ… Flyway
• SQL ์นœ์ˆ™ํ•˜๊ณ  ์ง๊ด€์ ์ธ ๋ฐฉ์‹
• ๋Ÿฌ๋‹์ปค๋ธŒ ์ ์Œ
• ํ…Œ์ŠคํŠธ ์‹œ ์œ ์—ฐํ•˜๊ฒŒ ํ™œ์šฉ ๊ฐ€๋Šฅ

 

โœ… Liquibase
• DSL ๊ธฐ๋ฐ˜ ์„ ์–ธ → ๋น„๊ฐœ๋ฐœ์ž๋„ ์ ‘๊ทผ ๊ฐ€๋Šฅ
• ๋กค๋ฐฑ ๊ธฐ๋Šฅ ๋“ฑ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ ์ œ๊ณต
• ๋‹จ, DSL ํ•™์Šต์ด ํ•„์š” → ํŒ€ ์ƒํ™ฉ ๊ณ ๋ ค

 

๐Ÿ’ฌ ํ˜„์žฌ ๋ฌผ๊นœ ํ”„๋กœ์ ํŠธ ํŒ€ ์ƒํ™ฉ์—์„œ๋Š”
→ ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ์ ๊ณ , SQL ๊ธฐ๋ฐ˜์˜ Flyway๊ฐ€ ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จ๋จ


๐Ÿงž‍โ™‚๏ธ DB ๋„ ๊ฒฐ๊ตญ ์—์ž์ผํ•ด์•ผ ํ•œ๋‹ค

 

์ด๋ ‡๊ฒŒ ์˜ฌ๋ ธ๋˜ ๋””์Šค์ปค์…˜์— ํŒ€์›์ธ ์นผ๋ฆฌ๐Ÿ‘๐Ÿป ๊ฐ€ ์œ„์™€ ๊ฐ™์€ ์ฝ”๋ฉ˜ํŠธ๋ฅผ ๋‚จ๊ฒจ์ฃผ์—ˆ๋‹ค. ์ด ์ฝ”๋ฉ˜ํŠธ์—์„œ ๋‚˜๋Š” ์ฃผ๋ชฉํ•œ ๋‹จ์–ด๊ฐ€ ์žˆ์—ˆ๋‹ค. ์—์ž์ผ! โ‡๏ธ

DB ๋„ ๊ฒฐ๊ตญ ์šฐ๋ฆฌ์˜ ์„œ๋น„์Šค๋ฅผ ์ด๋ฃจ๋Š” ์ฃผ์š”ํ•œ ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜์ธ๋ฐ, ์™œ ์—์ž์ผํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ•˜์ง€ ๋ชปํ–ˆ์„๊นŒ? ํ•˜๋Š” ์ƒ๊ฐ์„ ํ•˜๊ฒŒ ๋๋‹ค.

 

๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ์ €๋Ÿฐ ์†Œ์Šค๋“ค์„ ์ฐพ์•„๋ณด๋˜ ์ค‘, ๋‹ค์Œ ๊ธ€์„ ๋ณด๊ฒŒ ๋๋‹ค.

 

https://martinfowler.com/articles/evodb.html

 

Evolutionary Database Design

Techniques to allow you to evolve the schema and contents of a production database

martinfowler.com

 

์ด ๊ธ€์˜ ์ฃผ๋œ ์š”์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์˜ ์ฝ”๋“œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ญ์‹œ๋„ ์• ์ž์ผํ•˜๊ฒŒ ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•œ๋‹ค
  • ํ•ด๋‹น ๋ฒ„์ „์œผ๋กœ ๋กค๋ฐฑ์„ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ์ฝ”๋“œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋„ ์ด์— ๋งž์ถฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ด ๊ฐ–์ถฐ์ ธ์•ผ ํ•œ๋‹ค
  • ์ž„์‹œ sql ์„ ์ ˆ๋Œ€๋กœ ์‹คํ–‰ํ•˜๋ฉด ์•ˆ๋˜๊ณ , ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ๋งŒ ๊ตฌ๋™๋˜์–ด์•ผ ํ•œ๋‹ค

๊ทธ๋ ‡๋‹ค๋ฉด, ์—์ž์ผํ•˜๊ฒŒ ๊ด€๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ๋•๋Š” DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผ ํ•œ๋‹ค๋Š” ๊ฒŒ ๋‚ด ์ƒ๊ฐ์ด์—ˆ๋‹ค.

 

1. ๋กค๋ฐฑ์ด ์‰ฌ์›Œ์•ผ ํ•œ๋‹ค. -> ์–ธ์ œ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋„๊ตฌ์™€ ํ•จ๊ป˜ ๋ฒ„์ €๋‹์ด ์†์‰ฝ๊ฒŒ ๋˜์–ด์•ผ ํ•œ๋‹ค.

2. ๋ˆ„๊ตฐ๊ฐ€ ๊นƒํ—ˆ๋ธŒ์™€ ๊ฐ™์€ ๋ฒ„์ „์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ ์ด์™ธ์— ์ž„์˜๋กœ ์‹คํ–‰ํ•œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์—†๋Š”์ง€ ๊ฒ€์ฆ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ์š”์†Œ๋กœ ๋”ฐ์ ธ๋ณด์•˜์„ ๋•Œ์—๋Š”, Liquibase ์˜ ๋‹ค์Œ ์š”์†Œ๋“ค์„ ๋– ์˜ฌ๋ ค๋ดค์„ ๋•Œ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋„๊ตฌ๋ผ๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.

 

1. Liquibase ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ๋กค๋ฐฑ์ด ์กด์žฌํ•œ๋‹ค.

2. diff ๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•˜๋Š” ๋“ฑ ์ž„์‹œ ์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์„ ci ๋“ฑ์„ ํ†ตํ•ด ์—„๊ฒฉํžˆ ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ Flyway ๋กœ..

๊ทธ๋Ÿผ์—๋„ ์šฐ๋ฆฌ ํŒ€์€ Flyway ๋ฅผ ์„ ํƒํ•˜๊ฒŒ ๋๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

1. ๋Ÿฌ๋‹ ์ปค๋ธŒ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  • MVP ๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ฝ‘์•„๋‚ด๋ณด๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•œ ์ง€๊ธˆ, SQL ๊ธฐ๋ฐ˜ ๋Œ€์‹  DSL ๊ธฐ๋ฐ˜์˜ ์–ธ์–ด๋ฅผ ๋ฐฐ์›Œ๋ณด๋Š” ๊ฒŒ ํšจ์œจ์ ์ธ๊ฐ€?
  • SQL ์ด ์˜คํžˆ๋ ค ์šฐ๋ฆฌ์—๊ฒŒ๋Š” ์ง๊ด€์ ์ผ ์ˆ˜๋„ ์žˆ๋‹ค.
  • ํ˜„์žฌ๋Š” ์—์ž์ผ์ด๋ผ๋Š” ๊ฐ€์น˜๋‚˜ ์ƒˆ๋กœ์šด ํˆด์„ ๋ฐฐ์›Œ๋ณด๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๊ฐ€์น˜๋ณด๋‹ค ์†๋„๊ฐ€ ์ƒ๋ช…!

2. Flyway ๋„ ์–ด๋А ์ •๋„ ํ•ด๋‚ธ๋‹ค..

  • ๋‚ด๊ฐ€ ์ค‘์š”์‹œํ–ˆ๋˜ ๋กค๋ฐฑ์€ ์ƒˆ๋กœ์šด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•ด ๋กค๋ฐฑ์„ 'ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€' ์ผ์ข…์˜ ํšจ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜๋„ ์žˆ๋‹ค.
  • ์ฒดํฌ์„ฌ / ๋ฒ„์ „ ๊ธฐ๋ก ๋“ฑ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์œผ๋กœ '์–ด๋А ์ •๋„๋Š”' ์˜๋„ํ•œ ๋ฐ”๋Œ€๋กœ ์—์ž์ผํ•˜๊ณ  ์ •ํ•ฉ์„ฑ ์žˆ๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ ์šฐ์„ ์€ Flyway ๋กœ ์„ธํŒ…์„ ํ•ด๋‘๊ณ , ๋กค๋ฐฑ์˜ ํ•„์š”์„ฑ์ด๋‚˜ / ๋” ์—„๊ฒฉํ•œ ๋ฒ„์ €๋‹์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จ์ด ๋  ๋•Œ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค!