Back/Node.js

[NestJs, Prisma] Prisma CRUD

회사 내 특정 서비스들을 Nestjs + Prisma 로 바꾸고 싶었다.

 

기존 프로덕트는 모든게 생쿼리를 날리거나,

 

내가 직접 만든 orm을 사용했는데.

 

이게 처음엔 mysql이 뭔지도 모르는 초짜가 sql에 대해 학습하기 좋았지만,

 

점점 작업하면 할 수록 불편해졌다.

 

1. 내가 모든 컬럼을 외울 수도 없는 노릇

2. 모든 테이블을 혼자 만든 나도 이런데, 나말고 다른 백엔드 개발자가 보면 더 적응하기 힘들거라 생각

 

TypeORM과 Prisma중에 선택을 해야 했는데,

 

Prisma를 선택했다. 추후 GraphQL을 사용할 건데, Prisma가 더 적합해 보였다.

 

단점은 AWS RDS Aurora에서 읽기 전용 DB를 지원하지 않는 다는 거였는데..

 

(prisma에 미들웨어처럼 넣어서 어거지로 할 수 있긴하다.)

 

 

npx prisma init

generator client {
  provider = "prisma-client-js"
}

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

요런 파일이 만들어진다.

 

.env파일을 변경해준다.

DATABASE_URL="mysql://유저이름:비밀번호@디비주소:3306/스키마이름(디비이름)?schema=public"

 

여기서 처음부터 prisma로 db 모델을 만든게 아니라, 기존 db를 받아 오고 싶었는데,

 

npx prisma db pull

 

하면 된다.

 

(여기서 db가 변경 컬럼등이 변경되서 다시 동기화시키고 싶으면 npx prisma generate 하면된다)

 

그럼 

 

schema.prisma에 db에 있는 컬럼들을 자동으로 model들이 생성된다.

model title {
  idx       Int       @id
  title String?   @default("0") @db.VarChar(200)
  created_at         DateTime? @default(now()) @db.DateTime(0)
  updated_at         DateTime? @default(now()) @db.DateTime(0)
  test               String?   @db.VarChar(200)
}

 

 

src/prisma.service.ts

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

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }

  async enableShutdownHooks(app: INestApplication) {
    this.$on('beforeExit', async () => {
      await app.close();
    });
  }
}

 

prisma를 연결해주는 서비스를 만들어주고,

 

사용할 곳에서 import해서 쓰면 되겠다.

 

 

service.ts

import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma.service';
import { title } from '@prisma/client';

@Injectable()
export class TodoService {
  constructor(private prismaService: PrismaService) {}

  async fetchAllTodos(): Promise<title[]> {
    return this.prismaService.title.findMany();
  }

  async fetchTodoItem(memberIdx: number): Promise<title | null | object> {
    return this.prismaService.title.findUnique({
      where: { idx: Number(memberIdx) },
    });
  }

  async deleteTodoItem(memberIdx: number): Promise<object | null> {
    return this.prismaService.title.delete({
      where: { idx: Number(memberIdx) },
    });
  }

  async addTodoItem(data: title): Promise<object> {
    return this.prismaService.title.create({
      data: data,
    });
  }

  async updateTodoItem(memberIdx: number, memberName: string): Promise<object | null> {
    await this.prismaService.title.update({
      where: { idx: memberIdx },
      data: { title: memberName },
    });
    return { msg: 'success' };
  }
}

CRUD 예제

 

@prisma/client에서 정의된 model title은 타입이 자동으로 만들어진다.

db에 변경이 있어서 npx prisma pull 하고 나서, 저 부분의 타입이 바뀌지 않는다면

 npx prisma generate 해줘야 한다.