Dev Tools11 min

Drizzle ORM × Next.js 서버리스 가이드 — Prisma 대체 실전 정리

Drizzle ORM 번들 50KB, Edge 런타임 기본 지원, Neon·Supabase·Turso 연동까지. Next.js App Router + 서버리스 환경에서 Prisma를 대체하는 실전 가이드를 2026년 4월 기준으로 정리했다.

On this page (12)

2026년 4월 · 개발 도구

Next.js App Router와 Vercel 서버리스 조합에서 ORM 선택지가 Drizzle로 빠르게 기울고 있다. 번들 크기 ~50KB(gzip ~7KB), Edge 런타임 기본 지원, Neon·Supabase·Turso 공식 연동까지 서버리스 환경에 최적화된 설계 때문이다. Prisma가 7 버전에서 Rust 엔진을 걷어내며 번들을 90% 줄였지만, 기본값은 여전히 Drizzle이 가볍다.

이 글은 Next.js 프로젝트에서 Drizzle을 실전 투입할 때 필요한 것만 모은 가이드다. 설치, 스키마 정의, 타입 세이프 쿼리, 마이그레이션 워크플로우, Server Component에서 사용하는 패턴까지 코드 단위로 정리했다. Neon을 기본 DB로 두고, Supabase·Turso 연동 차이도 같이 짚는다.

결론부터 쓰면, 1인·소규모 서버리스 프로젝트라면 Drizzle + Neon이 최선에 가깝다. 팀 규모가 크고 Prisma Studio 같은 GUI가 중요하면 Prisma가 여전히 나쁘지 않다. 어느 쪽이 절대적으로 낫다는 게 아니라 스택과 팀 규모에 따라 답이 다르다.

빠르게 보기
  • Drizzle ORM 번들 ~50KB (gzip ~7KB), Prisma 7 ~1.6MB — 서버리스 콜드스타트 체감 차이
  • Edge 런타임 기본 동작 — Vercel Edge Functions, Cloudflare Workers 추가 설정 없이 지원
  • 스키마는 TypeScript 파일 하나 — drizzle-kit이 SQL diff 자동 생성
  • 타입 자동 추론 — $inferSelect, $inferInsert로 API 타입까지 재사용
  • 지원 DB — PostgreSQL(Neon, Supabase), SQLite(Turso, libSQL), MySQL(PlanetScale)
  • drizzle-kit push는 로컬 테스트용, migrate는 프로덕션용 — 섞지 않는다
  • Next.js Server Component에서 db를 바로 import해서 쓴다 — 상태 관리 불필요

왜 Drizzle인가 — 서버리스에서 Prisma가 느린 이유

Prisma 번들 사이즈는 7 버전 기준 약 1.6MB다. 서버리스 콜드 스타트에서 이게 직접 영향을 준다. Drizzle은 ~50KB(gzip ~7KB)라 차이가 체감된다. Prisma 7이 Rust 엔진을 걷어내며 90% 감축했지만 여전히 Drizzle 쪽이 한 자릿수 배수 차이로 가볍다.

콜드 스타트는 서버리스 함수가 처음 실행될 때 코드를 로딩하는 시간이다. 마치 컴퓨터를 켤 때 운영체제가 올라오는 것과 같다. 번들이 클수록 이 시간이 길어진다. 트래픽이 없다가 갑자기 요청이 오는 서비스에서는 UX에 직결된다.

Edge 런타임에서 Prisma는 별도 어댑터가 필요하다. Drizzle은 기본으로 동작한다. Vercel Edge Functions와 Cloudflare Workers 모두 추가 설정 없이 쓸 수 있다. 추가 설정이 없다는 건 버그 포인트가 없다는 뜻이다.

Next.js + Neon 기본 설정

Neon은 서버리스 PostgreSQL 서비스다. HTTP 기반 커넥션을 제공해서 서버리스 함수와 궁합이 좋다. 무료 티어에서 0.5GB 스토리지를 제공한다. 패키지 두 개로 연동이 끝난다.

# 설치
npm install drizzle-orm @neondatabase/serverless
npm install -D drizzle-kit

// lib/db.ts
import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';

