๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ›„๊ธฐ๐Ÿ”ฅ/ํšŒ๊ณ ๋ก

์›น ๊ธฐ๋ฐ˜์˜ DB ํ˜•์ƒ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ ๊ตฌ์ถ•๊ธฐ(feat. Flyway)

by dkswnkk 2025. 1. 19.

ํ”„๋กœ์ ํŠธ ๋ฐฐ๊ฒฝ

ํ˜„์žฌ ๋‚ด๊ฐ€ ์†ํ•œ ํŒ€์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค์ฟผ๋“œ๋กœ ๋‚˜๋‰˜์–ด ์šด์˜๋˜๊ณ  ์žˆ๋‹ค. ์Šค์ฟผ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๊ฝค๋‚˜ ๋งŽ์€๋ฐ ์ด ์ค‘ 4๊ฐœ ์ด์ƒ์˜ ์Šค์ฟผ๋“œ๊ฐ€ ๋™์ผํ•œ ๊ณตํ†ต ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐฐํฌํ™˜๊ฒฝ๋„ ์ผ๋ฐ˜์ ์ธ ํšŒ์‚ฌ๋“ค๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์œผ๋กœ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด Git์„ ํ†ตํ•ด ํ˜•์ƒ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋Š”๋ฐ, ๊ฐ ์Šค์ฟผ๋“œ๋Š” ์Šคํ”„๋ฆฐํŠธ ๋‹จ์œ„๋กœ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ•„์š”ํ•œ SQL ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ ํ”„๋กœ์ ํŠธ์˜ changelog ํด๋”์—์„œ ๋ฒ„์ „๋ณ„๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒ์œ„ ํ™˜๊ฒฝ์œผ๋กœ ๋ฐฐํฌํ•  ๋•Œ๋Š” ํ•ด๋‹น ๋ฒ„์ „์— ํฌํ•จ๋œ ์ฟผ๋ฆฌ๋“ค์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜์—ฌ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ๋‹ค.

sql/
โ”œโ”€โ”€ changelog/
โ”‚   โ”œโ”€โ”€ A/                         # A ์Šค์ฟผ๋“œ 
โ”‚   โ”‚   โ”œโ”€โ”€ v5.7.11.md
โ”‚   โ”‚   โ”œโ”€โ”€ v5.7.12.md
โ”‚   โ”‚   โ””โ”€โ”€ v5.9.0.md
โ”‚   โ”‚   ...
โ”‚   โ”œโ”€โ”€ B/                         # B ์Šค์ฟผ๋“œ
โ”‚   โ”‚   โ”œโ”€โ”€ v6.4.0_B.sql
โ”‚   โ”‚   โ””โ”€โ”€ v6.4.0_B_dml.sql
โ”‚   โ”‚   ...
โ”‚   โ”œโ”€โ”€ C/                         # C ์Šค์ฟผ๋“œ
โ”‚   โ”‚   โ”œโ”€โ”€ v6.2.0_C_squard.sql
โ”‚   โ”‚   โ””โ”€โ”€ v6.2.0_dml_C_squard.sql
โ”‚   โ”‚   ...
โ”‚   โ””โ”€โ”€ D/                         # D ์Šค์ฟผ๋“œ
โ”‚       โ”œโ”€โ”€ v6.3.0_D_squard.md
โ”‚       โ””โ”€โ”€ v6.4.0_D_squard.md
โ”‚       ...
โ”œโ”€โ”€ init.sql                         
โ””โ”€โ”€ schema.sql

 

 

๊ธฐ์กด ๋ฌธ์ œ์ 

์ด๋Ÿฐ ๋ฐฐ๊ฒฝ์—์„œ ๊ธฐ์กด์˜ ๋ฐฉ์‹์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋“ค์ด ๋ฐœ์ƒ์„ ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

  1. ๋ฐฐํฌ ์•ˆ์ •์„ฑ ์ €ํ•˜: ์—ฌ๋Ÿฌ ์Šค์ฟผ๋“œ๊ฐ€ ๋™์ผํ•œ ์Šคํ”„๋ฆฐํŠธ ๊ธฐ๊ฐ„์— ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ๊ฐ ์Šค์ฟผ๋“œ๊ฐ€ ์ž์‹ ๋“ค์˜ ์ฟผ๋ฆฌ๋งŒ์„ ์„ ํƒ์ ์œผ๋กœ ๋ฐ˜์˜ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ณ , ์ด๋กœ ์ธํ•ด ํ•„์ˆ˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์–ด ์˜ค๋ฅ˜๊ฐ€ ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒํ•œ๋‹ค.
  2. ๋ณ€๊ฒฝ ์ด๋ ฅ ์ถ”์ ์˜ ์–ด๋ ค์›€: Git์„ ํ†ตํ•ด ๋ˆ„๊ฐ€ ํ•ด๋‹นํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋ˆ„๊ฐ€ ์ž‘์„ฑํ–ˆ๋Š”์ง€ ๊นŒ์ง€๋Š” ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ˜์˜๋œ ์‹œ์ ์ด๋‚˜ ๋‹ด๋‹น์ž๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
  3. ํ™˜๊ฒฝ๋ณ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ถˆ์ผ์น˜: ์ฟผ๋ฆฌ ๋ฐ˜์˜ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ˆ„๋ฝ์œผ๋กœ ์ธํ•ด ํ™˜๊ฒฝ๋ณ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๋“ค์ด ๋งค์šฐ ๋งŽ๋‹ค.

