prisma란
- Prisma: Node.js 기반의 ORM(Object-Relational Mapping) 도구로, 데이터베이스와의 상호 작용을 단순화하고 개발 생산성을 높이는 데 도움을 주는 도구
- SQL 쿼리를 직접 작성하는 대신 자바스크립트 코드로 쿼리를 작성할 수 있게 해주며, 타입 세이프한 쿼리 작성성을 통해 런타임 에러를 방지
- 타입 세이프 쿼리: 쿼리를 자바스크립트 코드로 작성함으로써 타입 에러를 사전에 방지
- 자동 마이그레이션: 데이터베이스 스키마 변화를 감지하고 자동으로 마이그레이션을 처리하여 스키마 관리를 간소화
- 강력한 문법: 복잡한 쿼리 및 데이터베이스 관계를 다루기 위한 강력한 문법 제공
Prisma 개념 (구성 요소)
- Prisma Client: Node.js & TypeScript용 쿼리 작성 클라이언트
- Prisma Migrate: 마이그레이션 시스템
- Prisma Studio: 데이터베이스의 데이터를 보고 편집하는 GUI
- 개발자가 직접 SQL문을 작성하지 않아도, 데이터베이스와 상호작용할 수 있는 ORM
- 타 ORM과는 달리, 자체적인 스키마 문법 제공하여 직접 DB 마이그레이션, 클라이언트 코드 생성 등 작업 가능
- 위에 언급한 간편한 CLI, Prisma Studio 등 편리한 GUI 도구 제공하여 생산성 향상
Prisma 기능
- Prisma Client: 데이터베이스와 상호 작업하기 위한 자바스크립트 코드를 자동으로 생성해주는 도구
- 스키마 정의: 데이터베이스 스키마를 정의하고 관리
- DB 마이그레이션: 데이터베이스 스키마 변화를 추적하고 적용할 수 있는 마이그레이션 기능 제공
- DB 관계 정의: 복잡한 데이터베이스 관계를 정의하고 쿼리 기능 제공
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
스키마
-
모델 (Model): 모델은 데이터베이스의 특정 테이블이나 컬렉션과 대응. Prisma에서 모델을 정의하면 해당 모델에 대한 데이터베이스 테이블이나 컬렉션이 생성됨
-
필드 (Field): 모델 내에서 필드는 해당 모델이 가지는 데이터 속성을 나타냄. 각 필드는 데이터 타입과 제약 조건을 가질 수 있음
-
관계 (Relation): Prisma에서 관계는 모델 간의 연관을 나타냄. 두 테이블 간의 외래 키(Foreign Key)를 관리하고 연결된 데이터를 쿼리 가능
사용법
세팅
- Prisma 설치 후, Prisma Client 인스턴스화 해야 함. 세팅은 아래 단계를 따라 적용 Prisma Schema에 generator 정의:
generator client {
provider = "prisma-client-js"
}
- prisma/client 패키지 설치 후 prisma generate 실행:
yarn add @prisma/client
prisma generate
- Prisma Client를 인스턴스화 해서 사용:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
// `prisma`를 사용하여 데이터베이스에서 데이터를 읽고 쓸 수 있습니다.
CRUD
create
- Prisma로 데이터를 생성하기 위해서는 create API 사용
const user = await prisma.user.create({
data: {
email: 'elsa@prisma.io',
name: 'Elsa Prisma',
},
});
- Prisma로 데이터를 조회하기 위해서는 findMany 또는 findUnique와 같은 메서드 사용
const users = await prisma.user.findMany({
where: {
age: {
gte: 18,
},
},
orderBy: {
name: 'asc',
},
include: {
posts: true,
},
select: {
id: true,
name: true,
},
});
where, orderBy, include, select 등의 옵션으로 쿼리 조건 설정 가능
update
하나만 수정하기 위해서는 update 메서드를 사용하고, 여러 레코드를 한 번에 업데이트하려면 updateMany 사용
const updatedUser = await prisma.user.update({
where: {
id: 1,
},
data: {
name: 'Updated Name',
},
});
delete
데이터를 삭제하기 위해서 delete 메서드 사용
const deletedUser = await prisma.user.delete({
where: {
id: 1,
},
});
하나만 삭제하기 위해서는 delete 메서드를 사용하고, 여러 레코드 삭제를 위해서는 deleteMany 사용
const deleteUsers = await prisma.user.deleteMany({
where: {
email: {
contains: 'prisma.io',
},
},
});
DB에 반영
마이그레이션
앞서 작성한 스키마를 DB에 반영하기 위해서는 마이그레이션 명령어를 작성해야 함
npx prisma migrate dev
//마이그레이션 파일에 --name 옵션을 사용하여 이름을 지정할 수 있음
npx prisma migrate dev --name init
마이그레이션 된 파일들은 prisma/migrations에 생성됨. 현재 날짜와 시간, 그리고 –name 문자열 조합으로 생성됨
prisma
└── schema.prisma
└── migrations
└── 20230331052907_init
└── migration.sql
- 해당 마이그레이션 파일은 직접 수정하면 안됨. 항상 prisma migrate 명령어를 통해서만 파일 생성 / 디비 수정이 가능함.
- 마이그레이션 명령어를 통해 생성된 파일은 Prisma가 관리하며, 수정할 경우 예상치 못한 오류가 발생할 수 있음.
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"name" TEXT,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Post" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"userId" TEXT,
CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- CreateIndex
CREATE INDEX "Post_userId_idx" ON "Post"("userId");
-- AddForeignKey
ALTER TABLE "Post" ADD CONSTRAINT "Post_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
확인
확인은
npx prisma studio
로 해주면 된다.
Seed - 초기 데이터나 테스트 데이터를 넣는 과정
Prisma.schema 모델링을 먼저 해주고 마이그레이션을 해준다.
npx prisma migrate dev --name init
그다음 아래 순서를 따른다.
- package.json에 seed 스크립트 추가 yarn add –dev ts-node 추가
"prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" }
- Prisma 폴더 내에 seed.ts 파일 생성 후, seed 코드 작성
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function seedData() {
// seed 코드 작성
}
async function main() {
await seedData();
}
main()
.catch((e) => {
console.log(e);
process.exit(1);
})
.finally(() => {
prisma.$disconnect();
});
- seed 함수
async function seedData() {
data?.['DATA']?.map(async (store) => {
const storeData = {
phone: store.tel_no,
address: store?.rdn_code_nm,
lat: store?.y_dnts,
lng: store?.x_cnts,
name: store.upso_nm,
category: store?.bizcnd_code_nm,
storeType: store?.cob_code_nm,
foodCertifyName: store?.crtfcc_gbn_nm,
};
const result = await prisma.store.create({
data: storeData
});
console.log(result);
});
}
- npx prisma로 데이터 시드 실행
npx prisma db seed
에러
npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma\schema.prisma
Datasource "db": PostgreSQL database "postgres", schema "public" at "aws-0-ap-northeast-2.pooler.supabase.com"
하… 삽질 엄청했다 여기서 더이상 진행이 안돼서. 결론은 위 url을 아래처럼 바꿔주면 된다.
DATABASE_URL="postgresql://postgres.qkkdhukxhudwdxtmphqe:비밀번호@aws-0-ap-northeast-2.pooler.supabase.com:6543/postgres"
DATABASE_URL="postgresql://postgres.qkkdhukxhudwdxtmphqe:비밀번호@aws-0-ap-northeast-2.pooler.supabase.com"