Back/Node.js

[NestJs] Prisma2 셋팅

다음 프로젝트의 DB와 연결하는 것은 쿼리를 직접 날리는 것 말고, orm을 사용하기로 했다.
후보는 Type+ORM과 Prisma이 있었고, 레퍼런스가 많고, 어느정도 대중화가 된 TypeORM을 이용하려고 했으나,

GraphQL에 더 적합한 Prisma로 전환했다.

Prisma는 기존 ORM과 근본적으로 다르며 새로운 종류의 ORM이라고 공식 문서에서 소개하고 있다.

 

Is Prisma an ORM? | What is an ORM?

Learn about how Prisma implements the Data Mapper ORM pattern and how it achieves the same goal as traditional ORMs without requiring you to map classes to tables as traditional ORMs do.

www.prisma.io

기존 ORM은 테이블을 모델 클레스에 맵핑하여 RDBMS에 작업하기 위한 객체 지향 방식을 제공하나, 'The Object-Relational Impedance Mismatch'이란 문제가 있다.

객체 모델을 관계형 모델에 저장할 때 생기는 패러다임의 불일치에서 오는 문제를 말하는데 이 문제를 Prisma는 해결했다고 한다.

 

Prisma를 사용하면 데이터베이스 스키마와 프로그래밍 언어 모델에 대해서 Prisma 스키마에서 모델을 직접 정의할 수 있다.
Prisma는 개발자가 데이터베이스 작업을 쉽게하고 도구를 제공하는 차세대 ORM이다.

  • Prisma Client : 애플리케이션에서 사용하기 위해 자동 생성되고 유형이 안전한 데이터베이스 클라이언트
  • Prisma Migrate : 선언적 데이터 모델링 및 마이그레이션 도구
  • Prisma Studio : 데이터베이스의 데이터를 검색하고 관리하기 위한 최신 GUI

NestJS에 셋팅

npm install prisma --save-dev
npx prisma init

npm install @prisma/client

@prisma/cli는 설치 안해도된다. prisma가 그 역할을 한다.
npx prisma init을 하면 루트디렉토리에 prisma 폴더가 생성된다.

schema.prisma에 모델을 작업해준다. (삼각형이 예쁘다)

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model Post {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  titlegood String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

model Profile {
  id     Int     @id @default(autoincrement())
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  name    String?
  posts   Post[]
  profile Profile?
}

환경변수에 있는 DATABASE_URL은 쓰고 있는 DB에 맞게 설정해주면된다.
나는 mysql을 사용했다.

mysql://유저이름:비밀번호@호스트:3306/스키마이름

 

스키마를 작성하고 난 뒤에,

npx prisma migrate dev

prisma cli를 입력하면, migrations폴더가 생기고, 쿼리를 확인할 수 있다.
DB에 들어가면 DB에 테이블들이 잘 생성되있다.

 

prisma.module.ts 작성

import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';

@Module({
  providers: [PrismaService],
  exports: [PrismaService]
})
export class PrismaModule {}

 

prisma.service.ts 작성

import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient
  implements OnModuleInit, OnModuleDestroy {
  constructor() {
    super();
  }

  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}

onModuleInit은 호스트 모듈이 초기화되면 호출한다. 이 때 db를 연결하고,
onModuleDestory는 Nest가 호스트 모듈을 파괴하기 직전에 정리한다. 이 때 db의 연결을 끊는다.

 

 

controller에서 사용 예시

import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
import { PrismaService } from './prisma/prisma.service';
import { CreateUserDto } from './create-user.dto';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly prisma: PrismaService
  ) {}

  @Get('users')
  async users() {
    return await this.prisma.user.findMany();
  }

}

users 정보를 다 얻어간다.
prsimaService를 사용하기전에 당연히 사용하는 곳의 모듈에서 imports와 providers 배열에 넣어주고 사용해야한다!

 

 

실험한다고 이렇게 불렀지만 나중엔 service에서 prisma를 임포트해와서 사용하면 되겠다.

지금 그래프큐엘과 프리스마를 같이 연동해서 사용해보는데, 굉장히 편하다..

레퍼런스가 없고, 아직 나온지 얼마 안되서 불안하긴 하지만 사용법을 익히고 나니 편리하다.