์‹ค์ œ๋กœ ๋ฐฐํฌ ์•ˆ์ •์„ฑ๊ณผ ํšจ์œจ์„ฑ์„ ์ €ํ•˜์‹œํ‚ฌ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฐœ๋ฐœ์ž ๊ฐ„ ์†Œํ†ต ๋น„์šฉ์„ ์ฆ๊ฐ€์‹œํ‚ค๊ณ  ์žˆ์—ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ˜•์ƒ ๊ด€๋ฆฌ ๋„๊ตฌ ๋„์ž…์„ ๊ณ ๋ คํ–ˆ๊ณ  Liquibase์™€ Flyway ์ค‘ ๊ณ ๋ฏผ์„ ํ•˜๋‹ค๊ฐ€ ํ•™์Šต ๊ณก์„ ์ด ๋‚ฎ๊ณ , SQL ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ„๋‹จํžˆ ์ž‘์„ฑ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๊ธฐ์กด ๋ฐฉ์‹๊ณผ์˜ ์œ ์‚ฌ์„ฑ์ด ๋†’์€ Flyway๋ฅผ ์„ ํƒํ–ˆ๋‹ค.

 

 

๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ˆœํžˆ Flyway๋งŒ ๋„์ž…ํ–ˆ์„ ์‹œ ๋ฌธ์ œ์ 

ํ•˜์ง€๋งŒ Flyway ๋„์ž…์„ ์œ„ํ•ด ์—ฌ๋Ÿฌ ์ƒํ™ฉ์„ ๊ณ ๋ คํ•˜๋ฉฐ ๋„์ž… ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋“ค์ด ๊ณ ๋ ค๋˜์—ˆ๋‹ค.

1. installed_by๊ฐ€ ํ•ญ์ƒ ๋™์ผํ•œ ์‚ฌ์šฉ์ž๋กœ ํ‘œ์‹œ

https://springframework.guru/database-migration-with-flyway/

Flyway๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ flyway_schema_history๋ผ๋Š” ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜์—ฌ DB ํ˜•์ƒ์„ ๊ด€๋ฆฌํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ํ…Œ์ด๋ธ”์—๋Š” installed_by ์ปฌ๋Ÿผ์ด ์žˆ์–ด ๋ˆ„๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ์ ์šฉํ–ˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ DB Connection์„ ๋™์ผํ•œ ๊ณ„์ •์œผ๋กœ ๋งบ๊ณ  ์žˆ๊ณ , Flyway๋„ ํŽธ์˜์ƒ ๋™์ผํ•œ ๊ณ„์ •์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Flyway๋ฅผ ํ†ตํ•ด ์ž‘์—…ํ•˜๋ฉด installed_by๊ฐ€ ํ•ญ์ƒ ๋™์ผํ•œ ์‚ฌ์šฉ์ž๋กœ ๊ธฐ๋ก๋˜์–ด ์‹ค์ œ๋กœ ๋ˆ„๊ฐ€ ํ•ด๋‹น ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ๋Š”์ง€ ์ถ”์ ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค. SQL ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๋ฉด Git์„ ํ†ตํ•ด ๋ณ€๊ฒฝ ์ด๋ ฅ์„ ํ™•์ธํ•  ์ˆ˜๋Š” ์žˆ๋‹ค์ง€๋งŒ, ํ˜„์žฌ๋„ SQL์ด๋‚˜ MD ํŒŒ์ผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ์ •๋ ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ข…์ข… ์žˆ์–ด ์ด๋กœ ์ธํ•ด ๋ˆ„๊ตฐ๊ฐ€ ์ •๋ ฌ์„ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๋ณ€๊ฒฝ ์ด๋ ฅ์ด ๊ธฐ๋ก๋˜์–ด ์‹ค์ œ ์ž‘์„ฑ์ž๋ฅผ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šด ์ƒํ™ฉ์ด์—ˆ๋‹ค.

2. ๋น„ํšจ์œจ์ ์ธ ๋ฐ˜์˜ ํ”„๋กœ์„ธ์Šค

Flyway๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ src/main/resources/db/migration ํด๋”์— ์ €์žฅ๋œ .sql ํŒŒ์ผ์„ ๊ธฐ์ค€์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ๋ช… ๊ทœ์น™์— ๋”ฐ๋ผ ์ž‘์„ฑ๋œ ์ฟผ๋ฆฌ ํŒŒ์ผ๋“ค์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ ์ž๋™์œผ๋กœ ์ ์šฉ๋˜๋ฉฐ ์‹คํŒจ ์‹œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ค‘์ง€๋œ๋‹ค.

์ด๋Ÿฐ ๋™์ž‘ ๋ฐฉ์‹์€ ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ•˜๋ ค๋Š” ์ž‘์—…์กฐ์ฐจ ๋งค๋ฒˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ๋ฐฐํฌํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ๋ฐœ์ƒํ•œ๋‹ค. ํŠนํžˆ ์šฐ๋ฆฌ๋Š” ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ์šฉ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘ ์—ฐ๊ฒฐํ•ด ์ž‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ, ๋งค๋ฒˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์ด ์ €ํ•˜๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•˜๋‹ค.

