2026년 Drizzle ORM vs Prisma: 아무도 안 하는 솔직한 비교
2026년에 TypeScript 백엔드를 짜고 있다면, 결국 이 질문에 도달하게 돼요. Drizzle이냐 Prisma냐?
"Prisma는 너무 무겁다." "Drizzle은 raw SQL에 껍데기 씌운 거다." "Prisma 엔진은 오버스펙이다." "Drizzle은 마이그레이션이 별로다." — 이런 주장, 인터넷에 정말 많죠. 근데 대부분 오래됐거나, 일부만 맞거나, 아예 틀려요. 특히 Prisma 7이 엔진을 통째로 TypeScript로 갈아엎은 지금은요. 비판 근거였던 Rust 바이너리가 아예 없어졌거든요.
이 글에서는 진짜 중요한 것들만 비교할 거예요. 쿼리 성능, 콜드 스타트, 번들 사이즈, 타입 안전성, 마이그레이션, 엣지 호환, 개발 경험. 팬보이 없고 스폰서 결론도 없어요. 데이터랑 솔직한 분석만 있습니다.
끝까지 읽으면 내 프로젝트에 뭐가 맞는지, 그리고 왜 그런지 확실히 감이 올 거예요.
근본적인 철학 차이
벤치마크를 보기 전에, Drizzle과 Prisma의 설계 방향이 어떻게 다른지부터 짚고 가야 해요. 이건 그냥 구현 방식 차이가 아니라, 모든 걸 결정짓는 출발점이에요.
Prisma는 추상화 우선이에요. .prisma 파일에 Prisma 전용 문법으로 스키마를 쓰면, 타입 안전한 클라이언트가 자동으로 생겨요. 의도적으로 SQL을 감춰요. "SQL은 몰라도 돼. 데이터 모델만 기술하면 나머지는 우리가 알아서 할게."
Drizzle은 SQL 우선이에요. TypeScript로 스키마를 작성하는데, SQL 구조를 그대로 반영하는 함수들을 써요. "SQL 할 줄 알면 Drizzle도 이미 할 줄 아는 거야. 데이터베이스를 숨기지 않고, 타입만 붙여줄게."
정리하면:
- Prisma 쓰는 사람은 모델과 관계 중심으로 생각하고
- Drizzle 쓰는 사람은 테이블과 조인 중심으로 생각해요
어느 쪽이 객관적으로 낫다는 건 없어요. 근데 이 철학 차이가 아래에서 다룰 모든 부분에 영향을 미쳐요.
스키마 정의: 두 세계
Prisma 스키마
Prisma는 자체 .prisma DSL을 써요:
model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? 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 tags Tag[] createdAt DateTime @default(now()) } model Tag { id Int @id @default(autoincrement()) name String @unique posts Post[] } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique }
깔끔하고 읽기 좋고 선언적이에요. 관계를 모델 레벨에서 정의하니까 한눈에 들어오고, 문법도 간결해서 별도 문서 없이도 이해가 돼요.
다만 이건 TypeScript가 아니에요. 스키마가 별도 파일에 자체 문법, 자체 확장자, 자체 툴링으로 존재해요. VS Code 확장으로 .prisma 파일을 지원하긴 하지만, 네이티브 TypeScript IntelliSense에 비하면 한계가 있어요.
Drizzle 스키마
Drizzle은 순수 TypeScript로 스키마를 정의해요:
import { pgTable, serial, text, boolean, integer, timestamp } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; export const users = pgTable('users', { id: serial('id').primaryKey(), email: text('email').notNull().unique(), name: text('name'), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), }); export const posts = pgTable('posts', { id: serial('id').primaryKey(), title: text('title').notNull(), content: text('content'), published: boolean('published').default(false).notNull(), authorId: integer('author_id').references(() => users.id).notNull(), createdAt: timestamp('created_at').defaultNow().notNull(), }); export const tags = pgTable('tags', { id: serial('id').primaryKey(), name: text('name').notNull().unique(), }); export const profiles = pgTable('profiles', { id: serial('id').primaryKey(), bio: text('bio'), userId: integer('user_id').references(() => users.id).notNull().unique(), }); // 관계 정의 (쿼리 API에서 사용) export const usersRelations = relations(users, ({ many, one }) => ({ posts: many(posts), profile: one(profiles), })); export const postsRelations = relations(posts, ({ one, many }) => ({ author: one(users, { fields: [posts.authorId], references: [users.id] }), tags: many(tags), }));
좀 더 길죠? 네, 맞아요. 대신 이건 순수 TypeScript예요. IntelliSense 다 되고, 아무 데서든 import 가능하고, 별도 확장 없이 lint/format/refactor 전부 그냥 돌아요.
트레이드오프가 명확해요: Prisma 스키마가 간결하고 읽기 좋은 대신, Drizzle 스키마가 이식성과 조합성에서 이겨요.
쿼리 API: 진짜 차이가 드러나는 곳
두 ORM이 가장 크게 갈리는 부분이에요.
간단한 쿼리
Prisma:
const user = await prisma.user.findUnique({ where: { email: '[email protected]' }, include: { posts: true, profile: true }, });
Drizzle (Query API):
const user = await db.query.users.findFirst({ where: eq(users.email, '[email protected]'), with: { posts: true, profile: true }, });
Drizzle (SQL-like API):
const user = await db .select() .from(users) .where(eq(users.email, '[email protected]')) .leftJoin(posts, eq(posts.authorId, users.id)) .leftJoin(profiles, eq(profiles.userId, users.id));
간단한 쿼리에서는 체감 차이가 거의 없어요. Drizzle은 관계형 쿼리 API(Prisma 스타일)와 SQL-like API(타입 안전 쿼리 빌더 스타일) 둘 다 제공하고요.
복잡한 쿼리: 여기서 진짜 갈려요
진짜 재밌어지는 건 복잡한 쿼리예요. "최근 30일 이내 가입한 유저 중에서 published 포스트가 있는 유저를 포스트 수 순으로 페이지네이션해라." 이런 거요.
Prisma:
const results = await prisma.user.findMany({ where: { createdAt: { gte: thirtyDaysAgo }, posts: { some: { published: true } }, }, include: { posts: { where: { published: true }, orderBy: { createdAt: 'desc' }, }, _count: { select: { posts: true } }, }, orderBy: { posts: { _count: 'desc' } }, skip: page * pageSize, take: pageSize, });
Drizzle:
const results = await db .select({ user: users, postCount: sql<number>`count(${posts.id})`.as('post_count'), }) .from(users) .leftJoin(posts, and( eq(posts.authorId, users.id), eq(posts.published, true), )) .where(gte(users.createdAt, thirtyDaysAgo)) .groupBy(users.id) .orderBy(desc(sql`post_count`)) .limit(pageSize) .offset(page * pageSize);
여기서 철학 차이가 확 체감돼요:
-
Prisma는 추상적으로 접근해요. "published된 포스트가 있는 유저를 찾아줘" 식으로 고수준 개념으로 생각하죠. 다만
_count나 중첩include같은 Prisma만의 패턴을 따로 익혀야 해요. -
Drizzle은 내가 직접 쓸 SQL과 거의 1:1로 대응돼요. SQL 아는 사람이면 바로 읽혀요. 대신
GROUP BY나LEFT JOIN같은 SQL 개념은 알고 있어야 하고요.
Raw SQL 탈출구
둘 다 raw SQL을 쓸 수 있는데, 사용감이 달라요:
Prisma:
const result = await prisma.$queryRaw` SELECT u.*, COUNT(p.id) as post_count FROM "User" u LEFT JOIN "Post" p ON p."authorId" = u.id WHERE p.published = true GROUP BY u.id ORDER BY post_count DESC `; // ⚠️ 반환 타입이 `unknown`
Drizzle:
const result = await db.execute(sql` SELECT ${users.id}, ${users.email}, COUNT(${posts.id}) as post_count FROM ${users} LEFT JOIN ${posts} ON ${posts.authorId} = ${users.id} WHERE ${posts.published} = true GROUP BY ${users.id} ORDER BY post_count DESC `); // ✅ 테이블/컬럼 참조가 여전히 타입 체크됨
Drizzle의 sql 템플릿 태그는 raw SQL 안에서도 스키마 객체를 참조할 수 있어서, 부분적으로 타입 안전성이 유지돼요. Prisma의 $queryRaw는 그런 거 없이 통째로 무타입이에요.
성능: 숫자로 보자
다들 진짜 궁금한 부분이죠. 그리고 2026년에 판이 완전히 바뀌었어요.
Prisma 7 혁명
2026년 이전 벤치마크로 판단하고 있었다면, 이제 버리세요. Prisma 7이 쿼리 엔진을 완전히 새로 썼어요. Rust 기반 엔진을 걷어내고 TypeScript/WebAssembly 기반 Query Compiler로 교체했거든요. 이 한 가지 변화가 성능 논쟁 자체를 뒤집어놨어요:
- Rust 엔진 바이너리가 ~14MB였는데, 새 TS/WASM 엔진은 ~1.6MB (gzip 600KB). 85-90% 줄었어요.
- JS ↔ Rust 간 직렬화 오버헤드가 사라져서, 대량 결과셋에서 최대 3.4배 빨라졌어요.
- 서버리스 콜드 스타트가 최대 9배 개선.
Prisma 성능을 까던 논거 상당수가 이제 유효하지 않아요.
쿼리 실행 성능
벤치마크들이 놓치는 포인트가 하나 있어요. 대부분의 경우 ORM 자체가 병목이 아니에요. 진짜 쿼리에서는 DB 실행 시간이 ORM 오버헤드를 압도하거든요.
그래도 2026년 기준 측정 가능한 차이는 있어요:
| 지표 | Prisma 7.x | Drizzle 0.45.x |
|---|---|---|
단순 findOne 오버헤드 | ~1-2ms | ~0.5-1ms |
| 복잡 조인 쿼리 오버헤드 | ~2-5ms | ~1-3ms |
| 대량 결과셋 (1000+행) | 크게 개선 (Prisma 6 대비 3.4배) | 원래부터 빠름 |
| Raw SQL 패스스루 | ~0.5ms | ~0.3ms |
Drizzle이 순수 ORM 오버헤드에서는 여전히 빨라요. 엔진 레이어 없이 SQL 문자열을 바로 만드니까요. 근데 Prisma 7 이후로 격차가 많이 좁아졌고, 어차피 대부분 앱에서는 DB 왕복 시간(5-50ms)이 전체 쿼리 시간의 대부분이에요.
성능 차이가 진짜로 체감되는 상황이 두 가지 있어요:
1. 콜드 스타트 (서버리스)
Prisma가 역대 가장 까인 부분인데, Prisma 7이 정면돌파했어요.
콜드 스타트 비교 (AWS Lambda, Node.js 22):
Prisma 7.x (TypeScript 엔진):
- Rust 바이너리 없음
- TS/WASM 엔진 로드: ~40-80ms
- 첫 쿼리: 총 ~80-150ms
Drizzle 0.45.x:
- 엔진 자체가 없음
- 커넥션 설정: ~20-50ms
- 첫 쿼리: 총 ~50-100ms
참고 — Prisma 5.x (구 Rust 엔진):
- 엔진 초기화: ~500-1500ms
- 첫 쿼리: 총 ~600-1800ms
개선 폭이 엄청나요. Prisma 7 콜드 스타트는 이제 Drizzle과 비슷한 레벨이지, 차원이 다른 게 아니에요. Drizzle이 여전히 빠르긴 한데, 1초 차이가 아니라 ~50-80ms 차이예요.
2. 번들 사이즈
여기서 Drizzle이 가장 확실하게 앞서요:
번들 사이즈 (런타임):
Prisma 7.x:
@prisma/client + TS 엔진: ~1.6MB (gzip 600KB)
prisma (CLI): ~15MB (개발용)
런타임 총계: ~1.6MB
Drizzle 0.45.x:
drizzle-orm: ~12KB
drizzle-kit: ~8MB (CLI, 개발용)
런타임 총계: ~12KB
Prisma 7이 엄청 줄이긴 했지만, Drizzle 런타임은 여전히 ~130배 작아요. 이게 중요한 상황:
- Docker 이미지 크기 관리
- 서버리스 함수 패키징 (AWS Lambda 250MB 제한)
- 엣지 런타임 배포 (Cloudflare Workers의 빡빡한 사이즈 제한)
- CI/CD 파이프라인 속도
엣지 런타임 호환성
여기도 Prisma 7의 변화가 큰 부분이에요.
Drizzle: Cloudflare Workers, Vercel Edge Functions, Deno Deploy 등 모든 엣지 런타임에서 네이티브 동작. 바이너리 의존성 없음. 원래부터 그랬어요.
Prisma 7: Rust 엔진이 사라지면서, Driver Adapter가 더 이상 실험적 기능이 아니라 코어 아키텍처의 필수 요소가 됐어요. TypeScript 엔진 덕분에 엣지에서 네이티브 동작하고, 기본 엣지 지원에 Prisma Accelerate가 필요 없어졌어요.
경쟁이 훨씬 팽팽해졌어요. 극단적으로 사이즈 제한이 타이트한 환경(Cloudflare Workers 같은 데선 1.6MB보다 12KB가 확실히 유리)에서는 Drizzle이 이기지만, Prisma가 아키텍처적으로 엣지에서 배제되던 시대는 끝났어요.
마이그레이션 워크플로우
Prisma Migrate
Prisma 마이그레이션은 성숙하고 확실한 방향성을 갖고 있어요:
# schema.prisma 수정 후: npx prisma migrate dev --name add_user_avatar # 이게 자동으로: # 1. 스키마와 DB 차이를 비교 # 2. SQL 마이그레이션 파일 생성 # 3. 개발 DB에 적용 # 4. Prisma Client 재생성
개발 경험이 매끈해요. 스키마 수정하고 명령어 하나 치면 끝이에요.
Drizzle Kit
Drizzle Kit은 다른 흐름을 제공해요:
# TypeScript 스키마 수정 후: npx drizzle-kit generate --name add_user_avatar # 그리고 적용: npx drizzle-kit migrate
빠른 프로토타이핑을 위한 push 모드도 있고요:
npx drizzle-kit push
실전에서는 둘 다 잘 돌아가요. Prisma가 데이터 손실 감지나 인터랙티브 프롬프트 쪽에서 더 성숙하고, Drizzle Kit도 1.0을 향해 가면서 많이 좋아졌지만 가끔 생성된 SQL이 좀 아쉬운 엣지 케이스가 있을 수 있어요.
타입 안전성: 좀 더 깊이 보기
두 ORM 다 TypeScript 통합이 훌륭한데, 접근 방식이 달라요.
Prisma의 타입 생성
// Prisma가 자동 생성 type User = { id: number; email: string; name: string | null; createdAt: Date; updatedAt: Date; };
타입이 항상 스키마와 동기화되긴 하는데, prisma generate를 실행한 다음에만 그래요. Prisma 7은 타입 체크 속도도 70% 정도 개선해서 생성이 더 빨라지긴 했어요.
Drizzle의 타입 추론
type User = typeof users.$inferSelect; // Select 타입 type NewUser = typeof users.$inferInsert; // Insert 타입 // 스키마 수정하면 바로 타입 업데이트
Drizzle 스키마가 TypeScript니까, 파일 저장하는 순간 타입이 바뀌어요. 생성 단계 없고, 구버전 타입 걱정 없고, postinstall 훅도 안 넣어도 돼요.
타입 즉시성에서는 Drizzle 승리. 외부 스키마에서 생성하는 게 아니라 소스 코드에서 직접 추론하니까 항상 최신이에요.
반면 생성된 헬퍼 타입에서는 Prisma가 이겨요. UserCreateNestedManyWithoutAuthorInput 같은 복잡한 인풋 타입을 자동으로 만들어줘서 중첩 관계 뮤테이션을 편하게 처리할 수 있거든요. Drizzle에서는 이런 걸 직접 조립해야 해요.
실전 의사결정 가이드
"어느 ORM이 더 좋아?"보다 **"내 상황에 뭐가 맞아?"**를 물어야 해요.
Prisma가 맞는 경우:
-
팀원들의 SQL 실력이 들쑥날쑥할 때. Prisma의 추상화가 SQL에 덜 익숙한 개발자를 보호해줘요.
-
검증된 생태계가 필요할 때. 수천 개 회사에서 수년간 프로덕션으로 쓰고 있고, 생태계도 방대해요.
-
기존 서버든 서버리스든 상관없을 때. Prisma 7의 콜드 스타트 대폭 개선 덕에, 서버리스 페널티가 더 이상 치명적이지 않아요. Express, Fastify, NestJS, Lambda 뭐든 무리 없이 돌아요.
-
컨벤션 기반 개발을 좋아할 때. Prisma가 많은 결정을 대신해줘서 고민이 줄어들어요.
Drizzle이 맞는 경우:
-
엣지 환경에 배포하는데 사이즈가 빡빡할 때. 12KB 런타임은 Cloudflare Workers 같은 데서 진짜 무적이에요. Prisma 7의 1.6MB도 대부분의 엣지 플랫폼에서 돌아가긴 하지만, Drizzle 쪽이 여유가 훨씬 커요.
-
팀이 SQL에 익숙할 때. SQL 잘 쓰는 팀이라면 Drizzle의 SQL-first API가 딱 맞을 거예요. 새로운 추상화를 배우는 게 아니라 타입 붙은 SQL을 쓰는 거니까요.
-
코드 생성이 싫을 때. 빌드 단계,
postinstall훅, 생성 파일 같은 게 번거롭다면 Drizzle의 추론 방식이 깔끔해요. -
극한의 경량화가 필요할 때. 격차가 많이 좁아지긴 했지만, Drizzle이 여전히 런타임 오버헤드가 적어요. 초고성능 시나리오에서는 밀리초 하나하나가 중요하니까요.
-
여러 DB를 지원해야 할 때. Drizzle은 PostgreSQL, MySQL, SQLite, Turso(LibSQL) 등 여러 DB를 깔끔하게 지원해요.
하이브리드 접근법
사실 아무도 잘 안 말하는 건데, 둘 다 쓸 수 있어요. 같은 프로젝트에서 동시에 쓰라는 건 아니고(그건 미친 짓), 아키텍처적으로 나눠 쓰는 거예요:
- 메인 앱 서버에서는 풍부한 생태계와 생산성이 중요하니까 Prisma
- 사이즈 제한이 빡빡한 엣지 함수나 마이크로서비스에서는 12KB가 빛나는 Drizzle
2026년 많은 프로덕션 아키텍처가 이런 식으로 잘 운영하고 있어요.
비교 글이 안 다루는 것: Prisma의 비즈니스 모델
비교 글들이 보통 슬쩍 넘어가는 얘기를 좀 해볼게요. 지속 가능성과 비즈니스 모델이에요.
Prisma는 VC 투자를 받은 회사예요. 무료 ORM으로 유저를 모은 다음, 유료 서비스(Prisma Accelerate, Prisma Optimize, Prisma Postgres)로 수익을 내죠. 이게 나쁘다는 건 아니에요. 다만 Prisma의 로드맵이 상업적 우선순위의 영향을 받는다는 건 알고 있어야 해요.
Drizzle ORM은 오픈소스로, Drizzle Team이 유지보수하고 있어요. Drizzle Studio도 나왔고 상업적 계획도 있지만, ORM 코어는 기능 제한 없이 완전 오픈소스에요. 1.0을 향해 가고 있고(현재 v1.0.0-beta.15), 프로젝트가 빠른 속도로 성숙 중이에요.
어느 모델이 더 "믿을 만하다"고 단정할 순 없어요. 다만 내가 쓰는 도구의 인센티브 구조가 뭔지는 알고 선택하는 게 좋겠죠.
전환 가이드: 갈아타기
Prisma → Drizzle
비교적 단계가 명확해요:
drizzle-kit introspect로 기존 DB에서 Drizzle 스키마를 뽑아내고- Prisma 쿼리를 파일 단위로 교체하고
- 전환 기간 동안 두 ORM을 병렬 운영하고
- 다 옮기면 Prisma를 제거
가장 까다로운 건 Prisma의 중첩 include나 관계 뮤테이션을 쓰는 복잡한 쿼리의 재작성이에요.
Drizzle → Prisma
prisma db pull로 DB를 들여다보고.prisma스키마 생성prisma generate로 클라이언트 생성- Drizzle 쿼리를 Prisma 스타일로 교체
- Prisma의 고수준 API가 대부분의 쿼리를 더 짧게 표현할 수 있어서, 전환이 좀 더 부드러운 편이에요
앞으로의 전망: 2026년 이후
두 ORM 다 빠르게 진화하고 있고, 가장 재밌는 트렌드는 수렴이에요.
Prisma 7은 전환점이었어요. Rust 엔진을 버리고 TypeScript/WASM으로 갈아타면서, 가장 큰 아키텍처적 약점을 없앴어요. Driver Adapter가 이제 코어 필수 요소고, 결과적으로 더 가볍고, 더 빠르고, 이식성이 훨씬 좋은 ORM이 됐죠. Prisma Postgres(관리형 DB)가 ORM과 밀접하게 통합돼 있고, 플랫폼 전략은 계속 확장 중이에요.
Drizzle은 1.0을 향해 달리고 있어요. 베타 단계에서 이미 validator 패키지(drizzle-zod, drizzle-valibot)를 코어 저장소에 통합 중이고, 에러 메시지 개선, 마이그레이션 생성 개선, Drizzle Studio와 인증 연동으로 생태계를 넓혀가고 있어요.
큰 흐름을 보면: Prisma는 더 가볍고 SQL-aware해지고, Drizzle은 기능이 더 풍부해지고 추상화가 개선되고 있어요. 둘 사이의 격차는 대부분이 생각하는 것보다 빠르게 좁아지고 있어요.
결론
불편한 진실 하나 말할게요. 둘 다 좋은 선택이에요. 2026년 TypeScript ORM 생태계는 진짜 괜찮은 수준이고, 뭘 골라도 치명적인 실수는 아니에요.
근데 한 문장으로 정리해야 한다면:
ORM이 대신 생각해주길 원하면 Prisma. ORM이 같이 생각해주길 원하면 Drizzle.
Prisma는 복잡성을 대신 처리해주는 데 강하고, Drizzle은 복잡성을 타입 안전하게 다루는 데 강해요.
한 가지 확실히 달라진 건: 성능 논쟁이 어느 한쪽의 압승이 아니게 됐다는 거예요. Prisma 7이 이전 세대를 정의하던 콜드 스타트 페널티를 해소했거든요. Drizzle이 순수 효율에서는 여전히 앞서지만, 그 차이가 초와 메가바이트가 아니라 밀리초와 킬로바이트 단위예요.
트위터 핫테이크에 이 결정을 맡기지 마세요. 내 프로젝트에 맞는 걸 골라서, 좋은 거 만들고, 진짜 중요한 문제로 넘어가세요.
관련 도구 둘러보기
Pockit의 무료 개발자 도구를 사용해 보세요