본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 4. · 57 Views
Prisma ORM 기초부터 심화까지
Prisma는 타입 안전성을 제공하는 차세대 ORM입니다. 데이터베이스 스키마 정의부터 복잡한 쿼리, 트랜잭션 처리까지 실무에서 바로 활용 가능한 핵심 기능들을 다룹니다.
들어가며
이 글에서는 Prisma ORM 기초부터 심화까지에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- Prisma_스키마_정의
- Prisma_Client_초기화
- 기본_CRUD_작업
- 관계형_데이터_조회
- 필터링과_정렬
- 트랜잭션_처리
- 집계_함수_사용
- Raw_Query_실행
- 미들웨어_활용
- 페이지네이션_구현
- Upsert_작업
- 연결_끊기와_리소스_정리
1. Prisma 스키마 정의
개요
Prisma 스키마 파일에서 데이터베이스 모델을 정의하는 방법입니다. 타입 안전성과 자동 완성을 제공합니다.
코드 예제
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
}
설명
@id로 기본키를 지정하고, @unique로 유니크 제약조건을 추가합니다. 관계형 필드(posts)로 다른 모델과의 연결을 정의할 수 있습니다.
2. Prisma Client 초기화
개요
Prisma Client를 생성하고 데이터베이스와 연결하는 기본 설정입니다. 싱글톤 패턴으로 재사용합니다.
코드 예제
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
export default prisma
설명
PrismaClient 인스턴스를 생성하여 데이터베이스 작업을 수행합니다. 애플리케이션 전체에서 하나의 인스턴스를 공유하는 것이 권장됩니다.
3. 기본 CRUD 작업
개요
Prisma로 데이터를 생성(Create), 조회(Read), 수정(Update), 삭제(Delete)하는 기본 작업입니다.
코드 예제
// Create
const user = await prisma.user.create({
data: { email: 'test@example.com', name: 'John' }
})
// Read
const users = await prisma.user.findMany()
// Update
await prisma.user.update({
where: { id: 1 },
data: { name: 'Jane' }
})
설명
직관적인 API로 데이터베이스 작업을 수행합니다. TypeScript 타입 추론으로 오타나 타입 오류를 컴파일 시점에 잡을 수 있습니다.
4. 관계형 데이터 조회
개요
include와 select를 사용하여 연관된 데이터를 함께 조회하는 방법입니다. N+1 문제를 방지합니다.
코드 예제
const userWithPosts = await prisma.user.findUnique({
where: { id: 1 },
include: {
posts: {
where: { published: true },
orderBy: { createdAt: 'desc' }
}
}
})
설명
include로 관련 데이터를 한 번의 쿼리로 가져옵니다. 중첩된 where와 orderBy로 세밀한 필터링이 가능합니다.
5. 필터링과 정렬
개요
where 조건으로 데이터를 필터링하고 orderBy로 정렬하는 고급 쿼리 기법입니다.
코드 예제
const filteredUsers = await prisma.user.findMany({
where: {
OR: [
{ email: { contains: 'gmail' } },
{ name: { startsWith: 'J' } }
]
},
orderBy: { createdAt: 'desc' },
take: 10
})
설명
OR, AND 연산자와 contains, startsWith 같은 필터를 조합합니다. take로 결과 개수를 제한하여 페이지네이션을 구현할 수 있습니다.
6. 트랜잭션 처리
개요
여러 데이터베이스 작업을 하나의 트랜잭션으로 묶어 원자성을 보장합니다. 실패 시 모두 롤백됩니다.
코드 예제
await prisma.$transaction(async (tx) => {
const user = await tx.user.create({
data: { email: 'user@test.com' }
})
await tx.post.create({
data: { title: 'First Post', userId: user.id }
})
})
설명
$transaction으로 여러 작업을 묶습니다. 하나라도 실패하면 전체가 롤백되어 데이터 일관성을 유지합니다.
7. 집계 함수 사용
개요
count, avg, sum, min, max 등의 집계 함수로 통계 데이터를 계산합니다.
코드 예제
const stats = await prisma.post.aggregate({
_count: { id: true },
_avg: { views: true },
_max: { createdAt: true },
where: { published: true }
})
console.log(stats._count.id, stats._avg.views)
설명
aggregate API로 데이터베이스 레벨에서 통계를 계산합니다. 대량의 데이터를 효율적으로 처리할 수 있습니다.
8. Raw Query 실행
개요
복잡한 쿼리나 Prisma가 지원하지 않는 기능을 사용할 때 원시 SQL을 직접 실행합니다.
코드 예제
const users = await prisma.$queryRaw`
SELECT * FROM User
WHERE email LIKE ${`%gmail%`}
AND createdAt > ${new Date('2024-01-01')}
`
설명
$queryRaw로 SQL을 직접 작성하되 템플릿 리터럴로 SQL 인젝션을 방지합니다. 복잡한 조인이나 서브쿼리에 유용합니다.
9. 미들웨어 활용
개요
모든 쿼리 실행 전후에 로직을 추가하는 미들웨어로 로깅, 인증, 데이터 변환 등을 구현합니다.
코드 예제
prisma.$use(async (params, next) => {
const before = Date.now()
const result = await next(params)
const after = Date.now()
console.log(`Query ${params.model}.${params.action} took ${after - before}ms`)
return result
})
설명
$use로 미들웨어를 등록합니다. 쿼리 성능 모니터링, 소프트 삭제 구현, 자동 타임스탬프 업데이트 등에 활용됩니다.
10. 페이지네이션 구현
개요
cursor 기반 또는 offset 기반 페이지네이션으로 대용량 데이터를 효율적으로 조회합니다.
코드 예제
// Cursor-based pagination
const posts = await prisma.post.findMany({
take: 10,
skip: 1,
cursor: { id: lastPostId },
orderBy: { id: 'asc' }
})
const nextCursor = posts[posts.length - 1]?.id
설명
cursor 기반 페이지네이션은 대용량 데이터에서 성능이 우수합니다. take로 가져올 개수, skip으로 커서 자체를 제외합니다.
11. Upsert 작업
개요
데이터가 존재하면 업데이트하고, 없으면 생성하는 upsert 연산입니다. 중복 처리 로직을 단순화합니다.
코드 예제
const user = await prisma.user.upsert({
where: { email: 'user@example.com' },
update: { name: 'Updated Name' },
create: {
email: 'user@example.com',
name: 'New User'
}
})
설명
where 조건으로 찾은 레코드가 있으면 update를, 없으면 create를 실행합니다. 원자적으로 처리되어 동시성 문제를 방지합니다.
12. 연결 끊기와 리소스 정리
개요
애플리케이션 종료 시 데이터베이스 연결을 안전하게 종료하여 리소스를 정리합니다.
코드 예제
async function main() {
// Your database operations
}
main()
.catch(console.error)
.finally(async () => {
await prisma.$disconnect()
})
설명
$disconnect()로 연결 풀을 정리합니다. 서버리스 환경에서는 각 요청 후, 장기 실행 앱에서는 종료 시 호출합니다.
마치며
이번 글에서는 Prisma ORM 기초부터 심화까지에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Prisma #ORM #TypeScript #Database #Schema
이 카드뉴스가 포함된 코스
댓글 (0)
함께 보면 좋은 카드 뉴스
UX와 협업 패턴 완벽 가이드
AI 에이전트와 사용자 간의 효과적인 협업을 위한 UX 패턴을 다룹니다. 프롬프트 핸드오프부터 인터럽트 처리까지, 현대적인 에이전트 시스템 설계의 핵심을 배웁니다.
자가 치유 및 재시도 패턴 완벽 가이드
AI 에이전트와 분산 시스템에서 필수적인 자가 치유 패턴을 다룹니다. 에러 감지부터 서킷 브레이커까지, 시스템을 스스로 복구하는 탄력적인 코드 작성법을 배워봅니다.
Feedback Loops 컴파일러와 CI/CD 완벽 가이드
컴파일러 피드백 루프부터 CI/CD 파이프라인, 테스트 자동화, 자가 치유 빌드까지 현대 개발 워크플로우의 핵심을 다룹니다. 초급 개발자도 쉽게 이해할 수 있도록 실무 예제와 함께 설명합니다.
실전 MCP 통합 프로젝트 완벽 가이드
Model Context Protocol을 활용한 실전 통합 프로젝트를 처음부터 끝까지 구축하는 방법을 다룹니다. 아키텍처 설계부터 멀티 서버 통합, 모니터링, 배포까지 운영 레벨의 MCP 시스템을 구축하는 노하우를 담았습니다.
MCP 동적 도구 업데이트 완벽 가이드
AI 에이전트의 도구를 런타임에 동적으로 로딩하고 관리하는 방법을 알아봅니다. 플러그인 시스템 설계부터 핫 리로딩, 보안까지 실무에서 바로 적용할 수 있는 내용을 다룹니다.