๋ฌผ๋ก .. 'Flyway๋Š” CLI ๋„๊ตฌ๋„ ์ œ๊ณตํ•ด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์žฌ๋ฐฐํฌ ์—†์ด๋„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ.. ๊ณผ์—ฐ ์ด๊ฒŒ ๋” ํŽธํ• ๊นŒ?'๋Š” ์˜๋ฌธ์ด๋‹ค.

3. ์—„๊ฒฉํ•œ ๋„ค์ด๋ฐ ๊ทœ์น™์œผ๋กœ ์ธํ•œ ํ•™์Šต ํ•„์š”

Flyway๋Š” ํŒŒ์ผ๋ช…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฒ„์ „์„ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํŒŒ์ผ๋ช…์„ ์—„๊ฒฉํ•œ ๊ทœ์น™์— ๋”ฐ๋ผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค. 

https://www.red-gate.com/blog/database-devops/flyway-naming-patterns-matter

๊ทธ๋ ‡๊ธฐ์— ํŒ€ ์ „์ฒด ๊ฐœ๋ฐœ์ž๋“ค์ด ์ด๋Ÿฐ ๋„ค์ด๋ฐ ๊ทœ์น™์„ ์ค€์ˆ˜ํ•˜๊ธฐ ์œ„ํ•ด ํ•™์Šต์„ ํ•ด์•ผ ํ•˜๋Š” ์ถ”๊ฐ€ ๋น„์šฉ์ด ๋ฐœ์ƒํ•œ๋‹ค. ์ฐธ๊ณ ๋กœ Flyway๋กœ ํ•จ๊ป˜ ์ผํ•˜๊ธฐ, ๋ฒ„์ „ ์ถฉ๋Œ ํ”ผํ•˜๊ธฐ ๊ฐ™์€ ์•„ํ‹ฐํด์—์„œ ์–ธ๊ธ‰๋œ ์‚ฌ๋ก€๋“ค ์—ญ์‹œ ์ถฉ๋ถ„ํžˆ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋„ค์ด๋ฐ ๊ทœ์น™์ด ๋”์šฑ ๋ณต์žกํ•ด์ง„๋‹ค.

4. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํŒจ ์‹œ ๋ณต์žกํ•œ ๋ณต๊ตฌ ์ ˆ์ฐจ

Flyway ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ ๋ณต๊ตฌ ์ ˆ์ฐจ๊ฐ€ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์€๋ฐ, repair ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ flyway_schema_history ํ…Œ์ด๋ธ”์—์„œ ์‹คํŒจํ•œ ํ•ญ๋ชฉ(success = FALSE)์„ ์ˆ˜๋™์œผ๋กœ ์ œ๊ฑฐํ•œ ๋’ค ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ์ด๋Ÿฌํ•œ ์ ˆ์ฐจ ๋˜ํ•œ ํ•™์Šต์ด ํ•„์š”ํ•ด ํŒ€์›๋“ค์—๊ฒŒ ์ถ”๊ฐ€์ ์ธ ์‹œ๊ฐ„ ๋น„์šฉ์„ ์œ ๋ฐœํ•œ๋‹ค.

5. ์‚ฌํ›„ ์ฟผ๋ฆฌ ๊ด€๋ฆฌ์˜ ์ด์ค‘์„ฑ

๋ฐฐํฌ ํ›„ ๋ณ„๋„๋กœ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ์‚ฌํ›„ ์ฟผ๋ฆฌ๋Š” Flyway๋กœ ๊ด€๋ฆฌ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ๊ฒฐ๊ตญ ์‚ฌํ›„ ์ฟผ๋ฆฌ๋Š” ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด์ค‘์ ์ธ ๊ด€๋ฆฌ๊ฐ€ ๋˜์–ด ๊ด€๋ฆฌํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚œ๋‹ค.

๋ณ„๋„๋กœ afterMigrate๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์ „๋ถ€ ์™„๋ฃŒ๋œ ์งํ›„ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋˜๊ฒŒ ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ์‹คํ–‰ ์‹œ์ ์„ ์ž„์˜๋กœ ์ง€์ •ํ•  ์ˆ˜๋Š” ์—†๊ธฐ์— ์ด๋Ÿฐ ๊ธฐ๋Šฅ์€ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜๋‹ค.

6. ๋ณ€๊ฒฝ ์ด๋ ฅ์˜ ํŒŒ์•… ์–ด๋ ค์›€

์•„๊นŒ 1๋ฒˆ์—์„œ flyway_schema_history ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋“ค ๊ฐ’์„ ๋ดค๋“ฏ์ด script ์ปฌ๋Ÿผ์˜ ๊ฒฝ์šฐ ๋ฐ˜์˜ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํŒŒ์ผ๋ช…์„ ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ๊ฐ ํ™˜๊ฒฝ์—์„œ ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ˜์˜๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐ˜์˜๋œ SQL ํŒŒ์ผ์„ ์ง์ ‘ ์ฐพ์•„์„œ ์—ด์–ด๋ด์•ผ ํ•˜๋Š” ๋ถˆํŽธํ•จ์ด ์กด์žฌํ•œ๋‹ค.

 

 

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด DB ํ˜•์ƒ ๊ด€๋ฆฌ ์›น ๊ตฌ์ถ•

