타입 안전한 ORM은 데이터베이스 스키마에서 TypeScript 타입을 자동 생성 해서, 쿼리의 입력과 출력을 컴파일 타임에 검증합니다.

Prisma의 타입 생성

스키마 정의

PRISMA
// schema.prisma
model User {
  id        Int      @id @default(autoincrement())
  name      String
  email     String   @unique
  posts     Post[]
  createdAt DateTime @default(now())
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

코드 생성 (Code Generation)

BASH
npx prisma generate
# → node_modules/.prisma/client/index.d.ts에 타입 생성

생성되는 타입:

TYPESCRIPT
// 자동 생성된 타입 (간략화)
interface User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

interface Post {
  id: number;
  title: string;
  content: string | null;
  published: boolean;
  authorId: number;
}

타입 안전한 쿼리

TYPESCRIPT
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// ✅ 타입 안전한 CRUD
const user = await prisma.user.create({
  data: {
    name: '홍길동',
    email: 'hong@test.com',
    // id: 1, // ❌ Error — autoincrement이므로 전달 불가
  },
});
// user: User — 반환 타입이 자동 추론

// ✅ 관계 포함 쿼리
const userWithPosts = await prisma.user.findUnique({
  where: { id: 1 },
  include: { posts: true },
});
// userWithPosts: User & { posts: Post[] } | null

// ✅ select로 필드 선택
const partial = await prisma.user.findMany({
  select: { name: true, email: true },
});
// partial: { name: string; email: string }[]

// ❌ 존재하지 않는 필드
// prisma.user.findMany({ where: { phone: '010' } }); // Error

Prisma의 고급 타입 활용

TYPESCRIPT
import { Prisma } from '@prisma/client';

// 모델의 입력 타입
type UserCreateInput = Prisma.UserCreateInput;
// { name: string; email: string; posts?: ... }

// 모델의 where 조건 타입
type UserWhereInput = Prisma.UserWhereInput;
// { id?: number | IntFilter; name?: string | StringFilter; ... }

// select/include에 따른 반환 타입 계산
type UserWithPosts = Prisma.UserGetPayload<{
  include: { posts: true };
}>;
// User & { posts: Post[] }

Drizzle의 타입 추론

Drizzle은 코드 생성 없이 TypeScript 추론만으로 타입을 제공합니다.

스키마 정의

TYPESCRIPT
import { pgTable, serial, text, boolean, integer, timestamp } from 'drizzle-orm/pg-core';

// 스키마가 TypeScript 코드
export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  createdAt: timestamp('created_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').notNull().references(() => users.id),
});

// 타입 추출
type User = typeof users.$inferSelect;
// { id: number; name: string; email: string; createdAt: Date | null }

type NewUser = typeof users.$inferInsert;
// { name: string; email: string; id?: number; createdAt?: Date }

타입 안전한 쿼리

TYPESCRIPT
import { eq, and, gt } from 'drizzle-orm';

// 타입 안전한 쿼리
const allUsers = await db.select().from(users);
// User[]

// 조건부 쿼리
const activeUsers = await db
  .select({ name: users.name, email: users.email })
  .from(users)
  .where(eq(users.name, '홍길동'));
// { name: string; email: string }[]

// 조인
const postsWithAuthor = await db
  .select()
  .from(posts)
  .leftJoin(users, eq(posts.authorId, users.id));
// { posts: Post; users: User | null }[]

Prisma vs Drizzle 비교

특성PrismaDrizzle
타입 생성코드 제너레이터TypeScript 추론
스키마 언어.prisma (독자 DSL)TypeScript
빌드 단계prisma generate 필요불필요
쿼리 스타일객체 기반SQL 유사
번들 크기크다작다
관계 쿼리include 옵션명시적 조인

타입 생성의 내부 원리

Prisma: 코드 생성

PLAINTEXT
schema.prisma → prisma generate → .d.ts 파일 생성 → TypeScript가 읽음

Prisma는 스키마 파일을 파싱해서 TypeScript 타입 선언 파일을 ** 직접 생성 **합니다. 모든 가능한 쿼리 조합에 대한 타입이 미리 생성됩니다.

Drizzle: 타입 추론

PLAINTEXT
TypeScript 스키마 코드 → 제네릭 + 조건부 타입 → TypeScript 컴파일러가 추론

Drizzle은 스키마 정의가 TypeScript 코드이므로 제네릭과 조건부 타입으로 쿼리 결과의 타입을 ** 실시간으로 추론 **합니다.

정리

  • Prisma는 .prisma 스키마에서 TypeScript 타입을 코드 생성한다
  • Drizzle은 스키마가 TypeScript이므로 추론만으로 타입을 제공한다
  • 두 ORM 모두 쿼리의 입력/출력을 컴파일 타임에 검증한다
  • select, include에 따라 반환 타입이 자동으로 달라진다
  • Prisma는 편의성, Drizzle은 유연성과 경량 번들이 강점이다
댓글 로딩 중...