Migration ํญ์์๋ Entity ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ํ๊ธฐ ์ํ ๋ง์ด๊ทธ๋ ์ด์
์ ์๊ฐ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค. CLI์ pnpm migrate ๋ช
๋ น์ด๋ฅผ UI๋ก ๋์ฒดํฉ๋๋ค.
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");
});
}
๋ง์ด๊ทธ๋ ์ด์
์คํ
๋จ์ผ ๋ง์ด๊ทธ๋ ์ด์
์คํ
- ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ ์ ํ
- [Apply] ๋ฒํผ ํด๋ฆญ
- ํ์ธ ๋ชจ๋ฌ์์ [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] ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๋๊ธฐ ์ค์ธ ๋ชจ๋ ๋ง์ด๊ทธ๋ ์ด์
์ ์์๋๋ก ์คํํฉ๋๋ค.
ํ๋ก๋์
์ฃผ์: ํ๋ก๋์
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ง์ด๊ทธ๋ ์ด์
์ ์คํํ๊ธฐ ์ ์๋ ๋ฐ๋์ ๋ฐฑ์
ํ์ธ์.
๋ง์ด๊ทธ๋ ์ด์
๋กค๋ฐฑ
๋จ์ผ ๋กค๋ฐฑ
- Applied ์ํ์ ๋ง์ด๊ทธ๋ ์ด์
์ ํ
- [Rollback] ๋ฒํผ ํด๋ฆญ
- ํ์ธ ๋ชจ๋ฌ์์ [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
์์ ๋ณ๊ฒฝ
์์๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๋ ๊ฒฝ์ฐ:
- ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ๋ช
์ ํ์์คํฌํ ์์
- ํ์ผ ์์คํ
์์ ์ง์ ๋ณ๊ฒฝ
- 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์ ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ ์ปค๋ฐ
- ์ปค๋ฐ ๋ฉ์์ง์ ๋ณ๊ฒฝ ๋ด์ฉ ๋ช
์
- ํ์๋ค๊ณผ ๋ง์ด๊ทธ๋ ์ด์
์์ ๊ณต์
๋ค์ ๋จ๊ณ