๊ฒฐ๊ตญ ๊ธฐ์กด๋ณด๋‹ค ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ๋ฐฐํฌ์™€ ๊ด€๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ ์ž ๋„์ž…์„ ๊ฒ€ํ† ํ•œ Flyway๋Š” ์˜คํžˆ๋ ค ์ƒˆ๋กœ์šด ํ•™์Šต ๋น„์šฉ๊ณผ ์—„๊ฒฉํžˆ ์ง€์ผœ์•ผ ํ•  ๊ทœ์น™๋“ค์ด ์ถ”๊ฐ€๋จ์œผ๋กœ์จ, ๊ธฐ์กด ๋ฐฉ์‹๋ณด๋‹ค ๋” ํฐ ๋ถˆํŽธ์„ ์ดˆ๋ž˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•˜๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ๊ณ ๋ฏผ ๋์— Flyway์˜ ๊ฐ•์ ์€ ์œ ์ง€ํ•˜๋˜ ๋‹จ์ ๋“ค์„ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ๋Š” ์›น ๊ธฐ๋ฐ˜์˜ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค. ์ง€๊ธˆ๋ถ€ํ„ฐ๋Š” ํŽธ์˜์„ฑ์„ ์œ„ํ•ด DMM(Database Migration Manager)์œผ๋กœ ๋ถ€๋ฅด๊ฒ ๋‹ค.

์ฐธ๊ณ ๋กœ ํ™”๋ฉด์€ ํƒ€์ž„๋ฆฌํ”„๋กœ ๊ทธ๋ ธ๋Š”๋ฐ Cursor์˜ ๋„์›€์„ ๋งŽ์ด ๋ฐ›์•˜๋‹ค. ์ƒ์ „ ์ฒ˜์Œ ๋งŒ๋“ค์–ด๋ณด๋Š” ํ™”๋ฉด์ธ๋ฐ๋„ ๊ฝค๋‚˜ ํ€„๋ฆฌํ‹ฐ๊ฐ€ ์ž˜ ๋‚˜์™”๋‹ค.

1. ๋กœ๊ทธ์ธ ํ™”๋ฉด

  • ํ™˜๊ฒฝ ์„ ํƒ ์ง€์›: ์ ‘์†ํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™˜๊ฒฝ ์„ ํƒ
  • ID/PW: ์‹ค์ œ DB ์ ‘๊ทผ ์‹œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐœ๊ธ‰๋ฐ›์€ ๋ณธ์ธ์˜ ๊ณ„์ • ์ž…๋ ฅ
  • ์Šคํ‚ค๋งˆ: ์ ‘์†ํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ์ด๋ฆ„ ์ž…๋ ฅ
  • ๋กœ๊ทธ์ธ ์ •๋ณด ๊ธฐ์–ต: 30์ผ๊ฐ„ ๋ธŒ๋ผ์šฐ์ € ์ƒˆ๋กœ๊ณ ์นจ ํ›„์—๋„ ์ž…๋ ฅ์ •๋ณด๋ฅผ ์œ ์ง€

์—ฌ๊ธฐ์„œ ๋กœ๊ทธ์ธํ•œ ๊ณ„์ •์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด DB Connection์„ ๋งบ์–ด๋†“๋Š”๋‹ค.

private final Map<String, DataSource> userDataSources = new ConcurrentHashMap<>();
private final Map<String, JdbcTemplate> userJdbcTemplates = new ConcurrentHashMap<>();

public boolean connection(String dbEnv, String dbId, String dbPassword, String schema) {
    // ํ™˜๊ฒฝ์— ๋งž๋Š” JDBC URL ์ƒ์„ฑ
    String jdbcUrl = buildJdbcUrl(dbEnv, schema);  
    // ์‚ฌ์šฉ์ž ๊ณ ์œ  ํ‚ค ์ƒ์„ฑ
    String userKey = generateUserKey(dbId, dbEnv, schema);  

    try {
        // ๊ธฐ์กด ์—ฐ๊ฒฐ์ด ์žˆ๋‹ค๋ฉด ์ •๋ฆฌ
        cleanupExistingConnection(userKey);

        // ์ƒˆ๋กœ์šด ์—ฐ๊ฒฐ ์ƒ์„ฑ
        DataSource newDataSource = createDataSource(jdbcUrl, dbId, dbPassword);
        JdbcTemplate newJdbcTemplate = new JdbcTemplate(newDataSource);

        try (Connection connection = newDataSource.getConnection()) {
            // ์—ฐ๊ฒฐ ์„ฑ๊ณต ์‹œ ์‚ฌ์šฉ์ž๋ณ„ ์ •๋ณด ์ €์žฅ
            userDataSources.put(userKey, newDataSource);
            userJdbcTemplates.put(userKey, newJdbcTemplate);
            return true;
        }
    } catch (SQLException e) {
        throw new RuntimeException("๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์‹คํŒจ: " + e.getMessage());
    }
}

๊ทธ๋ฆฌ๊ณ  ๋ณ„๋„์˜ DB๊ฐ€ ์•„๋‹Œ ๋กœ๊ทธ์ธํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์Šคํ‚ค๋งˆ์— ์žˆ๋Š” flyway_schema_history ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•œ๋‹ค. DMM ํ”„๋กœ์ ํŠธ ๋ง๊ณ ๋Š” Flyway๋ฅผ ์ „ํ˜€ ์˜์กดํ•˜๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ Flyway ๊ด€๋ จ ํ…Œ์ด๋ธ”์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.

