6.8 KiB
6.8 KiB
Drizzle ORM 마이그레이션 완료 ✅
🎉 변경 사항 요약
JWT 인증 시스템이 순수 SQL에서 Drizzle ORM으로 완전히 마이그레이션되었습니다.
📊 Before & After
Before (순수 SQL)
// ❌ 타입 안전성 없음
const user = await db
.prepare('SELECT id, email, password_hash, nickname FROM users WHERE email = ?')
.bind(email)
.first<User>();
After (Drizzle ORM)
// ✅ 완전한 타입 안전성
const [user] = await drizzleDb
.select()
.from(users)
.where(eq(users.email, email))
.limit(1);
📦 설치된 패키지
{
"dependencies": {
"drizzle-orm": "^0.44.7",
"jose": "^6.1.2"
},
"devDependencies": {
"drizzle-kit": "^0.31.7"
}
}
📁 새로운 파일 구조
프로젝트/
├── drizzle.config.ts # ✨ 신규: Drizzle 설정
├── drizzle/ # ✨ 신규: 마이그레이션 디렉토리
│ ├── 0000_omniscient_lady_mastermind.sql
│ └── meta/
├── src/
│ └── lib/
│ └── server/
│ ├── schema.ts # ✨ 신규: Drizzle 스키마
│ ├── db.ts # 🔄 수정: Drizzle 사용
│ └── auth.ts # 유지
├── AUTH_GUIDE.md # 🔄 업데이트
├── DRIZZLE_GUIDE.md # ✨ 신규
└── package.json # 🔄 스크립트 추가
🛠️ 새로운 NPM 스크립트
# Drizzle 마이그레이션 생성
pnpm db:generate
# 로컬 DB에 적용
pnpm db:push
# 프로덕션 DB에 적용
pnpm db:push:remote
# Drizzle Studio 실행
pnpm db:studio
# DB 쿼리 (로컬)
pnpm db:query
# DB 쿼리 (프로덕션)
pnpm db:query:remote
🔧 주요 변경 파일
1. src/lib/server/schema.ts (신규)
Drizzle 스키마 정의:
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
import { sql } from 'drizzle-orm';
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
email: text('email').notNull().unique(),
passwordHash: text('password_hash').notNull(),
nickname: text('nickname').notNull(),
createdAt: integer('created_at', { mode: 'timestamp' })
.notNull()
.default(sql`(strftime('%s', 'now'))`)
});
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
2. src/lib/server/db.ts (수정)
Drizzle ORM 사용:
import { drizzle } from 'drizzle-orm/d1';
import { eq } from 'drizzle-orm';
import { users, type User, type NewUser } from './schema';
export function getDb(d1: D1Database) {
return drizzle(d1);
}
export async function getUserByEmail(db: D1Database, email: string) {
const drizzleDb = getDb(db);
const [user] = await drizzleDb
.select()
.from(users)
.where(eq(users.email, email))
.limit(1);
return user || null;
}
3. drizzle.config.ts (신규)
Drizzle 설정:
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/lib/server/schema.ts',
out: './drizzle',
dialect: 'sqlite'
});
✅ 테스트 완료
- Drizzle ORM 설치 완료
- 스키마 정의 완료
- 마이그레이션 생성 완료
- 로컬 DB 적용 완료
- db.ts Drizzle로 변환 완료
- TypeScript 빌드 성공
- 모든 함수 타입 안전성 확보
🚀 실행 방법
1. 데이터베이스 초기화
# 이미 완료됨! 마이그레이션이 로컬 DB에 적용되었습니다.
pnpm db:push # 필요시 재실행
2. 개발 서버 실행
pnpm cf:dev
3. 테스트
- http://localhost:8787/register - 회원가입
- http://localhost:8787/login - 로그인
- http://localhost:8787 - 메인 페이지
🎯 Drizzle ORM의 이점
1. 타입 안전성
// 컴파일 타임에 에러 발견
const user = await drizzleDb
.select()
.from(users)
.where(eq(users.emial, email)); // ← 컴파일 에러!
// ^^^^^ 오타
2. 자동 완성
IDE에서 테이블과 컬럼에 대한 완벽한 자동 완성 지원
3. 자동 마이그레이션
# 스키마 변경 후
pnpm db:generate # SQL 자동 생성
4. SQL 인젝션 방지
모든 쿼리가 자동으로 파라미터화됨
5. 리팩토링 용이
테이블/컬럼명 변경 시 TypeScript가 모든 사용처를 찾아줌
📚 문서
-
DRIZZLE_GUIDE.md- Drizzle ORM 상세 가이드- 스키마 정의 방법
- 고급 쿼리 예제
- 마이그레이션 관리
- Drizzle Studio 사용법
-
AUTH_GUIDE.md- JWT 인증 가이드 (Drizzle 반영)- 로컬 개발 환경 설정
- 프로덕션 배포
- 보안 고려사항
-
IMPLEMENTATION_SUMMARY.md- 전체 구현 요약
🔄 마이그레이션 히스토리
drizzle/
└── 0000_omniscient_lady_mastermind.sql # 초기 users 테이블
💡 다음 단계 제안
이제 Drizzle ORM을 활용하여 쉽게 기능을 확장할 수 있습니다:
1. 프로필 기능 추가
export const profiles = sqliteTable('profiles', {
id: integer('id').primaryKey({ autoIncrement: true }),
userId: integer('user_id').references(() => users.id),
avatar: text('avatar'),
bio: text('bio')
});
2. 게시글 시스템
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey({ autoIncrement: true }),
userId: integer('user_id').references(() => users.id),
title: text('title').notNull(),
content: text('content').notNull(),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull()
});
3. 댓글 기능
export const comments = sqliteTable('comments', {
id: integer('id').primaryKey({ autoIncrement: true }),
postId: integer('post_id').references(() => posts.id),
userId: integer('user_id').references(() => users.id),
content: text('content').notNull()
});
모든 관계가 타입 안전하게 관리됩니다!
🎊 완료!
Drizzle ORM으로의 마이그레이션이 성공적으로 완료되었습니다!
- ✅ 타입 안전성 확보
- ✅ 개발 생산성 향상
- ✅ 유지보수성 개선
- ✅ 자동 마이그레이션 시스템 구축
이제 다음 명령어로 서버를 실행하세요:
pnpm cf:dev
생성된 파일:
- ✨
drizzle.config.ts - ✨
src/lib/server/schema.ts - 🔄
src/lib/server/db.ts(Drizzle로 재작성) - ✨
drizzle/0000_omniscient_lady_mastermind.sql - ✨
DRIZZLE_GUIDE.md - 🔄
AUTH_GUIDE.md(업데이트) - 🔄
package.json(스크립트 추가)
기존 파일 백업:
- 📦
src/lib/server/db-old.ts(순수 SQL 버전)