메인 μ½˜ν…μΈ λ‘œ κ±΄λ„ˆλ›°κΈ°
Migration νƒ­μ—μ„œλŠ” Entity 변경사항을 λ°μ΄ν„°λ² μ΄μŠ€μ— λ°˜μ˜ν•˜κΈ° μœ„ν•œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ„ μ‹œκ°μ μœΌλ‘œ 관리할 수 μžˆμŠ΅λ‹ˆλ‹€. CLI의 pnpm migrate λͺ…λ Ήμ–΄λ₯Ό UI둜 λŒ€μ²΄ν•©λ‹ˆλ‹€.

Migration νƒ­ ꡬ쑰

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에 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ 파일 컀밋
  • 컀밋 λ©”μ‹œμ§€μ— λ³€κ²½ λ‚΄μš© λͺ…μ‹œ
  • νŒ€μ›λ“€κ³Ό λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ μˆœμ„œ 곡유

λ‹€μŒ 단계