๋”ฐ๋ผ์„œ DMM์—์„œ๋Š” ๋กœ๊ทธ์ธ ์‹œ, ์ ‘์†ํ•œ ์Šคํ‚ค๋งˆ์— flyway_schema_history ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ฉฐ, ํ•ด๋‹น ํ…Œ์ด๋ธ”์ด ์—†์„ ๊ฒฝ์šฐ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ ๋’ค ์ง„์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•ˆ๋‚ด ๋ฌธ๊ตฌ๋ฅผ ํ‘œ์‹œํ•˜๋„๋ก ํ•˜์—ฌ ์ƒˆ๋กœ์šด ์Šคํ‚ค๋งˆ์—์„œ๋„ ์–ธ์ œ๋“ ์ง€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

 

2. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ด๋ ฅ ์กฐํšŒ ๋ฐ ๊ด€๋ฆฌ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ด๋ ฅ ๊ด€๋ฆฌ ํ™”๋ฉด

๋กœ๊ทธ์ธํ•˜๋ฉด ๋ณด์ด๋Š” ๋ฉ”์ธ ํŽ˜์ด์ง€๋‹ค. ํŠน์ • ํ™˜๊ฒฝ์—์„œ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ•˜๊ณ , ๋ฐ˜์˜ ๋‚ด์—ญ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋Œ€์ถฉ ํ˜„์žฌ ํ™”๋ฉด ํ•˜๋‚˜๋งŒ ๋ด๋„ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹ค์‹œ๊ฐ„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ด๋ ฅ ์กฐํšŒ

  • ๋ฆฌ์ŠคํŠธ์—์„œ ์›ํ•˜๋Š” ํ–‰(row)์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ‚ค๋ณด๋“œ ํ™”์‚ดํ‘œ๋ฅผ ์‚ฌ์šฉํ•ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์„ ํƒํ•œ ํ–‰์— ๋ฐ˜์˜๋œ SQL์ด ํ•˜๋‹จ์— ์ž๋™์œผ๋กœ ํ‘œ์‹œ๋œ๋‹ค.
  • ํŽ˜์ด์ง€๋„ค์ด์…˜, ์ •๋ ฌ, ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ด๋ ฅ์„ ํšจ์œจ์ ์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

์šฐ์ธก ์ƒ๋‹จ์˜ + Migration ๊ด€๋ฆฌ ๋ฒ„ํŠผ

  • ์‹ ๊ทœ Migration ๋“ฑ๋ก
  • ํ™˜๊ฒฝ ๊ฐ„ Migration ๋น„๊ต
  • ์Šคํ‚ค๋งˆ ๋น„๊ต

์šฐ์ธก ์ƒ๋‹จ์˜ + Migration ๊ด€๋ฆฌ ๋ฒ„ํŠผ์—์„œ ์ œ๊ณตํ•ด ์ฃผ๋Š” ๊ธฐ๋Šฅ๋“ค์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

 

3. ์‹ ๊ทœ Migration(์ฟผ๋ฆฌ) ๋“ฑ๋ก

DB ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ ๊ธฐ์กด์—๋Š” ๊ฐ์ž DBMS๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ–ˆ์ง€๋งŒ DMM์ด ๋„์ž…๋˜๊ณ ๋‚œ ์ดํ›„๋ถ€ํ„ฐ๋Š” ๋ชจ๋“  ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  DML ๋ฐ DDL ์ฟผ๋ฆฌ๋ฐ˜์˜์€ ์—ฌ๊ธฐ์„œ ๋ฐ˜์˜์„ ํ•˜๋„๋ก ํŒ€ ๋‚ด ์ฟผ๋ฆฌ ๋ฐ˜์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

SQL ํŒŒ์ผ ์—…๋กœ๋“œ ๋˜๋Š” ์ง์ ‘ ์ž…๋ ฅ ๋ฐฉ์‹์„ ๋ชจ๋‘ ์ง€์›ํ•˜๋ฉฐ, ์ž…๋ ฅ๋œ SQL์€ ํŒŒ์ผ๋กœ ์ƒ์„ฑ๋œ ํ›„ S3 ์ €์žฅ์†Œ์— ์—…๋กœ๋“œ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ดํ›„ Flyway๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜๋œ๋‹ค.(์ฐธ๊ณ ๋กœ Flyway์˜ S3 ์ง€์›์€ Flyway v7.0๋ถ€ํ„ฐ ์ œ๊ณต๋œ๋‹ค.)

๋งŒ์•ฝ Flyway๋งŒ ๋‹จ์ˆœํžˆ ๋„์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค Flyway ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  src/main/resources/db/migration ๊ฒฝ๋กœ์— SQL ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ DMM ๋•๋ถ„์— ๊ฐ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Flyway์— ๋Œ€ํ•ด ์ „ํ˜€ ์•Œ ํ•„์š”๊ฐ€ ์—†๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ฐ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Flyway๋ฅผ ์ „ํ˜€ ์˜์กดํ•˜์ง€ ์•Š์•„๋„ ๋จ.

๊ทธ๋ฆฌ๊ณ  Flyway๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ ์ •๋ณด์— ๋”ฐ๋ผ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ ๋ฐ˜์˜ ์‹œ๋งˆ๋‹ค ๋งค๋ฒˆ ์ƒˆ๋กœ์šด Flyway ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•œ๋‹ค.