const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql);

.env.local에 DATABASE_URL만 추가하면 된다. Neon 대시보드에서 connection string을 복사한다. neon()에 URL을 넘기는 것만으로 HTTP 커넥션이 완성된다.

서버리스 커넥션 풀 주의사항

전통적인 PostgreSQL 커넥션은 서버리스에서 커넥션 수 초과 문제가 생긴다. Neon HTTP 드라이버는 각 요청을 HTTP로 처리해서 이 문제를 피한다. Supabase를 쓴다면 Direct Connection이 아닌 Transaction Pooler URL을 써야 한다.

스키마 정의 — TypeScript로 테이블을 선언한다

Drizzle 스키마는 TypeScript 파일이다. pgTable()로 테이블을 선언하고 컬럼 타입을 지정한다. 이 파일 하나가 DB 테이블 정의이자 TypeScript 타입의 원본이다.

// lib/schema.ts
import { pgTable, serial, text, timestamp, boolean } from 'drizzle-orm/pg-core';

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  published: boolean('published').default(false),
  createdAt: timestamp('created_at').defaultNow(),
});

// 타입 자동 추출
export type Post = typeof posts.$inferSelect;
export type NewPost = typeof posts.$inferInsert;

$inferSelect로 SELECT 결과 타입을, $inferInsert로 INSERT 입력 타입을 뽑는다. 이 타입을 API 응답 타입이나 컴포넌트 props에 재사용하면 된다. 스키마가 바뀌면 타입도 자동으로 반영된다.

integer, text, boolean, timestamp 외에도 json, uuid, numeric, varchar 등 PostgreSQL 컬럼 타입이 전부 지원된다. MySQL과 SQLite 전용 타입도 각각 별도 임포트 경로로 제공된다.

타입 세이프 쿼리 작성법

스키마를 TypeScript로 정의하면 쿼리 반환 타입이 자동으로 추론된다. Prisma처럼 npx prisma generate 같은 별도 코드 생성 단계가 없다.

// Server Component에서 바로 사용
import { eq, desc, like } from 'drizzle-orm';

// SELECT
const result = await db.select().from(posts).where(eq(posts.id, 1));
const list = await db.select().from(posts).orderBy(desc(posts.createdAt)).limit(10);

// INSERT
await db.insert(posts).values({ title: '제목', published: false });

// UPDATE
await db.update(posts).set({ published: true }).where(eq(posts.id, 1));

// DELETE
await db.delete(posts).where(eq(posts.id, 1));

컬럼을 잘못 참조하면 컴파일 에러가 난다. 런타임 에러가 아니다. IDE 자동완성도 그냥 된다.

INSERT의 values 인자에 잘못된 타입을 넣으면 컴파일 시점에 에러가 난다. notNull() 컬럼을 누락해도 바로 잡힌다. 서버 배포 전에 DB 쿼리 실수를 잡는다는 뜻이다.

마이그레이션 — drizzle-kit 워크플로우

스키마 파일을 수정하면 drizzle-kit이 변경분을 감지한다. SQL diff를 자동으로 생성해서 마이그레이션 파일로 저장한다. 생성된 SQL을 직접 볼 수 있어서 블랙박스가 아니다.

// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  schema: './lib/schema.ts',
  out: './drizzle',
  dialect: 'postgresql',
  dbCredentials: { url: process.env.DATABASE_URL! },
});

# 마이그레이션 실행
npx drizzle-kit generate  # SQL 파일 생성
npx drizzle-kit migrate   # DB에 적용

생성된 SQL 파일은 drizzle/ 폴더에 번호 순서대로 쌓인다. git으로 마이그레이션 파일을 커밋하면 팀 전체가 동일한 스키마 히스토리를 가져간다. 스테이징과 프로덕션에 동일한 마이그레이션을 순서대로 적용할 수 있다.

drizzle-kit push vs migrate

push는 마이그레이션 파일 없이 스키마를 DB에 바로 적용한다. 로컬 개발 중 빠르게 테스트할 때 쓴다. migrate는 생성된 SQL 파일을 순서대로 실행한다. 스테이징·프로덕션 배포에는 반드시 migrate를 써야 한다.

