Prisma = JavaScript/TypeScript로 데이터베이스를 쉽게 다루게 해주는 도구(ORM)
Prisma란? 한 문장 정의 관련 이미지
ORM(Object-Relational Mapping)이라는 용어가 어렵게 느껴질 수 있어요. 쉽게 말하면:
기존 방식
Prisma 사용 시
SQL 쿼리 직접 작성
JavaScript 코드로 작성
타입 체크 없음
TypeScript 자동 타입 지원
DB별로 문법 다름
동일한 코드, DB만 교체
지원하는 데이터베이스
Prisma는 다양한 DB를 지원합니다:
관계형 DB: PostgreSQL, MySQL, SQLite, SQL Server
NoSQL: MongoDB
서버리스: PlanetScale, Neon, Supabase
💡 Pro Tip: 개발할 때는 SQLite(파일 기반)로 시작하고, 배포할 때 PostgreSQL로 바꾸는 패턴이 인기 있어요. 코드 변경 거의 없이 가능합니다!
왜 Prisma를 쓰나요?
문제 상황: 기존 방식의 불편함
SQL을 직접 쓰면 이런 코드가 됩니다:
// 😰 기존 방식: SQL 직접 작성const users = await db.query( 'SELECT * FROM users WHERE email = ? AND deleted_at IS NULL', [email]);// 결과 타입이 any... 오타 있어도 런타임에서야 발견됨
본문 관련 이미지
해결책: Prisma 방식
// 😊 Prisma 방식: 타입 안전한 코드const users = await prisma.user.findMany({ where: { email: email, deletedAt: null }});// 자동완성 지원 + 타입 체크 + 오타는 컴파일 에러로 즉시 발견
// prisma/schema.prisma// 1. DB 연결 설정datasource db { provider = "sqlite" // 또는 "postgresql", "mysql" url = "file:./dev.db" // SQLite는 파일 경로}// 2. Prisma Client 생성 설정generator client { provider = "prisma-client-js"}// 3. 데이터 모델 정의 (테이블)model User { id Int @id @default(autoincrement()) email String @unique name String? 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}
스키마 문법 빠른 정리:
문법
의미
예시
@id
기본키
id Int @id
@unique
유니크 제약
email String @unique
@default()
기본값
@default(now())
?
선택적 필드
name String?
[]
일대다 관계
posts Post[]
Step 3: DB에 반영하기
# 스키마를 DB에 반영 (테이블 생성)npx prisma db push# Prisma Client 생성 (타입 정의 파일)npx prisma generate
Step 4: 코드에서 사용하기
// src/index.tsimport { PrismaClient } from '@prisma/client'const prisma = new PrismaClient()async function main() { // 유저 생성 const user = await prisma.user.create({ data: { email: 'alice@example.com', name: 'Alice' } }) console.log('생성된 유저:', user)}main()
💡 Pro Tip: npx prisma studio 명령어를 실행하면 브라우저에서 DB를 GUI로 볼 수 있어요!
실전 CRUD 코드 예시
Create (생성)
// 단일 생성const user = await prisma.user.create({ data: { email: 'bob@example.com', name: 'Bob' }})// 관계 데이터와 함께 생성const userWithPost = await prisma.user.create({ data: { email: 'charlie@example.com', name: 'Charlie', posts: { create: { title: '첫 번째 글', content: '안녕하세요!' } } }})
Read (조회)
// 전체 조회const allUsers = await prisma.user.findMany()// 조건 조회const user = await prisma.user.findUnique({ where: { email: 'alice@example.com' }})// 관계 데이터 포함 조회const userWithPosts = await prisma.user.findUnique({ where: { id: 1 }, include: { posts: true } // 해당 유저의 posts도 가져옴})// 필터링 + 정렬 + 페이지네이션const recentUsers = await prisma.user.findMany({ where: { name: { contains: 'a' } // 이름에 'a' 포함 }, orderBy: { createdAt: 'desc' }, // 최신순 take: 10, // 10개만 skip: 0 // 0번째부터})