OPEN HYPER STEP
← 목록으로 (stack-analysis)
STACK-ANALYSIS · 41 / 90
stack-analysis
CHAPTER 41 / 90
읽기 약 2
FUNCTION

마이그레이션: Prisma Migrate 실전


핵심 개념

schema.prisma·migrate dev/deploy·zero-downtime·롤백 — 안전한 DB 변경.

본문

Prisma 셋업

BASH📋 코드 (2줄)
pnpm add prisma @prisma/client
pnpm dlx prisma init
PRISMA📋 코드 (32줄)
// schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String
  posts     Post[]
  createdAt DateTime @default(now())

  @@index([createdAt])
}

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String   @db.Text
  authorId  String
  author    User     @relation(fields: [authorId], references: [id])
  published Boolean  @default(false)
  createdAt DateTime @default(now())

  @@index([authorId, createdAt(sort: Desc)])
  @@index([published])
}

마이그레이션 명령

BASH📋 코드 (15줄)
# 개발 — 스키마 변경 후
pnpm dlx prisma migrate dev --name add_user_email_unique

# → migrations/20260429_add_user_email_unique/migration.sql 생성
# → DB 적용 + Prisma Client 재생성


# 프로덕션
pnpm dlx prisma migrate deploy

# → 미적용 마이그레이션 실행 (생성 X)


# DB 재설정 (개발용)
pnpm dlx prisma migrate reset

Zero-Downtime 마이그레이션

📋 코드 (21줄)
❌ 위험한 변경:
1. 컬럼 이름 변경 (rename)
2. 컬럼 타입 변경 (string → number)
3. NOT NULL 추가 (기존 데이터에)
4. 큰 테이블에 인덱스 추가 (블로킹)


✅ 안전한 패턴 — Expand & Contract:

[Phase 1: Expand]
- 새 컬럼 추가 (nullable)
- 새 코드는 양쪽 쓰기 (dual-write)
- 백필 (background)

[Phase 2: Migrate]
- 새 컬럼이 채워질 때까지 대기
- 새 코드는 새 컬럼만 읽기

[Phase 3: Contract]
- 옛 컬럼 제거
- 코드 정리

예시 — 컬럼 rename

TYPESCRIPT📋 코드 (24줄)
// ❌ 한 번에
model User {
  username String  // name → username으로 변경
}


// ✅ 단계별
// Phase 1
model User {
  name      String
  username  String?  // 추가
}
// 코드: 양쪽 쓰기
await prisma.user.update({ where, data: { name: x, username: x } });


// Phase 2 — 백필
await prisma.$executeRaw`UPDATE "User" SET username = name WHERE username IS NULL`;


// Phase 3
model User {
  username String  // name 제거 + NOT NULL
}

큰 테이블 인덱스 — CONCURRENTLY

SQL📋 코드 (13줄)
-- ❌ 블로킹
CREATE INDEX idx_posts_created ON posts(created_at);


-- ✅ 비차단 (PostgreSQL)
CREATE INDEX CONCURRENTLY idx_posts_created ON posts(created_at);


-- Prisma는 자동으로 CONCURRENTLY 안 함
-- → 수동 마이그레이션 SQL 작성

-- migration.sql
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_posts_created ON "Post"("createdAt");

시드 데이터

TYPESCRIPT📋 코드 (23줄)
// prisma/seed.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

async function main() {
  await prisma.user.upsert({
    where: { email: 'admin@example.com' },
    create: { email: 'admin@example.com', name: 'Admin', role: 'ADMIN' },
    update: {},
  });
}

main().finally(() => prisma.$disconnect());


// package.json
{
  "prisma": { "seed": "tsx prisma/seed.ts" }
}


// 실행
pnpm dlx prisma db seed

마이그레이션 롤백

BASH📋 코드 (13줄)
# Prisma는 자동 롤백 없음 → 수동 작성

# migrations/20260429_xxx/migration.sql
ALTER TABLE "Post" ADD COLUMN "summary" TEXT;

# rollback.sql (수동 작성·관리)
ALTER TABLE "Post" DROP COLUMN "summary";


# 프로덕션 롤백 절차:
1. 백업 확인 (RDS 자동 스냅샷)
2. 새 마이그레이션으로 역방향 변경
3. 또는 백업에서 PITR (Point-In-Time Recovery)

환경 분리

BASH📋 코드 (14줄)
# .env.development
DATABASE_URL="postgresql://localhost/myapp_dev"

# .env.staging
DATABASE_URL="postgresql://stage-db.../myapp_stage"

# .env.production (Vercel/Railway 환경변수)
DATABASE_URL="postgresql://prod-db.../myapp_prod"


# CI/CD 흐름:
1. PR 머지 → staging migrate deploy
2. 검증 통과 → production migrate deploy
3. 실패 시 alert + 롤백 절차

다음 챕터

CH.42 "Redis 패턴: 캐시/세션/큐/Pub-Sub".


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 코드의 DB 마이그레이션 부분을 분석해서
실전 분석 + 개선 우선순위를 알려줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

DB 마이그레이션 관련 인기 라이브러리/패턴 5개를
비교 분석해서 패턴 추출를 알려줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 프로젝트 전체에서 DB 마이그레이션
최적화 가능 위치를 보고해줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 한국 백엔드 시장의
DB 마이그레이션 트렌드를 솔직히 알려줘.

⭐ 이것만 기억하세요
마이그레이션: Prisma Migrate 실전 이 3가지만 확실히 잡으세요
1.migrate dev = 개발(생성+적용), migrate deploy = 프로덕션(적용만)
2.Zero-downtime은 Expand & Contract 패턴 — 점진적 전환
3.큰 테이블 인덱스는 CONCURRENTLY — 수동 SQL 필요


공유하기
진행도 41 / 90