/**
 * Flyway๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹คํ–‰
 * ์ฃผ์˜: ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ DB ์ •๋ณด๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์‹คํ–‰๋จ
 */
private void executeMigration(JdbcTemplate jdbcTemplate, String env, String dbId) {
    Flyway flyway = createFlywayInstance(jdbcTemplate, env, dbId);
    try {
        flyway.migrate();
        logger.info("Migration applied successfully");
    } catch (Exception e) {
        logger.error("Migration failed", e);
        throw e;
    }
}

/**
 * Flyway ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„ค์ •
 */
private Flyway createFlywayInstance(JdbcTemplate jdbcTemplate, String env, String dbId) {
    String schema = getSchemaFromSession();
    
    /**
     * S3 URL ํ˜•์‹: s3:<bucket>(/optionalfolder/subfolder)
     * https://documentation.red-gate.com/fd/locations-224919725.html
     */
    String s3Location = String.format("s3:%s/%s/%s",
                                      getBucketName(env),
                                      MIGRATION_BASE_PATH,
                                      schema);

    return Flyway.configure()
                 .dataSource(jdbcTemplate.getDataSource())
                 .installedBy(dbId)
                 .locations(s3Location)
                 .baselineOnMigrate(true)
                 .outOfOrder(true)
                 .schemas(schema)
                 .load();
}

์Šคํฌ๋ฆฝํŠธ์˜ ๋ฒ„์ „์€ ํƒ€์ž„์Šคํƒฌํ”„ ํ˜•์‹์œผ๋กœ ์ž๋™ ์ƒ์„ฑ๋˜๋ฉฐ, ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜์—ฌ ๋ฒ„์ „ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ–ˆ๋‹ค. ํƒ€์ž„์Šคํƒฌํ”„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™์œผ๋กœ ๋ฒ„์ „์ด ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋ฒ„์ „์„ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋„๋ก ํ•˜์˜€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฒ„์ „๋ช… ๋’ค์— ๋ถ™์„ ๋„ค์ด๋ฐ์—๋Š” '์Šค์ฟผ๋“œ๋ช…'๊ณผ '์Šคํ”„๋ฆฐํŠธ ๋ฒ„์ „'์„ ๊ธฐ์ž…ํ•˜๋„๋ก ํ•˜์—ฌ ํ›„์— ์กฐํšŒ ํ™”๋ฉด์—์„œ ํ•„ํ„ฐ๋ง์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์œ ๋„ํ–ˆ๋‹ค.

์ฟผ๋ฆฌ ๋ฐ˜์˜ ์„ฑ๊ณต

์ฟผ๋ฆฌ ๋ฐ˜์˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉด, ๋ฆฌ์ŠคํŠธ์— ๋ฐฉ๊ธˆ ์ถ”๊ฐ€ํ•œ ํ•ญ๋ชฉ์ด ๋ฐ˜์˜๋œ๋‹ค.

์ฟผ๋ฆฌ ๋ฐ˜์˜ ์„ฑ๊ณต ํ™”๋ฉด

์ฟผ๋ฆฌ ๋ฐ˜์˜ ์‹คํŒจ

์ฟผ๋ฆฌ ๋ฐ˜์˜ ์‹คํŒจ ํ™”๋ฉด

์ฟผ๋ฆฌ ๋ฐ˜์˜์— ์‹คํŒจํ•˜๋ฉด, ์‹คํŒจ ์›์ธ์— ๋Œ€ํ•œ ์•Œ๋ฆผ๊ณผ ํ•จ๊ป˜ ํ•ด๋‹น ์ƒํƒœ๊ฐ€ ์‹คํŒจ๋กœ ๊ธฐ๋ก๋œ๋‹ค. ์‹คํŒจํ•œ ๊ธฐ๋ก์„ ์‚ญ์ œํ•˜์ง€ ์•Š์œผ๋ฉด Flyway์˜ ํŠน์„ฑ์ƒ ์ดํ›„ ๋ชจ๋“  SQL ๋ฐ˜์˜ ์‹œ๋„๊ฐ€ ์‹คํŒจํ•˜๊ฒŒ ๋œ๋‹ค. ์‹คํŒจํ•œ ๊ธฐ๋ก์€ ํœด์ง€ํ†ต ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜์—ฌ ์†์‰ฝ๊ฒŒ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

Flyway๋งŒ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด, flyway_schema_history ํ…Œ์ด๋ธ”์— ๊ธฐ๋ก๋œ ์‹คํŒจ ์ƒํƒœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์‚ญ์ œํ•˜๊ณ , SQL์„ ์ˆ˜์ •ํ•œ ํ›„ ์žฌ๋ฐฐํฌํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด์ง€๋งŒ ํด๋ฆญ ํ•œ ๋ฒˆ์œผ๋กœ ์‹คํŒจ ๊ธฐ๋ก์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์–ด, ๋ณต์žกํ•œ ๊ณผ์ •์„ ๊ฐ„์†Œํ™”ํ•˜๊ณ  ๊ฐœ๋ฐœ์ž ํŽธ์˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œ์ผฐ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€ ๋ฐ˜์˜ ์ค‘์ผ ๊ฒฝ์šฐ

