-
[ORM] Prisma Schema 작성하여 DB 세팅하기 (with. NextJS)프레임워크/NodeJs 2024. 8. 7. 23:42
ORM
Object Relational Mapping
객체 관계 매핑은 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법이다.
객체 관계 매핑 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 객체 관계 매핑(Object-relational mapping; ORM)은 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법이다. 객체 지향
ko.wikipedia.org
해당 글은 개인 프로젝트를 만들면서 공부하고 적용한 내용을 작성한 글입니다.
그러므로 Prisma의 Schema 모든 기능이 작성되어 있지 않습니다.
모든 기능에 대한 내용은 아래 공식문서 링크에서 확인해 주세요.
https://www.prisma.io/docs/orm/overview/introduction/what-is-prisma
What is Prisma ORM? (Overview) | Prisma Documentation
This page gives a high-level overview of what Prisma ORM is and how it works. It's a great starting point for Prisma newcomers!
www.prisma.io
본격적으로 NextJS 프로젝트를 생성하고, Prisma로 Database 연결과 DB Schema를 작성하여 테이블을 생성해보자.
NextJS 프로젝트를 생성한다.
$ npx create-next-app@latest
개인적으로 풀스택 개발할 일이 생겨 React가 주력이기에 선택한 프레임 워크
Prisma와 Prisma Client 를 설치한다.
$ npm install prisma --save-dev $ npm install @prisma/client
생성된 폴더의 root 위치에 prisma 디렉토리를 생성하고, schema.prisma 파일을 생성한다.
/prisma schema.prisma /public /src package.json
package.json에 prisma라는 실행 script를 추가한다.
{ "name": "my-account-app", "version": "0.1.0", "private": true, // ... "scripts": { // ... "prisma": "prisma generate --schema=./prisma/schema.prisma" }, // ... }
/prisma/schema.prisma 파일에 우선 database를 연결해주는 스크립트를 작성한다.
이 프로젝트는 mariadb를 사용하였기에 mysql로 연결해줄 것이다.
generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") }
datasource db의 url은 아래와 같이 작성했다.
mysql://USER:PASSWORD@HOST:PORT/DATABASE
다음은 DataBase Model 작성. 테이블을 만들고 관계를 지어준다.
나는 카테고리를 코드로 만들어 사용할 것이기 떄문에, 코드 테이블과 코드들의 트리 관계를 지어줄 테이블을 만들어주었는데,
이 때 트리구조 DB 설계 방식은 클로저 테이블 방식을 택했고, 아래와 같이 스키마를 작성했다.model code { identifies String @id @db.VarChar(10) label String? @db.VarChar(20) ancenstor codeRelation[] @relation("ancenstorToCodeRelation") descendant codeRelation[] @relation("descendantToCodeRelation") } model codeRelation { id Int @id @default(autoincrement()) ancenstor code @relation("ancenstorToCodeRelation", fields: [ancenstorId], references: [identifies], onDelete: Restrict, onUpdate: Cascade) ancenstorId String @db.VarChar(10) descendant code @relation("descendantToCodeRelation", fields: [descendantId], references: [identifies], onDelete: Restrict, onUpdate: Cascade) descendantId String @db.VarChar(10) depth Int @default(0) }
1. @id는 인덱스 컬럼
추후, 인덱스 컬럼을 여러개 사용하는 경우 @@id라는 multiple id 기능이 있으니 참고하기
2. 문자열 타입은 String
String은 varchar(191) 을 뜻하는데, 이 때 max length를 다르게 지정하고 싶은 경우 @db.VarChar(10)으로 지정 가능
↓ prisma에서는 String이 기본으로 varchar(191)를 사용하는 이유가 뭘까?에 대한 궁금증을 해결해준 글
[DB] VARCHAR(191) vs VARCHAR(255)
최근 프로젝트를 진행하며 ERD를 설계하는 것에 어려움을 느끼고 있습니다.ERD를 설계해본 경험도, 아직 데이터베이스에 대한 지식이 없어서 학습하며 궁금한 내용을 정리합니다.멘토어님에게 ER
velog.io
3. String?
optional 컬럼
4. @default(0)
기본값을 0으로 지정
5. Foreign Key 설정 - 테이블 관계 만들기
model code { identifies String @id @db.VarChar(10) label String? @db.VarChar(20) ancenstor codeRelation[] @relation("ancenstorToCodeRelation") descendant codeRelation[] @relation("descendantToCodeRelation") } model codeRelation { //... ancenstor code @relation("ancenstorToCodeRelation", fields: [ancenstorId], references: [identifies], onDelete: Restrict, onUpdate: Cascade) ancenstorId String @db.VarChar(10) //... }
여기서는 데이터가 1:N 구조를 취하고 있기 때문에 1:N 구조의 관계를 맺을 것이다.
여기서 1:N이란 code 하나가 codeRelation의 한 컬럼에 여러개 들어간다는 뜻이다.
중요하게 볼 내용은
code 테이블
ancenstor codeRelation[] @relation("ancenstorToCodeRelation")
codeRelation 테이블
ancenstorId String @db.VarChar(10)
ancenstor code @relation("ancenstorToCodeRelation", fields: [ancenstorId], references: [identifies], onDelete: Restrict, onUpdate: Cascade)
codeRelation의 ancenstor은 트리구조에서의 부모 code이다.
Prisma에서 FK를 엮기 위해서는 세가지 조치를 취해야 한다.
1) join해서 가져올 테이블에 해당 index를 사용할 테이블 컬럼을 추가
model code { ancenstor codeRelation[] @relation("ancenstorToCodeRelation") }
- ancenstor라는 이름은 다른 이름으로 변경이 가능. 꼭 컬럼명이 같을 필요는 없음
- codeRelation은 테이블 명으로, join할 테이블명을 작성
- codeRelation[]인 이유는 1:N으로 codeRelation테이블의 ancenstor컬럼에서 코드를 중복해서 참조하기 때문
- 기본적으로는 ancenstor codeRelation[]이라고 작성만 해도 FK는 생성
- 그러나 codeRelation테이블에서 code 테이블의 id를 두 컬럼에서 참조하고 있기 때문에 에러가 발생
- 에러를 확인해 보니, 명확한 이름으로 FK를 생성해야 한다는 내용이였고, @relation("ancenstorToCodeRelation")를 작성하여 FK를 생성
2) index키를 가져다 쓸 테이블에서 id 데이터를 입력할 컬럼을 추가
model codeRelation { ancenstorId String @db.VarChar(10) }
- code의 identifies를 참조할 것이기 떄문에 같은 데이터 타입을 작성
3) index키를 가져다 쓸 테이블에서 FK 설정
model codeRelation { ancenstor code @relation("ancenstorToCodeRelation", fields: [ancenstorId], references: [identifies], onDelete: Restrict, onUpdate: Cascade) }
- @relation을 설정해준다.
- 1번에서 작성한 relation이름 "ancenstorToCodeRelation" 사용
- fields에는 2번에서 작성한 인덱스 데이터를 삽입할 컬럼
- references에는 code 테이블의 인덱스 컬럼(identifies) : SQL문으로 따지면 fields와 on을 작성해주는 것과 동일
- relation mode의 옵션 입력 ()
- onDelete와 onUpdate를 입력
- onDelete: Restrict (code가 delete되면 순서가 깨지기 때문에 restrict 제약을 설정)
- onUpdate: Cascade (code identifies는 변경이 가능하다. 그렇기에 함께 변경해주어 join시 문제가 발생하지 않도록 해야함)
- 지원하는 relation mode 참고
- onDelete와 onUpdate를 입력
DB schema를 다 작성했으면, 아래 명령어를 실행하여 Database에 테이블을 생성해주자
$ npx prisma db push
Database에 접속해 테이블 생성을 확인해니 정상적으로 생성 완료!
이 후, 초반에 package.json에 설정한 prisma script를 실행하자.
$ npm run prisma
이 명령어를 실행하면, Prisma Client를 최신 상태로 변경해준다. API 개발 시 필요한 내용이다.
그럼 이 다음은 Prisma의 기능들을 사용해 API를 만들일 만 남았다!
'프레임워크 > NodeJs' 카테고리의 다른 글
[NodeJs] localhost가 실행되었는데 127.0.0.1 에 접속되지 않는 경우 (0) 2022.11.05 [NodeJs] Exit status 3221225477 발생. 및 해결 (0) 2022.10.08 [NodeJs] 채팅 서버 만들어서 실행하기 (0) 2022.05.29 [NodeJs] tosource - console창에 [Function]이 출력 될 때 사용하는 라이브러리 (0) 2021.03.06 [NodeJs] puppeteer - EPERM error 발생 (0) 2021.02.21