지원 DB 목록 — Neon, Supabase, Turso, libSQL

Drizzle은 PostgreSQL, MySQL, SQLite를 지원한다. 서버리스 환경에서 주로 쓰는 DB 서비스들이 전부 공식 연동 가이드를 제공한다. 드라이버별로 import 경로만 다르다.

DB 서비스DB 종류Drizzle 드라이버서버리스 최적화무료 티어
NeonPostgreSQLdrizzle-orm/neon-http기본 지원0.5GB
SupabasePostgreSQLdrizzle-orm/postgres-jsTransaction Pooler 필요500MB
TursoSQLite (libSQL)drizzle-orm/libsql엣지 복제 지원9GB
PlanetScaleMySQLdrizzle-orm/planetscale-serverless기본 지원없음
로컬 SQLiteSQLitedrizzle-orm/better-sqlite3해당 없음무제한

Turso는 SQLite 기반 엣지 DB다. 지역별 복제가 지원돼서 레이턴시가 낮다. 1인 개발자가 무료로 쓸 수 있는 용량이 9GB로 넉넉하다.

Supabase를 Drizzle과 같이 쓸 때는 Auth와 DB 역할을 분리하는 게 일반적이다. Auth는 @supabase/supabase-js를, DB 쿼리는 Drizzle을 맡긴다. 두 SDK가 충돌하지 않는다.

Drizzle vs Prisma — 전체 비교

두 ORM 모두 TypeScript를 지원하고 타입 안전성을 보장한다. 차이는 철학에 있다. Prisma는 추상화를 높게 가져가고, Drizzle은 SQL에 가깝게 유지한다.

항목Drizzle ORMPrisma
번들 사이즈~50KB (gzip ~7KB)~1.6MB (Prisma 7)
Edge 런타임기본 지원어댑터 필요
코드 생성불필요prisma generate 필요
마이그레이션 SQL직접 확인 가능추상화됨
GUI 툴Drizzle Studio (베타)Prisma Studio (안정)
학습 곡선SQL 지식 도움됨SQL 없이 시작 가능
커뮤니티빠르게 성장 중대규모 안정적
적합한 규모1인·소규모, 서버리스대규모 팀

Drizzle을 쓴다고 SQL을 완전히 몰라도 된다. 하지만 SQL을 알면 훨씬 쓰기 편하다. Prisma는 SQL 없이 시작할 수 있지만, 복잡한 쿼리는 raw SQL을 직접 써야 한다.

서버리스 + Next.js + 1인 개발이면 Drizzle을 쓴다. 팀이 크고 Prisma Studio 같은 GUI가 필요하면 Prisma도 나쁘지 않다. 지금 스택이 서버리스라면 Drizzle이 맞는 선택이다.

용도별 추천 — 어떤 상황에서 무엇을 쓰나

상황추천이유
Next.js + Vercel 서버리스Drizzle + Neon콜드 스타트 최소, HTTP 커넥션
Cloudflare WorkersDrizzle + TursoSQLite 엣지 복제, 레이턴시 최소
Supabase Auth 사용 중Drizzle + Supabase DBAuth는 Supabase SDK, 쿼리는 Drizzle
대규모 팀, 복잡한 스키마PrismaPrisma Studio, 안정적 커뮤니티
빠른 로컬 프로토타이핑Drizzle + SQLite파일 기반, 별도 DB 설치 불필요
Drizzle과 Prisma 같이 쓰는 것도 방법이다

성능이 중요한 API에서는 Drizzle을, 어드민 패널처럼 GUI가 편한 곳에서는 Prisma Studio를 쓰는 방식도 있다. 두 ORM이 같은 DB를 바라봐도 된다. 실용적인 선택이면 충분하다.

실전 패턴 — Server Component에서 데이터 읽기

Next.js App Router에서 Server Component는 서버에서만 실행된다. db 인스턴스를 직접 import해서 쓴다. React 상태 관리나 useEffect가 필요 없다.

// app/posts/page.tsx — Server Component
import { db } from '@/lib/db';
import { posts } from '@/lib/schema';
import { desc } from 'drizzle-orm';

