Prisma ORM(Object-Relational Mapping)
: Node.js에서 사용 가능한 ORM
ORM이란?
데이터베이스와 상호작용할 때 SQL 쿼리가 아닌, 프로그래밍 언어(js에선 객체)로 테이블의 데이터를 처리 가능하게 하는 프로그래밍 기술
- 타입 안전함. 즉, 코드를 짤 때 데이터 타입을 가이드 해줌
간단 ex)
// 매핑 정의 model User { id Int @id @default(autoincrement()) name String @unique email String? @unique } // 객체로 데이터 조작 const user = await prisma.user.create({ data: { name: "John", email: "john@example.com" }, }); // name, email의 타입을 확인 가능
Prisma의 주요 구성 요소
- Prisma Client : 데이터에 맞춰 자동 생성되는 타입안전 쿼리 빌더
- Prisma Migrate : 데이터베이스 - 스키마 동기화

- Prisma Studio : CRUD를 로컬에서 시각적으로 할 수 있음
Prisma의 특징
- 서버컴포넌트에서만 사용 가능
- 타입 안전성:
- Prisma Client는 타입스크립트를 기반으로 자동 생성되며, 데이터 모델에 따라 타입이 자동으로 정의됨
- 생산성 향상
- 간단하고 직관적인 API로 데이터베이스 작업을 빠르게 처리가능
- 다중 데이터베이스 지원
- MySQL, PostgreSQL, SQLite, MongoDB 등 다양한 데이터베이스를 지원
- 마이그레이션 관리:
- Prisma Migrate를 통해 데이터베이스 스키마 변경 작업을 체계적으로 관리할 수 있음
- 데이터 정합성 보장
- 관계형 데이터베이스의 관계를 쉽게 정의하고 관리할 수 있음
사용 방법
npm i prisma
npx prisma init
: 기본 설정 파일 생성(schema.prisma
파일을 생성 후 스키마 추가,.env
파일에 데이터베이스 연결 URL을 추가)- 밑에 코드들이 자동으로 생성&추가 됨
// 데이터베이스 연결 URL을 설정 DATABASE_URL="file:./dev.db" //SQLite
datasource db { provider = "sqlite" // 사용할 데이터베이스 (sqlite, postgresql 등) url = env("DATABASE_URL") // DB 위치 } generator client { provider = "prisma-client-js" }
fyi) SQLite?
로컬 db. 서버 호스팅 안해도 됨
- Prisma 스키마 정의
- createdAt, updatedAt는 사용되지 않더라도 기본으로 넣어주는 것이 좋음
model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
npx prisma migrate dev --name 저장이름
: 데이터베이스 마이그레이션npx prisma generate
도 같이 실행 됨 : Prisma Client 생성
⇒ 스키마를 업데이트 할 때마다 이 명령어를 실행해야 함
이후 생성되는 db관련 파일을 .gitignore파일에 추가해줘야 함
*.db *.db-journal
- Prisma Client 사용
step 1) lib안에 ts파일 생성(여기선 lib/prisma.ts)
step 2) Prisma Client 인스턴스 초기화
// lib/prisma.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); export default prisma;
- CRUD하기
const users = await prisma.user.findMany();

npx prisma studio
: prisma Studio 실행
필드 속성


