핵심 요약
2025년 11월 회사 메인 서비스(API 300개·테이블 120개)의 ORM을 Prisma 6에서 Drizzle 2.0으로 옮겼다. 6개월 운영 결과: 빌드 -38%, 콜드 스타트 -52%, 메모리 -33%. 하지만 "관계 로딩"에서 Prisma가 그리워지는 순간이 있다.
1. 옮긴 동기 — 무엇이 문제였나
- Prisma Client 번들 크기: 8.7MB (engine 포함). Vercel/Cloudflare edge에서 문제.
- 쿼리 엔진 콜드 스타트: Lambda 환경에서 평균 320ms 추가
- raw SQL이 답답함: 복잡한 윈도우 함수·CTE를 Prisma 추상화로 표현 불가
- 마이그레이션 충돌: 팀원 6명, 매주 conflict 한 번씩
2. 스키마 비교
Prisma는 자체 DSL, Drizzle은 TypeScript 코드.
// Prisma
model User {
id Int @id @default(autoincrement())
email String @unique
posts Post[]
}
// Drizzle
import { pgTable, serial, text } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').notNull().unique(),
})
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}))
Drizzle은 코드라서 조건부 컬럼·동적 테이블·고급 타입 합성이 자유롭다. 대신 처음엔 번잡하게 느껴진다.
2. 쿼리 — SQL에 가까움
// Prisma — 추상적
const posts = await prisma.post.findMany({
where: { author: { email: 'kim@x.com' } },
include: { tags: true },
orderBy: { createdAt: 'desc' },
})
// Drizzle — SQL스러움
const posts = await db
.select()
.from(postsTable)
.innerJoin(users, eq(postsTable.authorId, users.id))
.where(eq(users.email, 'kim@x.com'))
.orderBy(desc(postsTable.createdAt))
장점: SQL 그대로라 EXPLAIN ANALYZE 결과 예측 가능. 단점: 관계 로딩이 한 줄로 끝나지 않는다.
3. 실측 — 6개월 평균
| 지표 | Prisma 6 | Drizzle 2.0 | 변화 |
|---|---|---|---|
| node_modules 크기 | 286MB | 62MB | -78% |
| tsc 빌드 시간 | 48s | 30s | -38% |
| Lambda 콜드 스타트 | 1,180ms | 560ms | -52% |
| RAM (idle) | 168MB | 112MB | -33% |
| 단순 select P50 | 4.2ms | 3.9ms | -7% |
| 5개 join P50 | 14ms | 11ms | -21% |
| insert + return P50 | 6.1ms | 5.8ms | -5% |
가장 큰 이득은 콜드 스타트. Edge·FaaS에서 큰 차이.
4. 마이그레이션 함정 7가지
① N+1 문제 표면화
Prisma의 include는 N+1을 자동으로 한 쿼리로 묶지 않고 IN 절로 처리. Drizzle은 그냥 N+1이 나옴. with + relations로 명시.
const result = await db.query.posts.findMany({
with: { author: true, tags: true },
}) // Drizzle도 한 번에 처리 가능
② JSON 컬럼 타입
Prisma는 Json = any, Drizzle은 제네릭으로 강타입.
metadata: jsonb('metadata').$type<{ tags: string[]; views: number }>()
③ 트랜잭션 격리수준
Prisma는 옵션 명시. Drizzle은 db.transaction(async tx => { ... }, { isolationLevel: 'serializable' }).
④ 마이그레이션 도구
drizzle-kit이 Prisma migrate보다 가벼움. 다만 충돌 해결은 수동. 팀 규약 필수.
⑤ 시드 데이터
Prisma의 prisma db seed 같은 표준이 없다. 자체 스크립트 작성.
⑥ Studio
Drizzle Studio가 Prisma Studio보다 가볍지만 기능은 80%. 데이터 편집 UX는 Prisma가 우위.
⑦ 에코시스템
NestJS·tRPC·Auth.js 통합 예시는 Prisma가 압도적으로 많음. Drizzle은 직접 wire-up.
5. 언제 Prisma를 그대로 두는 게 낫나
- 팀이 SQL을 별로 안 쓰는 풀스택 신입 위주
- Schema-driven 워크플로(스키마 → 마이그레이션 → 타입)에 만족
- Edge/FaaS 비중이 낮음
- Prisma Pulse·Accelerate 같은 부가 기능 이미 활용
6. 도입 순서 권장
- 새 마이크로서비스 1개를 Drizzle로 시작 (학습)
- 관계 모델 패턴이 잡힌 뒤 기존 서비스 1개 변환
- 드릴 다운: 가장 트래픽 큰 엔드포인트 10개 EXPLAIN으로 회귀 검증
- 전체 마이그레이션은 2~3개월 잡고, 신·구 ORM 공존 기간 둠
안티패턴
- "Drizzle이 빠르다고 들어서" — 콜드 스타트가 문제 아닌 환경에선 차이 미미
- "한 번에 다 옮긴다" — 6개월 잡고 점진 권장
- "raw SQL만 쓰자" — Drizzle 추상화의 타입 안전성을 다 버림
참고
- orm.drizzle.team — relational queries
- github.com/drizzle-team/drizzle-orm/releases — 2.0 변경점

댓글 0