Prisma를 사용해보세요
SPARCS 서비스 중 하나인 OTL plus 팀에 백엔드 신입으로 참여하여 Nest.js를 이용한 여러 기능 구현 과제를 수행하게 되었습니다. 이 과정에서 MySQL과 Prisma ORM을 사용하게 되었고, 공식 문서에 잘 나와 있긴 하지만 직접 사용해 본 경험을 바탕으로 Prisma에 대한 간단한 소개를 해보겠습니다.(초보자의 경험을 바탕으로 적은 글이므로 더 쉬운 방법이나 오류가 있을 수 있습니다.. 양해 부탁드립니다😭)
Prisma가 뭐죠?
간단하게 설명하자면 Prisma ORM은 TypeScript와 JavaScript를 위한 데이터베이스 ORM입니다. Prisma를 사용하면 개발자가 SQL 쿼리를 직접 작성할 필요 없이, 모델과 필드를 정의하고, Prisma CLI를 사용하여 데이터베이스 스키마를 자동으로 생성할 수 있습니다. 이를 통해 데이터베이스 스키마 변경 시, TypeScript/JavaScript 코드가 자동으로 업데이트되기 때문에 개발 생산성을 높일 수 있습니다.
스키마 파일 작성
Prisma를 사용하기 위해서 진행해야 하 는 가장 첫 단계라 할 수 있는 prsma schema 파일 작성입니다. 연결하는 DB에 대한 정보와 생성할 Model들에 대해 작성해줍니다. prisma schema파일은 Data sources, Generator, Data model definition의 세 부분으로 나눌 수 있습니다.
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
anonymous Boolean @default(true)
auth Auth @default(USER)
}
enum Auth{
USER
ADMIN
}
Data sources는 prisma가 어떤 데이터 베이스에 어떻게 연결할지에 대한 정보를 적는 부분입니다. 연결하고자 하는 데이터 베이스의 종류(mysql, postgresql 등)와 데이터베이스 URL을 적어주면 됩니다. 여기서 URL의 경우 dotenv를 이용하여 env(DB URL입력)
의 방식으로 환경파일을 사용함으로써 개발 데이터베이스와 프로덕션 데이터베이스를 분리할 수 있습니다. Generators는 prisma generate명렁어를 사용할 때 어떤 클라이언트를 생성할 것인지에 대해 설정해주는 부분입니다. Data model definition 테이블간의 관계, 각 field의 타입등 application model(Prisma model)들을 정의하는 부분입니다. TypeScript를 사용할 경우 index.ts파일에 prisma schema파일에서 지정해준 type에 맞게 다음과 같이 prisma client code를 자동생성해줍니다.
export type User = {
id: number @default(autoincrement()) @id
email: string @unique()
name: string | null
anonymous: boolean
auth: Auth
}
export const Auth: {
USER: 'USER',
ADMIN: 'ADMIN'
};
export type Auth = (typeof Auth)[keyof typeof Auth]
enum, type 을 사용해 새로운 타입을 지정할 수도 있고, @id
, @unique
, @default
같은 attribute, autoincrement()
, now()
같은 function을 사용할수도 있습니다. 각 model은 record를 식별하기 위해서 @id
, @@id
, @unique
, @@unique
중 최소한 하나를 지정해야 합니다. 여기서 @@는 두 field를 하나로 묶는다는 의미입니다. 다음과 같은 방식으로 지정하여 뒤에 설명할 update
나 findunique
에서 unique input으로 사용할 수 있습니다.
@@unique(fields: [id, isDeleted], name:"validChat")
schema파일에서 @relation을 이용하여 data model사이의 1:1, 1:N, N:M, 자기 참조 관계들을 생성할 수 있습니다.
model User {
id Int @id @default(autoincrement())
email String @unique
name String
test Test?
}
model Test{
id Int @id @default(autoincrement())
content String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
tests Test[]
}
model Test{
id Int @id @default(autoincrement())
content String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
anonymous Boolean @default(true)
spaces UsersInSpaces[]
}
model Space{
id Int @default(autoincrement()) @id
name String @unique
users UsersInSpaces[]
}
model UsersInSpaces{
user User @relation(fields: [userId], references:[id], onDelete: Cascade)
userId Int
space Space @relation(fields: [spaceId], references:[id], onDelete: Cascade)
spaceId Int
@@unique(fields: [userId, spaceId], name:"userspace")
@@id([userId, spaceId,roleId])
}
model Chat{
id Int @default(autoincrement()) @id
content String
chat Chat[] @relation("chat")
parent Chat? @relation("chat", fields: [parentId], references: [id])
parentId Int? @map("chatid")
level Int @default(0)
order Int @default(0)
@@unique(fields: [id, isDeleted], name:"validchat")
}