๋ฉ”์ธ ์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
Migration ํƒญ์—์„œ๋Š” Entity ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹œ๊ฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CLI์˜ pnpm migrate ๋ช…๋ น์–ด๋ฅผ UI๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

Migration ํƒญ ๊ตฌ์กฐ

Migration ๊ด€๋ฆฌ ํ™”๋ฉด

Migration ํƒญ์€ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์˜์—ญ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค:
  • ์™ผ์ชฝ Sidebar: ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋ชฉ๋ก (Pending/Applied ์ƒํƒœ๋ณ„๋กœ ๊ทธ๋ฃนํ™”)
  • ์˜ค๋ฅธ์ชฝ Content: ์„ ํƒํ•œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์˜ ์ƒ์„ธ ์ •๋ณด์™€ Preview

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ƒํƒœ ํ™•์ธ

Status ํ™•์ธ

[Check Status] ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ˜„์žฌ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ƒํƒœ์„ค๋ช…ํ‘œ์‹œ
Pending์•„์ง ์ ์šฉ๋˜์ง€ ์•Š์€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๐Ÿ“‹ ๋…ธ๋ž€์ƒ‰
Applied์ด๋ฏธ ์ ์šฉ๋œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜โœ… ์ดˆ๋ก์ƒ‰
Failed์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒโŒ ๋นจ๊ฐ„์ƒ‰

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณ„ ์ƒํƒœ

์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์„ค์ •๋œ ๊ฒฝ์šฐ ๊ฐ DB์˜ ์ƒํƒœ๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
Development Master: โœ… Up to date (v20240115_143022)
Testing: โš ๏ธ 2 pending migrations
Production: โœ… Up to date (v20240115_143022)

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ƒ์„ฑ

Entity๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด Sonamu๊ฐ€ ์ž๋™์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ž๋™ ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ

๋‹ค์Œ๊ณผ ๊ฐ™์€ Entity ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ:
๋ณ€๊ฒฝ ํƒ€์ž…์˜ˆ์‹œ
ํ…Œ์ด๋ธ” ์ƒ์„ฑ์ƒˆ Entity ์ถ”๊ฐ€
์ปฌ๋Ÿผ ์ถ”๊ฐ€Property ์ถ”๊ฐ€
์ปฌ๋Ÿผ ์ˆ˜์ •ํƒ€์ž…/๊ธธ์ด ๋ณ€๊ฒฝ
์ปฌ๋Ÿผ ์‚ญ์ œProperty ์‚ญ์ œ
์ธ๋ฑ์Šค ์ถ”๊ฐ€Index ์ถ”๊ฐ€
์™ธ๋ž˜ํ‚ค ์ถ”๊ฐ€belongsTo ๊ด€๊ณ„ ์ถ”๊ฐ€

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ ํ™•์ธ

์ƒ์„ฑ๋œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ํด๋ฆญํ•˜๋ฉด ๋‚ด์šฉ์„ ๋ฏธ๋ฆฌ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
import type { Knex } from "knex";

export async function up(knex: Knex): Promise<void> {
  await knex.schema.alterTable("users", (table) => {
    table.string("phone", 20).nullable();
  });
}

export async function down(knex: Knex): Promise<void> {
  await knex.schema.alterTable("users", (table) => {
    table.dropColumn("phone");
  });
}

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰

๋‹จ์ผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰

  1. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ ์„ ํƒ
  2. [Apply] ๋ฒ„ํŠผ ํด๋ฆญ
  3. ํ™•์ธ ๋ชจ๋‹ฌ์—์„œ [Confirm] ํด๋ฆญ
์‹คํ–‰ ๊ณผ์ •:
Development Master:
  โœ“ 20240116_101530_add_user_phone (0.2s)

Testing:
  โœ“ 20240116_101530_add_user_phone (0.2s)

All migrations applied successfully!

๋ชจ๋“  Pending ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰

[Run All] ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋Œ€๊ธฐ ์ค‘์ธ ๋ชจ๋“  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
ํ”„๋กœ๋•์…˜ ์ฃผ์˜: ํ”„๋กœ๋•์…˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์ „์—๋Š” ๋ฐ˜๋“œ์‹œ ๋ฐฑ์—…ํ•˜์„ธ์š”.

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋กค๋ฐฑ

๋‹จ์ผ ๋กค๋ฐฑ

  1. Applied ์ƒํƒœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์„ ํƒ
  2. [Rollback] ๋ฒ„ํŠผ ํด๋ฆญ
  3. ํ™•์ธ ๋ชจ๋‹ฌ์—์„œ [Confirm] ํด๋ฆญ
๋กค๋ฐฑ ๊ณผ์ •:
Rolling back last migration...

Development Master:
  โœ“ Rollback 20240116_101530_add_user_phone

Rollback completed successfully!
๋ฐ์ดํ„ฐ ์†์‹ค ์œ„ํ—˜: ๋กค๋ฐฑ์€ ํ…Œ์ด๋ธ”์ด๋‚˜ ์ปฌ๋Ÿผ์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์†์‹ค๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Migration Preview

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์–ด๋–ค ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ• ์ง€ ๋ฏธ๋ฆฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Preview ๋‚ด์šฉ

๐Ÿ“‹ Migration: 20240116_101530_add_user_profile

Changes:
  โœ… Table: users
     + column: profile_image (string, nullable)
     + column: bio (text, nullable)
     + index: (email) unique
  
  โš ๏ธ Table: posts
     - column: deprecated_field
     โš ๏ธ Warning: Data in this column will be lost!
