| name | database-migration |
| description | Manage database schema changes with version control. Use when modifying DB schema, adding tables/columns, or setting up new projects. Covers Prisma, Drizzle, and migration best practices. |
| allowed-tools | Read, Glob, Grep, Edit, Write, Bash |
| license | MIT |
| metadata | {"author":"antigravity-team","version":"1.0"} |
Database Migration
๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง ๋ณ๊ฒฝ์ ๋ฒ์ ๊ด๋ฆฌํ๋ ์คํฌ์
๋๋ค.
Core Principle
"DB ์คํค๋ง๋ ์ฝ๋์ฒ๋ผ ๋ฒ์ ๊ด๋ฆฌํ๋ค."
"์๋์ผ๋ก ALTER TABLE ์น๋ ์๊ฐ, ํ์
์ด ๋ง๊ฐ์ง๋ค."
Rules
| ๊ท์น | ์ํ | ์ค๋ช
|
|---|
| ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ ์์ฑ | ๐ด ํ์ | ์๋ SQL ์คํ ๊ธ์ง |
| ๋กค๋ฐฑ ๊ฐ๋ฅ | ๐ด ํ์ | down migration ํ์ |
| ์์ฐจ ์คํ | ๐ด ํ์ | ๋ง์ด๊ทธ๋ ์ด์
์์ ๋ณด์ฅ |
| ํ๋ก๋์
๋ฐฑ์
| ๐ด ํ์ | ๋ง์ด๊ทธ๋ ์ด์
์ ๋ฐฑ์
|
Prisma (๊ถ์ฅ)
์ด๊ธฐ ์ค์
npm install prisma @prisma/client
npx prisma init
์คํค๋ง ์ ์
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
๋ง์ด๊ทธ๋ ์ด์
์ํฌํ๋ก์ฐ
npx prisma migrate dev --name add_user_table
ls prisma/migrations/
npx prisma migrate deploy
npx prisma generate
๋ง์ด๊ทธ๋ ์ด์
ํ์ผ ๊ตฌ์กฐ
prisma/
โโโ schema.prisma
โโโ migrations/
โโโ 20240101000000_init/
โ โโโ migration.sql
โโโ 20240102000000_add_user_table/
โ โโโ migration.sql
โโโ migration_lock.toml
๋ง์ด๊ทธ๋ ์ด์
๋ช
๋ น์ด
npx prisma migrate dev --name <migration_name>
npx prisma migrate deploy
npx prisma migrate status
npx prisma migrate reset
Drizzle ORM
์ด๊ธฐ ์ค์
npm install drizzle-orm postgres
npm install -D drizzle-kit
์คํค๋ง ์ ์
import { pgTable, serial, text, timestamp, boolean, integer } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
published: boolean('published').default(false),
authorId: integer('author_id').( users.),
: ().(),
: ().(),
});
drizzle.config.ts
import type { Config } from 'drizzle-kit';
export default {
schema: './src/db/schema.ts',
out: './drizzle',
driver: 'pg',
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
} satisfies Config;
๋ง์ด๊ทธ๋ ์ด์
๋ช
๋ น์ด
npx drizzle-kit generate:pg
npx drizzle-kit push:pg
npx drizzle-kit studio
๋ง์ด๊ทธ๋ ์ด์
Best Practices
1. ์์ ๋จ์๋ก ๋ง์ด๊ทธ๋ ์ด์
ALTER TABLE users ADD COLUMN age INT;
ALTER TABLE users ADD COLUMN address TEXT;
ALTER TABLE users DROP COLUMN old_field;
CREATE TABLE new_table (...);
DROP TABLE old_table;
ALTER TABLE users ADD COLUMN age INT;
ALTER TABLE users ADD COLUMN address TEXT;
2. ์์ ํ ์ปฌ๋ผ ์ถ๊ฐ
ALTER TABLE users ADD COLUMN status TEXT NOT NULL;
ALTER TABLE users ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
ALTER TABLE users ADD COLUMN status TEXT;
UPDATE users SET status = 'active' WHERE status IS NULL;
ALTER TABLE users ALTER COLUMN status SET NOT NULL;
3. ์์ ํ ์ปฌ๋ผ ์ญ์
ALTER TABLE users DROP COLUMN old_field;
4. ์ธ๋ฑ์ค ์ถ๊ฐ
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
๋กค๋ฐฑ ์ ๋ต
Prisma ๋กค๋ฐฑ
npx prisma migrate resolve --rolled-back <migration_name>
npx prisma migrate reset
์๋ ๋กค๋ฐฑ ์คํฌ๋ฆฝํธ
ALTER TABLE users DROP COLUMN status;
CI/CD ํตํฉ
GitHub Actions
name: Database Migration
on:
push:
branches: [main]
paths:
- 'prisma/**'
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
๋ง์ด๊ทธ๋ ์ด์
๊ฒ์ฆ
jobs:
validate-migration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Run migrations on test DB
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://postgres:test@localhost:5432/test
ํ๋ก๋์
์ฒดํฌ๋ฆฌ์คํธ
๋ง์ด๊ทธ๋ ์ด์
์
๋ง์ด๊ทธ๋ ์ด์
์ค
๋ง์ด๊ทธ๋ ์ด์
ํ
Workflow
๊ฐ๋ฐ ์
1. ์คํค๋ง ํ์ผ ์์ (schema.prisma)
2. npx prisma migrate dev --name <description>
3. ์์ฑ๋ SQL ํ์ธ
4. Git ์ปค๋ฐ (์คํค๋ง + ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ)
๋ฐฐํฌ ์
1. PR ๋จธ์ง
2. CI์์ npx prisma migrate deploy ์คํ
3. ํ๋ก๋์
ํ์ธ
4. (๋ฌธ์ ์) ๋กค๋ฐฑ ์คํ
Checklist
References