1. Prisma의 의미
Prisma는 차세대 Node.js, TypeScript ORM 기술로서, 미리 정의한 모델인 GraphQL 스키마를 기반으로 DB의 필드, 속성을 자동생성(CREATE TABLE) 해준다. 이해하기 쉬운 데이터 모델 작성, migration 자동화 기능, type safe 및 auto-completion 기능 덕분에 데이터베이스 작업 시 편리하다.
1.1. GraphQL의 의미와 장점
facebook에서 만든 Graph Query Language 로 어플리케이션 쿼리 언어로써, 기존의 REST API의 한계점을 극복하고자 나온 통신 규약이다.
Node.js를 이용해, 데이터베이스에 접근하는 나만의 명령어를 만들고 (Query, Mutation, TypeDefs, resolvers ) CRUD 요청, 응답을 더 효과적으로 처리할 수 있게 해주는 API 이다.
장점
REST API의 다음과 같은 문제를 해결한다.
- 원하는 데이터보다 쓸데없이 더많은 데이터를 가져오는 문제(over-fetching)
- 특정 데이터를 요청하기위해 여러 번의 요청을 해야하는 문제(under-fetching)
1.2. ORM (Object Relational Mapping)의 의미와 장단점
Application단에서 모델을 생성하기만 하면, DBMS(관계형 데이터베이스)에서 CREATE TABLE할 필요 없이 모델의 필드와 속성에 맞춰 데이터베이스가 생성되어 매핑되는 것을 말한다.
장점
- Application단의 모델과 DBMS의 테이블간의 필드, 속성 불일치 문제를 해결한다.
- 모델에 기반한 코드를 작성하므로 직관적이다.
- 관계형 데이터베이스의 테이블 생성, 필드 설정 같은 작업이 생략되므로, Backend 개발자는 비즈니스 로직에 집중할 수 있다.
- Backend 내에서 데이터를 가져오는 코드를 작성하므로 재사용성, 가독성, 유지보수성, 생산성이 증가한다.
- 객체-테이블 매핑정보가 명확하여, ERD를 보는 것에 대한 의존도를 낮출 수 있다.
- 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하기 때문에 오류 발생률이 적다.
- DBMS를 교체하는 거대한 작업에도 migration 기능을 통해 비교적 적은 리스크와 시간이 소요된다.
단점
- 사용하기는 편하지만 설계는 매우 신중하게 해야한다.
- 프로젝트의 복잡성이 커질경우 난이도 또한 올라갈 수 있다.
- 잘못 구현된 경우에 속도 저하 및 심각할 경우 일관성이 무너지는 문제점이 생길 수 있다.
- 일부 자주 사용되는 대형 쿼리는 속도를 위해 SP를 쓰는등 별도의 튜닝이 필요한 경우가 있다.
- DBMS의 고유 기능을 이용하기 어렵지만 특정 DBMS의 고유기능을 이용하면 이식성이 저하되기 때문에 피하자.
- 프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다
2. Prisma 사용법
2.1. migration 파일
DB 스키마를 정의
// 가장 최근의 migration 파일을 사용
// migration 파일이 없으면 새로 만듬
npx prisma migrate dev
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// 유저 정보 테이블
model User {
id Int @default(autoincrement()) @id
emailLogin String @unique
emailAuth String @unique
password String
name String
nickname String
schoolYear String
schoolType String
sex String
region String
schoolName String
regDate DateTime @default(now())
updateDate DateTime @default(now()) @updatedAt
userEventScore UserEventScore[]
userTotalScore UserTotalScore[]
userFactorEvent UserFactorEvent[]
board Board[]
}
// 유저 종목별 점수
model UserEventScore {
id Int @default(autoincrement()) @id
user User @relation(fields: [userId], references: [id])
userId Int
factor String
event String
measure String
score Int
grade String
percentile Float
regDate DateTime @default(now())
updateDate DateTime @default(now()) @updatedAt
}
데이터베이스 수업을 들었거나, 데이터베이스를 설계해 본 사람이라면, 위 코드 대부분이 이해가 갈 것이다.
특이한 점은 FK(Foreign key)를 설정하는 방법인데,
userEventScore UserEventScore[]
user User @relation(fields: [userId], references: [id])
userId Int
이 부분인데, FK(Foreign key)를 설정할 때 기본키를 가지고 있는 UserEventScore 테이블에서는 userId와 User @relation를 추가해준다. FK 관계 테이블인 User에는 userEventScore UserEventScore[]를 추가해준다.
2.2. Request Model 정의
export interface UserRequest {
emailLogin: string;
emailAuth: string;
password: string;
name: string;
nickname: string;
schoolYear: string;
schoolType: string;
sex: string;
region: string;
schoolName: string;
}
2.3. Service 비즈니스 로직 작성
public async createUser(user: UserRequest): Promise<TokenResponse> {
try {
const res = await prisma.user.create({
data: user,
});
const token: string = await this.generateAccessToken(res.id);
return {
id: res.id,
token: token,
};
} catch (e) {
throw e;
}
}
회원가입을 하면 데이터베이스가 입력한 회원정보가 등록되는 코드가 3줄로 작성된다.
2.3. route 코드 작성
route.post('/user', async (req: Request, res: Response) => {
try {
const userRequest: UserRequest = req.body;
const tokenResponse: TokenResponse = await userService.createUser(userRequest);
res.status(200).json({
code: 200,
msg: '',
data: tokenResponse,
});
} catch (e) {
if (e instanceof Error) {
res.status(500).send({ message: e.message });
} else {
res.status(500).send({ message: 'Undefined Error!' });
}
}
});
prisma가 생성한 데이터베이스에 데이터가 잘 들어간 것을 확인할 수 있다.
Next Todo
회원가입 시 password 암호화하기 (단방향 암호화를 사용하여 복호화 불가능하게 함)
'개발 > Node.js' 카테고리의 다른 글
SQL :: 점수 합계, 등급 산정하기, PERCENTRANK, SUM (8) | 2023.01.26 |
---|---|
Node.js + bcrypt :: 회원가입 시 비밀번호 암호화하기 & 로그인 시 비밀번호 검증, 비교하기 (0) | 2022.11.09 |
Node.js + TypeScript + nodemailer :: 이메일 인증번호 보내기 (0) | 2022.11.08 |