Object Relational Mapping
은 우리가 DB에서 다루는 객체를 추상화시켜 OOP적 사고방식을 적용시키기 위해 사용한다.
DB를 사용하는 유저들 중에서 SQL을 모르는 유저는 없을 것이지만 필요한 DB 작업을 위해 SQL Query문을 짜는 것은 많은 시간을 필요로 하여 비용이 크다. 또한 쿼리문을 통해 받은 데이터는 추상화가 전혀 되어 있지 않은 평문 데이터이기 때문에 이 데이터에 어떤 정보가 있을지 알 수 없다. 또한 Entity에 변경이 필요할 경우 모든 Query를 수정해야하는 대참사가 일어날수도 있다. 이를 해결하기 위해 ORM의 사용은 필요하다고 생각한다.
Raw Query
문에 비해 성능이 떨어진다.prisma의 공식 홈페이지를 보면 Next-generation Node.js and TypeScript ORM
이라고 적혀있다.
기존에 node.js에서 사용하던 Sequelize
나 TypeORM
은 node.js치고는 많은 추상화 수준을 갖추게 해줬지만 그에 맞게 성능은 많이 떨어지는 모습을 보여줬다.
하지만 prisma
는 Client
와 Migrate
, Studio
로 나누어 구성되어 있어 더 높은 생산성을 얻을 수 있고 동시에 높은 제어성을 갖게 되었다.
Client
client는 prisma의 schema 정보를 입력받아 미리 object들을 구성하고 사용할 수 있게 해줍니다. 그래서 schema를 변경하면 다시 반영해주는 명령어를 실행해야 합니다.
Migrate
DB에 직접 적용시키는 migration을 담당하는 부분입니다.
Studio
데이터베이스에 접근하여 보고 편집할 수 있는 GUI입니다.
prisma의 쿼리는 client를 통하여 접근하고 이를 Query Engine을 통해 원하는 데이터를 받아와 더 나은 성능과 한단계 높은 추상화를 제공해줍니다.
우선 공식 사이트에 나와 있는 QuickStart를 따라해보자.
# 디렉토리 생성
mkdir hello-prisma
cd hello-prisma
# 프로젝트 생성 및 typescript, node 설치
npm init -y
npm install typescript ts-node @types/node --save-dev
# typescript 초기 설정
npx tsc --init
# prisma 설치
npm install prisma --save-dev
# prisma 초기 설정
npx prisma init --datasource-provider `DB Engine 이름`# ex) sqlite, mysql, postgresql...
다음과 같이 초기설정을 해준 후에 생성된 prisma/schema.prisma
파일을 수정하여 Prisma Schema 설정을 해주면 된다.
generator client {
provider = "prisma-client-js"
}
// env 파일로 DATABASE_URL을 넣어주면 된다.
// mysql의 경우는 다음과 같은 주소이다.
// mysql://mysql유저:비밀번호@서버 주소:포트번호/DB이름
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
// domain Type Attributes
user_id Int @id @default(autoincrement())
name String @unique
info String
created_date DateTime @default(now())
updated_date DateTime @updatedAt
posts Post[]
}
model Post {
post_id Int @id @default(autoincrement())
title String
// Not Null이 아니면 ?로 표시한다.
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [user_id])
authorId Int
}
prisma의 포맷을 지원하는 익스텐션은
VSCode
에만 있으므로 다른 IDE를 쓸때에는prisma format
명령어를 사용하여 이쁘게 맞춰줄 수 있다.
사용가능한 Type은 정해져있어 사용하는 DB 엔진에 맞게 알아서 변환을 해준다.
schema 관련 참고 - Type과 Attributes
schema를 적용시킨 DB가 있을 수 있지만 만든 schema를 서버에 적용시키려면 다음 명령어를 통해 migration 가능하다.
npx prisma migrate dev --name init
그리고 스키마를 client에 반영시켜줘야한다. 다음 명령어를 실행해주자.
npx prisma generate
서버에서 사용하려면 client에서 Type을 받아와 사용가능하다.
User에 대한 CRUD service는 다음과 같이 구현하면 된다.
// User.servite.ts
import { PrismaClient, User } from '@prisma/client'
const prisma = new PrismaClient()
const CountPerPage = 20
class UserService {
public getAllUsers = async (pageNo: number): Promise<User[]> => {
const skipNo = pageNo * CountPerPage;
const result = await prisma.user.findMany({
// pagination은 다음과 같이 할 수 있다.
skip: skipNo,
take: CountPerPage,
});
prisma.$disconnect()
return result
};
public getUserById = async (userId: number): Promise<User> => {
const result = await prisma.user.findUniqueOrThrow({
where: { user_id: userId },
});
prisma.$disconnect();
return result;
};
public createUser = async (user: UserDto): Promise<User> => {
const result = await prisma.user.create({
data: user,
});
prisma.$disconnect();
return result;
};
public updateUser = async (userId: number, user: UserDto): Promise<User> => {
const result = await prisma.user.update({
where: { user_id: userId },
data: user,
});
prisma.$disconnect();
return result;
};
public deleteUser = async (userId: number): Promise<User> => {
const result = await prisma.user.delete({
where: { user_id: userId },
});
prisma.$disconnect();
return result;
};
}
export default UserService;
join
은 선언한 정보만 받아오는 select
와 모든 정보를 받아오는 include
를 통하여 가능하다.
// User와 Post의 모든 정보를 받아오는 함수
public getAllUsersAndPosts = async (): Promise<any> => {
const result = await prisma.user.findMany({
include: {
Post: {
orderBy: {
module_id:"asc",
},
},
},
orderBy:{
module_id:"asc",
}
});
prisma.$disconnect()
return result
};
// User와 Post의 ID만 받아오는 함수
public getUsersIdAndPostsId = async (): Promise<any> => {
const result = await prisma.user.findMany({
select: {
user_id: true,
Post: {
select: {
post_id: true,
},
},
},
});
prisma.$disconnect()
return result
};
상당히 직관적으로 join
을 통하여 정보를 받아와 사용할 수 있어 쉽게 사용가능하다.
npx prisma studio
이 명령어를 통하여 웹 페이지를 통해 쉽게 DB에 구조를 확인하고 변경 할 수 있다.