Flyway ์ž‘์—…์ด ์ง„ํ–‰ ์ค‘์ผ ๋•Œ ๋‹ค๋ฅธ ์ž‘์—…์ด ๋™์‹œ์— ๋ฐ˜์˜๋˜๋ฉด ํŒŒ์ผ ์ƒ์„ฑ ์ˆœ์„œ์™€ ๋ฐ˜์˜์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž‘์—… ์ „ํ›„์— ๋ฝ์„ ๊ฑธ์–ด ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋œ ํ›„์— ๋™์ž‘ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค.(์ฐธ๊ณ ๋กœ ์ด๋ฅผ ์œ„ํ•ด 1๋ฒˆ์—์„œ ๋กœ๊ทธ์ธ ์‹œ์— flyway_schema_history ๋ง๊ณ ๋„ lock ๊ด€๋ จ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜ ๋” ์ƒ์„ฑํ•œ๋‹ค.)

 

4. ํ™˜๊ฒฝ ๊ฐ„ Migration ๋น„๊ต ๋ฐ ์ ์šฉ

์‚ฌ์‹ค์ƒ DMM์„ ํ•˜๊ฒŒ ๋œ ์ด์œ ์ด์ž ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ด๋‹ค. ํŠน์ • ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ์ด ์™„๋ฃŒ๋œ ํ›„, ๋‹ค๋ฅธ ํ™˜๊ฒฝ์œผ๋กœ ๋ฐฐํฌํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ˜„์žฌ DEV ํ™˜๊ฒฝ์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ˜์˜๋˜์–ด ์žˆ์ง€๋งŒ, QA ํ™˜๊ฒฝ์—๋Š” ๋ฐ˜์˜๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋ฅผ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•˜๊ณ  ์ผ๊ด„์ ์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ˆ„๋ฝ๋œ Migration ํ™•์ธ

์—ฌ๋Ÿฌ ๋ฐฐํฌ ํ™˜๊ฒฝ๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ ํ˜„์žฌ ํ™˜๊ฒฝ์—์„œ ๋ฐ˜์˜๋˜์ง€ ์•Š์€ ์ฟผ๋ฆฌ๋“ค์„ ํ•œ๋ˆˆ์— ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ํ™˜๊ฒฝ๋ณ„ DB์˜ flyway_schema_history๋ฅผ ๋น„๊ตํ•ด ๋ฒ„์ „์ด ์ผ์น˜ํ•˜์ง€ ์•Š์€ ๊ฒƒ๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค. 

๋ˆ„๋ฝ๋œ Migration ์ผ๊ด„ ์ ์šฉ

ํ™•์ธ๋œ ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋“ค์€ ์„ ํƒ ํ›„ ํ•œ ๋ฒˆ์— ํ•ด๋‹น ํ™˜๊ฒฝ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์„ ํƒํ•œ ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋Š” ์„ ํƒ ์ˆœ์„œ์™€ ๊ด€๊ณ„์—†์ด ๋ฒ„์ „ ์ˆœ์„œ๋Œ€๋กœ ์ž๋™ ์ ์šฉ๋˜๋ฏ€๋กœ, ์ ์šฉ ์ˆœ์„œ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋˜ ๋ฌธ์ œ๋ฅผ ์ดˆ๊ธฐ์— ๋ฐฉ์ง€ํ•˜๊ณ  ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œ์ผฐ๋‹ค.

๊ฐ€์žฅ ํฐ ๋„์›€์ด ๋˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ, ๊ฐœ๋ฐœ ํŠน์„ฑ์ƒ DEV ํ™˜๊ฒฝ์—์„œ ๊ผญ ์šฐ์„ ์ ์œผ๋กœ ์ฟผ๋ฆฌ ๋ฐ˜์˜์ด ์ผ์–ด๋‚˜์•ผ ํ•œ๋‹ค๊ฑฐ๋‚˜ ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. QA ํ™˜๊ฒฝ์— ๋ฐฐํฌ๋œ ์ดํ›„ bugfix ๊ณผ์ •์—์„œ QA ํ™˜๊ฒฝ์—๋งŒ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜์˜ํ•˜๊ณ  ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ์Šคํ…Œ์ด์ง• ๋˜๋Š” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—๋Š” ๋ฐ˜์˜ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜, ๋ฐ˜๋Œ€๋กœ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—๋งŒ ๋ฐ˜์˜ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ์•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์žฅ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ์ฟผ๋ฆฌ ๋ฐ˜์˜์ด ๋ˆ„๋ฝ๋˜์—ˆ์Œ์„ ๋๊นŒ์ง€ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•˜๋Š” ์ผ์ด ํ”ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋“ค์„ ์†์‰ฝ๊ฒŒ ์ฐพ๊ณ  ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

5. ์Šคํ‚ค๋งˆ ๋น„๊ต

ํ™˜๊ฒฝ๋ณ„ ์Šคํ‚ค๋งˆ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ์˜ ์ฐจ์ด๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ๊ธฐ์กด์— ํ™˜๊ฒฝ๋ณ„๋กœ ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๊ฐ€ ๋งŽ์•„ ์ •ํ•ฉ์„ฑ์„ ๋งž์ถ”๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์—ˆ์œผ๋ฉฐ, ์ดํ›„์—๋„ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ™•์ธํ•˜๋ฉด์„œ ์Šคํ‚ค๋งˆ์˜ ์ •ํ•ฉ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐ๋˜์–ด ๋งŒ๋“ค์—ˆ๋‹ค.