export default async function PostsPage() {
  const allPosts = await db.select().from(posts).orderBy(desc(posts.createdAt));
  return <ul>{allPosts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}

// app/api/posts/route.ts — Route Handler
export async function GET() {
  const allPosts = await db.select().from(posts);
  return Response.json(allPosts);
}

Server Component와 Route Handler 모두 동일한 db 인스턴스를 쓴다. lib/db.ts 하나만 유지하면 된다. 커넥션 관리 코드가 없어서 단순하다.

Server Actions에서도 동일하다. 'use server' 함수 안에서 db.insert()를 바로 호출한다. 별도 API 엔드포인트 없이 폼 제출을 처리할 수 있다.

자주 막히는 포인트 3가지

첫 번째는 DATABASE_URL 형식이다. Neon은 URL 끝에 ?sslmode=require가 붙어야 한다. Supabase는 Direct Connection이 아닌 Transaction Pooler URL을 써야 서버리스에서 제대로 동작한다. 대시보드에서 connection string을 복사할 때 서버리스용을 선택하면 된다.

두 번째는 타입 추론 한계다. LEFT JOIN 결과에서 nullable 컬럼이 의도와 다르게 추론될 때가 있다. $inferSelect 타입을 직접 명시하거나 결과에 Partial 타입을 씌우면 해결된다.

세 번째는 마이그레이션 충돌이다. 여러 브랜치에서 동시에 스키마를 변경하면 타임스탬프 기반 파일이 충돌할 수 있다. 마이그레이션 파일은 머지 전에 순서를 맞춰주는 게 안전하다.

FAQ

Q. Drizzle ORM은 Prisma보다 빠른가?

서버리스 콜드 스타트 기준에서는 빠르다. 번들 사이즈가 ~50KB로 Prisma의 ~1.5MB와 차이가 크기 때문이다. 쿼리 실행 속도 자체는 드라이버와 DB 성능에 달려 있어서 ORM만의 차이는 아니다.

Q. Drizzle ORM은 Edge 런타임에서 동작하나?

동작한다. Vercel Edge Functions, Cloudflare Workers 모두 추가 어댑터 없이 지원된다. Prisma는 Accelerate 어댑터가 별도로 필요하다.

Q. 기존 Prisma 프로젝트를 Drizzle로 마이그레이션할 수 있나?

가능하다. Prisma 스키마를 Drizzle 스키마로 수동 변환해야 한다. drizzle-kit의 introspect 기능으로 기존 DB에서 스키마를 자동 생성할 수도 있다. 기존 DB 데이터는 그대로 유지된다.

Q. Drizzle ORM의 단점은 무엇인가?

Prisma Studio 같은 GUI 툴이 베타 단계다. 복잡한 JOIN 쿼리에서 타입 추론이 의도와 다를 때가 있다. Prisma에 비해 커뮤니티 규모가 작아서 레퍼런스 찾기가 어려울 수 있다.

Q. Supabase와 Drizzle을 같이 쓸 수 있나?

가능하다. drizzle-orm/postgres-js 드라이버로 Supabase PostgreSQL에 연결한다. Auth는 @supabase/supabase-js를 그대로 쓰고, DB 쿼리만 Drizzle로 처리한다. 두 SDK가 충돌하지 않는다.

마무리

Drizzle ORM은 서버리스 Next.js에 잘 맞는 ORM이다. 번들 사이즈, Edge 런타임 지원, 코드 생성 불필요 — 세 가지 모두 서버리스 환경에서 실용적인 장점이다. SQL을 쓰는 것처럼 쿼리를 작성하면서 TypeScript 타입이 그냥 따라온다.

Prisma가 나쁜 선택은 아니다. 팀 규모가 크거나 GUI 툴이 중요하다면 Prisma도 충분하다. 1인 개발자나 소규모 서버리스 프로젝트라면 Drizzle + Neon 조합이 빠르고 단순하다.

본 글의 수치 및 기능 정보는 2026년 4월 기준이며, 이후 변경될 수 있다.

공식 문서와 릴리즈 노트를 통해 최신 정보를 확인하는 것을 권장한다.

Share