[Next.js] Next.js에서 Prisma 세팅하기

해달·2023년 8월 10일
0

사이드프로젝트로 개발 중에 DB서버 따로 띄우지말고 next.js api를 사용하자는 의견이 나와
어떤것으로 하면 좋을지 찾아보다가 사용할 수 있는 옵션 중에 prisma를 사용하기로 결정했다.

어떤게 좋을지 세팅방법이랑 사용방법을 간단하게 보면서 왜 프리즈마를 선택했고,
어떻게 세팅했는지 정리하려고한다!
NEXT API사용도 처음이였어서 꽤나 오랜시간이 걸렸다..🥲


Next.js API 사용 시 고려했던 ORM, db 옵션

ORM(Object-Relational Maaping) 이란?

SQL query를 사용하지 않고 직관적인 코드(create, find)와 같은 메서드로 데이터를 조작할 수 있도록 도와주는 것

ORM을 구성하는 3가지

(1) 스키마 오브젝트 / 모델 객체

create table User(
 ...,
)

(2) 쿼리 빌더

select id,name from user where id = 123;

(3) 마이그레이션 툴

DB 스키마 변경사항을 기록하고 관리하기 위한 마이그레이션 툴

  • ex) 20230814.... // file

🤖 ORM 장점과 단점 (chat GPT)

  • ORM의 장점
    • 추상화: ORM은 개발자에게 데이터베이스 조작을 객체와 메서드로 다룰 수 있도록 추상화해줍니다. 이로써 개발자는 SQL 쿼리 작성에 대한 부담을 덜 수 있습니다.
    • 데이터베이스 독립성: ORM은 다양한 데이터베이스 시스템을 지원하며, 코드 변경 없이 다른 데이터베이스로 전환하기 용이합니다.
    • 데이터베이스 스키마 관리: ORM은 데이터베이스 스키마를 코드 기반으로 관리하므로 스키마 변경에 따른 번거로움을 줄일 수 있습니다.

  • ORM의 단점:
    • 성능 이슈: ORM은 객체와 SQL 간의 변환을 수행하며, 이로 인해 일부 상황에서 성능이 저하될 수 있습니다. 특히 복잡한 쿼리나 대량 데이터 조작 시에 이슈가 발생할 수 있습니다.
    • 학습 곡선: ORM은 사용법을 익히는 데 시간이 걸릴 수 있습니다. 특히 복잡한 기능을 활용하려면 더 많은 학습이 필요할 수 있습니다.
    • 제한된 기능: 일부 고급 데이터베이스 기능이 ORM으로 완벽하게 처리되지 않을 수 있습니다. 이런 경우 원시 SQL을 직접 작성해야 할 수도 있습니다.

따라서 ORM을 선택할 때는 프로젝트의 규모, 복잡성, 성능 요구 사항 등을 고려하여 적절한 도구를 선택하는 것이 중요합니다. 쿼리의 효율성에 대한 우려가 있다면, ORM을 사용하기 전에 해당 ORM의 성능 특성을 조사하고 테스트하는 것이 좋습니다.


✅ 고려한 옵션

(1) mysql

SQL query를 작성해서 DB와 상호작용
간단한 프로젝트에서 사용하기 좋은 방식이라고 생각된다.

지금 진행중인 프로젝트는 현재는 가볍지만 추후에 고려해놓은 기능까지 생각하면 SQL말고 ORM을 쓰는것이 더 편리할거 같다고 생각돼서 옵션에서 뺐다

  • 장점
    작고 간단한 프로젝트에 적합
    간단한 데이터베이스 작업에 대한 좋은 성능
    원하는 방식대로 쿼리를 작성할 수 있기 때문에 쿼리의 효율성 제어 가능r
  • 단점
    데이터 관계가 복잡한 대규모 프로젝트에는 적합하지 않을 수 있음.

(2) typeorm (ORM)

typeorm 은 이전에 현업에서 API를 만들일이 있어서 사용해보았을 때 굉장히 편리하고 DB스키마 같은것들이 굉장히 직관적으로 보여서 제일 고민했던 옵션중에 하나였다.

Users 테이블의 스키마를 작성했을 경우 아래와 같이 typeORM 형식에 맞추어 Entity가 생성된다.

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

enum Gender {
  Male = 'male',
  Female = 'female',
}

@Entity('users')
export class User {
  @PrimaryGeneratedColumn()
  id: number;
 
  @Column({ type: 'varchar', length: 20 })
  phone_number: string;
 

  @Column({ type: 'enum', enum: Gender })
  gender: Gender;
 
}

사용해본 경험이 있기때문에 제일 많이 고려한 옵션이였지만
next.js 13에서 typeorm을 세팅하다가 시간을 좀 오래 잡아먹기도 했고
공식문서에 nextjs에 대한 가이드를 따로 제공할 계획이 없다는 내용을 찾기도했다.

공식문서에서 지원해 주지 않다는다는 글이 있어서 나중에 에러와 마주했을 때 디버깅이 쉽지 않을것으로 판단되어 옵션에서 빠지게 되었다

TpyeORM next.js docs 관련 이슈?
검색하다가 찾은 이슈인데 사람들이 얘기하는게 웃겨서 가져왔다
22년 4월에 달린 답글로는 Docs를 추가할 계획이 없다고 나와있고 다른 개발자들은 프리즈마로 갈아탔다는 내용들도 남겨져있다