Prisma Schema API
API reference documentation for the Prisma Schema Language (PSL).
@id
- 해당 필드를 Primary Key로 지정
- Primary Key는 반드시 하나의 모델에 있어야 하며, Null 값을 허용 x
@default
- 필드의 기본값을 설정
- 정적 값, 함수 등으로 값 설정 가능
- 지원되는 함수:
•
autoincrement()
: 자동 증가 값 (숫자 필드). •cuid()
,uuid()
: 고유 식별자 생성. •now()
: 현재 시간.
id Int @id @default(autoincrement()) createdAt DateTime @default(now()) status String @default("active")
@unique
- 해당 필드 값이 고유해야 함을 지정
@map
- Prisma 모델의 필드를 데이터베이스의 다른 열 이름에 매핑
firstName String @map("first_name")
@relation
- 모델 간 관계를 정의
- 외래 키 및 참조 키를 명시적으로 지정
author User @relation(fields: [authorId], references: [id]) authorId Int
@@id
- 복합 id, 두개의 값의 조합이 id가 된다
model User { id Int @id @default(autoincrement()) name String post Post[] likes Like[] } model Post { id Int @id @default(autoincrement()) content String User User? @relation(fields: [userId], references: [id]) userId Int? likes Like[] } model Like { postId Int userId Int User User @relation(fields: [userId], references: [id]) Post Post @relation(fields: [postId], references: [id]) @@id([postId, userId]) }
쿼리 옵션
- where : 특정 조건을 만족하는 데이터 필터링
- 조건 연산자:
equals
,contains
,startsWith
,endsWith
,gt
(greater than),lt
(less than) 등. - 논리 연산자:
AND
,OR
,NOT
.
// 특정 이메일을 가진 사용자 조회 const user = await prisma.user.findMany({ where: { email: "example@prisma.io", }, }); // 여러 조건을 결합하여 필터링 const users = await prisma.user.findMany({ where: { AND: [ { isActive: true }, { email: { contains: "@prisma.io" } }, ], }, });
- select : 필드 선택
- 반환되는 데이터에서 특정 필드만 선택하여 가져옴
// 사용자 이름과 이메일만 가져오기 const user = await prisma.user.findUnique({ where: { id: 1 }, select: { name: true, email: true, }, });
- include : 관계 데이터 포함(중첩)
// 사용자와 해당 사용자의 게시물(Post)을 함께 가져오기 const userWithPosts = await prisma.user.findUnique({ where: { id: 1 }, include: { posts: true, }, });
- orderBy : 정렬
// 사용자 데이터를 생성일 기준으로 내림차순 정렬 const users = await prisma.user.findMany({ orderBy: { createdAt: "desc", }, });
- take, skip : 페이징
- take: 가져올 데이터의 최대 개수를 제한합니다.
- skip: 지정된 개수만큼 데이터를 건너뜁니다.
// 첫 번째 페이지의 첫 10명의 사용자 가져오기 const users = await prisma.user.findMany({ take: 10, skip: 0, }); // 두 번째 페이지의 다음 10명의 사용자 가져오기 const nextUsers = await prisma.user.findMany({ take: 10, skip: 10, });
- distinct : 중복 제거 • 특정 필드를 기준으로 중복 제거도 가능
// 고유한 이메일을 가진 사용자 목록 가져오기 const uniqueEmails = await prisma.user.findMany({ distinct: ["email"], });
_count
변수:- 최상위 레벨(
include
orselect
) 내부에서 사용할 수 있음
const posts = await prisma.post.findMany({ select: { id: true, title: true, description: true, views: true, created_at: true, _count: { select: { comments: true, likes: true, }, }, }, });
연산 in update

const updatePosts = await prisma.post.updateMany({ data: { views: { increment: 1, //views를 기존에서 +1 }, likes: { set: 0, //like를 0으로 set }, }, });
relation
B모델이 A모델을 참조하는걸 나타내려면?
ex)
model User { SMSToken SMSToken[] } model SMSToken { ... user User @relatioin(fields:[userId], references: [id]) //실제 db에는 추가ㄴㄴ userId Int //실제 db에는 이 id필드만 추가됨 }
@relatioin 코드 자동완성하는 법
- Prisma VScode extension 설치
- cmd + p
- JSON settings 파일을 열기
- 아래 코드 추가
"[prisma]": { "editor.defaultFormatter": "Prisma.prisma" }
client 예시코드
const token = await prisma.sMSToken.create({ data: { token: "123123", user: { connect {//id 3인 사용자와 연결 (create는 사용자 생성) id: 3 } } } })
onDelete
- relation에서 어떤 모델이 다른 모델에 의해 참조되고 있다면, 그 모델은 삭제하지 못한다.
- 삭제하려면? ⇒ 참조하는 모델도 같이 같이 삭제하는 방법!
- onDelete: Cascade!
user User @relatioin(fields:[userId], references: [id]), onDelete: Cascade
- onDelete: SetNull ⇒ 참조했던 모델이 삭제되면 필드 값이 null이 됨
- 참조 필드를 optional로 둬야 함
user User? @relatioin(fields:[userId], references: [id], onDelete: SetNull) userId Int?
- Restrict(기본값): 참조 레코드가 있는 경우 삭제를 방지
- NoAction: Restrict과 유사하지만 사용 중인 데이터베이스에 따라 다릅
- SetDefault: 참조 필드가 기본값으로 설정
- VScode Extension 설치 권장
- Prisma ⇒ 문법강조, 포매팅, 자동 완성 등
- SQLite Viewer ⇒ .db 파일(스키마) 시각화
fyi
page에서
import 파일
>> 해당 페이지에 접속하면 해당 파일을 실행