์Šคํ‚ค๋งˆ ๋น„๊ต ์š”์•ฝ
์ถ”๊ฐ€๋œ ํ…Œ์ด๋ธ” ์‹๋ณ„
์‚ญ์ œ๋œ ํ…Œ์ด๋ธ” ์‹๋ณ„

์œ„์™€ ๊ฐ™์ด ํŽธํ•˜๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

๋ณ€๊ฒฝ๋œ ํ…Œ์ด๋ธ” ์‹๋ณ„

๊ทธ๋ฆฌ๊ณ  ๋ณ€๊ฒฝ๋œ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด์„œ๋Š” ์„œ๋กœ ์ผ์น˜์‹œํ‚ค๊ธฐ ์œ„ํ•œ DDL์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ •ํ•ฉ์„ฑ์„ ๋งž์ถ”๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๊ณ ์ž ํ•˜์˜€๋‹ค.

 

 

๊ฒฐ๋ก  

ํ”„๋กœ์ ํŠธ ๋„์ž… ์ดํ›„ ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  DML ๋ฐ DDL ์ž‘์—…์€ DMM์„ ํ†ตํ•ด ๋ฐ˜์˜ํ•˜๋„๋ก DB ๋ฐ˜์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒˆ๋กญ๊ฒŒ ์ˆ˜๋ฆฝํ•˜์˜€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ ์Šคํ”„๋ฆฐํŠธ๋ฅผ ํ•œ ์‚ฌ์ดํด ๋Œ๋ ค๋ณธ ๊ฒฐ๊ณผ ํฐ ๋ฌธ์ œ์—†์ด ์•ˆ์ •์ ์œผ๋กœ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ •๋ฆฝ๋˜์—ˆ๋‹ค. DMM ๋•๋ถ„์— ๊ธฐ์กด์—๋Š” ๊ฐ์ž๊ฐ€ DBMS๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋ฐ˜์˜ํ•˜๋ฉด์„œ, ํ•ด๋‹น ํ™˜๊ฒฝ์— ์ฟผ๋ฆฌ๊ฐ€ ์ œ๋Œ€๋กœ ๋ฐ˜์˜๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ์ง€๋งŒ ์ด์ œ๋Š” ํ•œ๋ˆˆ์— ๋ฐ˜์˜ ์ƒํƒœ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ณ , ํ™˜๊ฒฝ ๊ฐ„ ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋ฅผ ์†์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ๋ˆ„๋ฝ๋œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์œผ๋กœ ์ธํ•ด ์ฑ…์ž„ ์†Œ์žฌ๋ฅผ ๋”ฐ์ง€๊ธฐ ์œ„ํ•œ ๋ถˆํ•„์š”ํ•œ ์†Œํ†ต๋„ ์ค„์—ˆ๋‹ค. ๊ธฐ์กด์—๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋”๋ผ๋„ "์ด๊ฑฐ ๋ฐ˜์˜๋œ ๊ฑธ๊นŒ?", "๋ฐ˜์˜ํ•ด๋„ ๋ ๊นŒ?", "๊ดœํžˆ ํ–ˆ๋‹ค๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ๋‚ด๊ฐ€ ์ฑ…์ž„์ ธ์•ผ ํ•  ๊ฒƒ ๊ฐ™์€๋ฐ, ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ํ•ด์ฃผ๊ฒ ์ง€"์™€ ๊ฐ™์€ ์ƒ๊ฐ ๋•Œ๋ฌธ์— ์„ ๋œป ๋ฐ˜์˜ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜์ง€๋งŒ ์ด์ œ๋Š” ๋ˆ„๋ฝ๋œ ์ฟผ๋ฆฌ๋ฅผ ๋ช…ํ™•ํžˆ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ์–ด ํ™•์ธํ•œ ์‚ฌ๋žŒ์ด ๋ฐ”๋กœ ๋ฐ˜์˜๋งŒ ํ•˜๋ฉด ๋˜๊ฒŒ ๋˜์—ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ•ญ์ƒ ๋จธ๋ฆฟ์†์— ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋˜ ์ƒ๊ฐ์€ '์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •๋ฆฝํ•˜๋Š” ๊ฒƒ์ด ๊ธฐ์กด๋ณด๋‹ค ๋” ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ์–ด๋ ต์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.'์˜€๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ๋‹จ์ˆœํžˆ Flyway๋ฅผ ๋„์ž…ํ•˜๋Š” ๋ฐ ๊ทธ์น˜์ง€ ์•Š๊ณ , ํŒ€์›๋“ค์ด ๋ณ„๋„๋กœ Flyway ๊ทœ์น™์„ ํ•™์Šตํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•˜๊ณ ์ž ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐํš๋ถ€ํ„ฐ ๋””์ž์ธ(?), ํ”„๋ก ํŠธ์—”๋“œ, ๋ฐฑ์—”๋“œ๊นŒ์ง€ ์ „๋ฐ˜์ ์œผ๋กœ ํ˜ผ์ž ์ง„ํ–‰ํ•ด ๋ณด์•˜๋Š”๋ฐ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ์„ฑ๊ณผ๊ฐ€ ๋‚˜์˜จ ๊ฒƒ ๊ฐ™๋‹ค. 

๋Œ“๊ธ€