nextjs + typeorm 세팅 벨로그 글



  • 장점
    매우 다양한 DB지원
  • 단점
    복잡한 설정인 경우 학습 곡선이 상대적으로 높을 수 있음
    Next.js와의 통합은 공식 문서가 다루지 않을 수 있어 추가적인 노력이 필요할 수 있음.

(3) ⭐️prisma (ORM)

결국 최종적으로 선택하게 된 Prisma !
제일 큰 이유는 아무래도 주위에서 사용하는 사람이 많고 공식문서도 친절하게 되어있어서(큰 커뮤니티)
필요한 내용들을 빨리 찾아볼 수 있다는 점이 우선으로 작용한거같다.
많은 시간을 쏟을 수 없으므로 빠르고 쉽게 적용해야 할 ORM이 필요했기 때문!

그 외에도 장점들과 단점들을 찾아보며 정리해보았다.

  • 장점
    타입 안전한 쿼리 작성 및 자동 완성 지원
    쿼리 최적화로 성능 개선
    마이그레이션 관리 용이
  • 단점
    학습 곡선이 상대적으로 높을 수 있음

그 외에도 각 ORM마다 성능에 관한 장점과 단점이 있으니
프로젝트가 커지거나 복잡한 경우 여러가지 조건들을 고려하여 선호도에 맞춰 사용하면 되겠다


세팅

//설치
yarn add -D prisma
yarn add @prisma/client

//설치 후 
npx prisma init

// => prisma 폴더 및 파일 생성 완료

./prisma/schema.prisma

아래와 같이 초기 파일과 .env 파일이 생성된다.

사용하는 DB타입에 맞추어 내용들을 수정해주면 된다.

// 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 = "postgresql"
  url      = env("DATABASE_URL")
}

수정_schema.prisma

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

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

datasource db option 중 relationMode ?

"prisma": 이 설정은 Prisma 모델과 데이터베이스 스키마 간의 관계를 Prisma Client가 이해하는 형식으로 가져옵니다. 이 모드에서는 관계를 더욱 정교하게 제어할 수 있습니다. 예를 들어, @relation 데코레이터를 사용하여 관계의 이름이나 참조 필드 등을 정의할 수 있습니다.

DB에 이미 생성해놓은 Table들이 있어서 스키마 파일과 싱크를 맞춰주어야 했다.
npx prisma db pull 명령어를 사용하면 스키마가 자동으로 생성되는걸 확인할 수 있는데, 아래와 같은 에러를 마주했다.

에러

✖ Introspecting based on datasource defined in prisma/schema.prisma

Error: Error querying the database: Unknown authentication plugin `sha256_password'.

위 에러는 .env 파일에 DB_URL 설정을 잘못해놔서 발생한 오류였다.

아래 Docs에 들어가보면

CONNECTOR://USER:PASSWORD@HOST:PORT/DATABASE
형태와 같이 작성하라고 나와있었는데 USER:PASSWORD 구문을 생략하고 DB_URL을 넣어서 발생했던 오류였다.. 😅
url 수정후에 명렁어를 다시 수행하면 스키마파일이 수정된다!

만약 직접 스키마 파일을 수정한다면
npx prisma db push 명령어를 사용하면 된다

  • 그 외 명령어
    npx prisma generate : prisma/schema.prisma 파일에서 정의된 generator와 데이터 모델을 기반으로 Prisma Client와 같은 에셋을 생성
    npx prisma studio : prisma GUI
    npx prisma validate : 스미카 유효성 검사

lib/prisma.ts 생성

https://github.com/prisma/prisma-examples/blob/latest/typescript/rest-nextjs-api-routes-auth/lib/prisma.ts

공식문서에서 안내해주는 prisma.ts 파일 생성

import { PrismaClient } from '@prisma/client'

// PrismaClient is attached to the `global` object in development to prevent
// exhausting your database connection limit.
//
// Learn more:
// https://pris.ly/d/help/next-js-best-practices

const globalForPrisma = global as unknown as { prisma: PrismaClient }

export const prisma = globalForPrisma.prisma || new PrismaClient()

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

export default prisma

조건에 맞는 db data 가져오기 (findmany)

처음에 findUnique 메서드를 이용해서 데이터를 가져오려 했더니
findUnique 명령어는 기본키를 포함한 where 조건이 필요해서 ex)id 값을 같이 전달해줘야 한다.

필수키 없이 조건에 맞는 데이터를 가져오려면 findMany 명령어를 사용해야 한다.

Prisma의 findUnique 메서드는 해당 테이블의 기본 키 (일반적으로 id 필드)를 사용하여 레코드를 찾습니다.
따라서 findUnique를 사용하려면 해당 테이블의 기본 키를 포함한 where 조건이 필요합니다.


실제로 세팅하면서 며칠에 거쳐 부분부분 작성한 글이라 글 내용이 조금 뒤죽박죽이다..!
prisma의 스키마에서 relation을 정의하는 방법도 다르고 typeORM과 prisma와 비교한 공식문서가 있는데 이 부분은 아직 확인해보지는 못했다.


그 외 reference

0개의 댓글