01. Drizzle ORM 소개
2026년 2월 16일 수정됨
📋 개요
ORM(Object-Relational Mapping)은 데이터베이스 테이블을 코드의 객체로 매핑하여, SQL을 직접 작성하지 않고도 데이터베이스를 조작할 수 있게 해주는 도구입니다.
📋 목차
ORM이란?
ORM(Object-Relational Mapping)은 데이터베이스 테이블을 코드의 객체로 매핑하여, SQL을 직접 작성하지 않고도 데이터베이스를 조작할 수 있게 해주는 도구입니다.
┌─────────────────────────────────────────────────────────┐
│ TypeScript 코드 ←→ ORM ←→ PostgreSQL │
│ db.select().from(users) → SELECT * FROM users │
└─────────────────────────────────────────────────────────┘
Drizzle ORM 특징
| 특징 | 설명 |
|---|---|
| 타입 안전성 | 스키마에서 TypeScript 타입 자동 추론 |
| SQL-like 문법 | SQL과 유사한 API로 학습 곡선 낮음 |
| 경량 | 런타임 의존성 최소화, 빠른 실행 속도 |
| Serverless 최적화 | Edge 환경에서도 동작 |
프로젝트 구조
packages/schema/ # 공유 스키마 패키지
├── src/
│ ├── schema/ # 테이블 정의
│ │ ├── users.ts # 사용자 테이블
│ │ ├── stocks.ts # 주식 테이블
│ │ └── index.ts # 스키마 내보내기
│ └── index.ts # 메인 진입점
└── drizzle.config.ts # Drizzle Kit 설정
구조 설명:
packages/schema/: 모노레포에서 FE/BE가 공유하는 스키마 패키지입니다.schema/: 각 도메인별 테이블 정의를 분리하여 관리합니다.drizzle.config.ts: 마이그레이션, DB 연결 등 Drizzle Kit 도구 설정 파일입니다.
데이터베이스 연결
// packages/schema/src/db.ts
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
// 1. PostgreSQL 클라이언트 생성
const client = postgres(process.env.DATABASE_URL!, {
max: 10, // 최대 연결 수
idle_timeout: 20, // 유휴 연결 타임아웃 (초)
connect_timeout: 10, // 연결 타임아웃 (초)
});
// 2. Drizzle 인스턴스 생성
export const db = drizzle(client, { schema });코드 설명:
postgres(DATABASE_URL):postgres라이브러리로 PostgreSQL에 연결합니다. 연결 풀 설정도 여기서 지정합니다.max: 10: 동시에 유지할 수 있는 최대 DB 연결 수입니다. 서버 부하에 따라 조절합니다.drizzle(client, { schema }): Drizzle 인스턴스를 생성합니다.schema를 전달하면 관계형 쿼리 API를 사용할 수 있습니다.export const db: 이 인스턴스를 애플리케이션 전체에서 임포트하여 사용합니다.
첫 번째 스키마 정의
// packages/schema/src/schema/users.ts
import { pgTable, uuid, varchar, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
// uuid 타입의 기본키, 자동 생성
id: uuid('id').primaryKey().defaultRandom(),
// varchar(100) 타입, null 불가, 중복 불가
email: varchar('email', { length: 100 }).notNull().unique(),
// varchar(50) 타입, null 불가
name: varchar('name', { length: 50 }).notNull(),
// 생성 시간, 기본값: 현재 시간
createdAt: timestamp('created_at').defaultNow().notNull(),
// 수정 시간, 레코드 변경 시 자동 업데이트
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});각 컬럼 설명:
uuid('id'): PostgreSQL의 UUID 타입입니다.defaultRandom()은 자동으로 고유 ID를 생성합니다.varchar('email', { length: 100 }): 최대 100자 문자열입니다.unique()로 중복 이메일을 방지합니다.timestamp('created_at'): 날짜/시간 타입입니다.defaultNow()는 INSERT 시 현재 시간을 자동 설정합니다..notNull(): NULL 값을 허용하지 않는 제약 조건입니다.
기본 조회 예제
import { db } from './db';
import { users } from './schema';
import { eq } from 'drizzle-orm';
// 모든 사용자 조회
const allUsers = await db.select().from(users);
// 특정 사용자 조회
const user = await db
.select()
.from(users)
.where(eq(users.id, 'user-uuid-here'));코드 설명:
db.select().from(users):SELECT * FROM users와 동일합니다. 모든 컬럼을 가져옵니다.eq(users.id, 'user-uuid-here'):WHERE id = 'user-uuid-here'조건입니다.eq는 equality(동등) 비교 연산자입니다.where(): SQL의 WHERE 절에 해당하며, 여러 조건을 체이닝할 수 있습니다.
레퍼런스
다음 장: 02. 스키마 기초