์•„์ด์ฝ˜ ์˜๋ฏธ:
  • โœ… ์ถ”๊ฐ€: ์ƒˆ๋กœ์šด ํ…Œ์ด๋ธ”/์ปฌ๋Ÿผ/์ธ๋ฑ์Šค
  • ๐Ÿ”„ ์ˆ˜์ •: ๊ธฐ์กด ์ปฌ๋Ÿผ ํƒ€์ž…/๊ธธ์ด ๋ณ€๊ฒฝ
  • โš ๏ธ ์‚ญ์ œ: ํ…Œ์ด๋ธ”/์ปฌ๋Ÿผ ์‚ญ์ œ (๋ฐ์ดํ„ฐ ์†์‹ค ๊ฐ€๋Šฅ)

๋‹ค์ค‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ

Sonamu๋Š” ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋™์‹œ์— ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ ํƒ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰ ์‹œ ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
  • โ˜‘๏ธ Development Master
  • โ˜‘๏ธ Testing
  • โ˜ Production (์ˆ˜๋™ ์„ ํƒ)
๊ธฐ๋ณธ์ ์œผ๋กœ _master๋กœ ๋๋‚˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ test ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ž๋™์œผ๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์„ ํƒํ•ด์•ผ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆœ์„œ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ํŒŒ์ผ๋ช…์˜ ํƒ€์ž„์Šคํƒฌํ”„ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค:
โœ… 20240115_120000_create_users_table.ts
โœ… 20240115_130000_create_posts_table.ts
๐Ÿ“‹ 20240116_101530_add_user_phone.ts      โ† ๋‹ค์Œ ์‹คํ–‰
๐Ÿ“‹ 20240116_102045_add_post_tags.ts

์ˆœ์„œ ๋ณ€๊ฒฝ

์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ:
  1. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ๋ช…์˜ ํƒ€์ž„์Šคํƒฌํ”„ ์ˆ˜์ •
  2. ํŒŒ์ผ ์‹œ์Šคํ…œ์—์„œ ์ง์ ‘ ๋ณ€๊ฒฝ
  3. UI์—์„œ ์ƒˆ๋กœ๊ณ ์นจ
์™ธ๋ž˜ํ‚ค ๊ด€๊ณ„ ์ฃผ์˜: ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์ด ๋จผ์ € ์ƒ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: posts.user_id โ†’ users.id ๊ด€๊ณ„๋ผ๋ฉด users ํ…Œ์ด๋ธ”์„ ๋จผ์ € ์ƒ์„ฑํ•ด์•ผ ํ•จ

๋ฌธ์ œ ํ•ด๊ฒฐ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํŒจ

์ฆ์ƒ: ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์›์ธ ๋ฐ ํ•ด๊ฒฐ:
์˜ค๋ฅ˜์›์ธํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
Foreign key constraint์ฐธ์กฐ ํ…Œ์ด๋ธ”์ด ์—†์Œ์ฐธ์กฐ ํ…Œ์ด๋ธ”์„ ๋จผ์ € ์ƒ์„ฑ
Column already exists์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ปฌ๋Ÿผ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ ํ™•์ธ
Cannot drop column๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ œ์•ฝ์กฐ๊ฑด ์กด์žฌ์ œ์•ฝ์กฐ๊ฑด ๋จผ์ € ์‚ญ์ œ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ธฐ๋ก ๋ถˆ์ผ์น˜

์ฆ์ƒ: ์‹ค์ œ DB ์ƒํƒœ์™€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ธฐ๋ก์ด ๋‹ค๋ฆ„ ํ•ด๊ฒฐ:
# CLI์—์„œ ์‹คํ–‰
pnpm migrate clear  # ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ธฐ๋ก ์‚ญ์ œ
pnpm migrate status # ํ˜„์žฌ ์ƒํƒœ ํ™•์ธ

๋กค๋ฐฑ ๋ถˆ๊ฐ€๋Šฅ

์ฆ์ƒ: ๋กค๋ฐฑ ์‹œ๋„ ์‹œ ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์›์ธ: down() ํ•จ์ˆ˜๊ฐ€ ์ œ๋Œ€๋กœ ์ •์˜๋˜์ง€ ์•Š์Œ ํ•ด๊ฒฐ: ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ์—ด์–ด down() ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •

์‹ค์ „ ํŒ

1. ์ž‘์€ ๋‹จ์œ„๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

# โŒ ๋‚˜์œ ์˜ˆ: ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ•œ ๋ฒˆ์—
- 10๊ฐœ Entity ๋™์‹œ ์ˆ˜์ •
- ํ•œ ๋ฒˆ์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰

# โœ… ์ข‹์€ ์˜ˆ: ์ž‘์€ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„๊ธฐ
- Entity 1๊ฐœ์”ฉ ์ˆ˜์ •
- ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰
- ํ…Œ์ŠคํŠธ ํ›„ ๋‹ค์Œ Entity ์ง„ํ–‰

2. ํ”„๋กœ๋•์…˜ ์ „ ํ…Œ์ŠคํŠธ

1. Development DB์—์„œ ํ…Œ์ŠคํŠธ
   โ†“
2. Testing DB์—์„œ ๊ฒ€์ฆ
   โ†“
3. ๋ฐ์ดํ„ฐ ๋ฐฑ์—…
   โ†“
4. Production DB์— ์ ์šฉ

3. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ธฐ๋ก ๊ด€๋ฆฌ

  • Git์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ ์ปค๋ฐ‹
  • ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์— ๋ณ€๊ฒฝ ๋‚ด์šฉ ๋ช…์‹œ
  • ํŒ€์›๋“ค๊ณผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆœ์„œ ๊ณต์œ 

๋‹ค์Œ ๋‹จ๊ณ„