JavaScript/JS백엔드

Prisma 기본

염두리안 2025. 1. 1. 21:55
728x90
반응형

Prisma 초기화

npx prisma init --datasource-provider postgresql

.env 파일에서windows의 경우 [postgres:password]로 변경하고, mydb를 생성할 db 이름 입력
DATABASE_URL="postgresql://postgres:password@localhost:5432/comazon?schema=public"
PORT=3000

다음과 같은 파일 생성

 

User 모델 만들기

// @id, @unique: 유니크한 값
// @default(uuid()): uuid - 36자로 이뤄진 형식
// ? : 값을 비워놔도 된다는 의미... NULL로 표시
model User {
  id        String @id
  email     String @unique
  firstName String
  lastName  String
  address   String?
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  
  @@unique([firstname, lastname]) // 조합이 유니크 해야하는 경우 @@unique 사용
}

 

마이그레이션: 모델 코드를 데이터베이스에 반영하는 것

npx prisma migrate dev

동기화 및 새로운 파일들 생성

migration.sql
-- CreateTable
CREATE TABLE "User" (
    "id" TEXT NOT NULL,
    "email" TEXT NOT NULL,
    "firstName" TEXT NOT NULL,
    "lastName" TEXT NOT NULL,
    "address" TEXT NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
DB 접속 및 확인
npx prisma studio

 

테이블에 데이터가 있을 때 마이그레이션 하기

  • model User 필드에 age Int 추가시 기존 데이터들은 값이 없어서 오류가 뜸
  • 그래서 처음 추가할 땐 옵셔널 필드로 넣은 다음에 기존 데이터 들을 채워준 후에 필수 필드로 지정해주면 됨
  • 삭제시엔 경고문만 뜨고 별로 문제가 되지 않음

Prisma Client와 DB CRUD

  • Prisma 사용하기
// app.js
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

 

// 유저 목록 조회
const users = await prisma.user.findMany();
// id에 해당하는 유저 조회
const user = await prisma.user.findUnique({
	where: { id },
});

// 리퀘스트 바디 내용으로 유저 생성
const user = await prisma.user.create({
  data: req.body,
});
  
// 리퀘스트 바디 내용으로 id에 해당하는 유저 수정
const user = await prisma.user.update({
  where: { id },
  data: req.body,
});
  
// id에 해당하는 유저 삭제
await prisma.user.delete({
  where: { id },
});

 

데이터베이스 시딩

import { USERS } from './mock.js';

const prisma = new PrismaClient();

async function main() {
  // 기존 데이터 삭제
  await prisma.user.deleteMany();

  // 목 데이터 삽입
  await prisma.user.createMany({
    data: USERS,
    skipDuplicates: true, // unique한 데이터들이 중복되면 skip
  });
}
// pacage.json에 다음 코드 추가
"prisma": {
    "seed": "node prisma/seed.js"
  }
  
  // 후에 npx prisma db seed를 입력하면 seed 데이터가 잘 들어간 것을 알 수 있음

 

쿼리 파라미터 처리하기

// app.js - app.get()을 다임과 같이 수정
app.get('/users', async (req, res) => {
  // 유저 목록 조회
  const { offset = 0, limit = 10, order = 'newest' } = req.query;
  let orderBy;
  switch (order) {
    case 'oldest':
      orderBy = { createdAt: 'asc' };
      break;
    case 'newest':
    default:
      orderBy = { createdAt: 'desc' };
  }
  const users = await prisma.user.findMany({
    orderBy,
    skip: parseInt(offset),
    take: parseInt(limit),
  });
  res.send(users);
});

 

유효성 검사

// structs.js
import * as s from 'superstruct';
import isEmail from 'is-email';

export const CreateUser = s.object({
    email: s.define('Email', isEmail),
    firstName: s.size(s.string(), 1, 30),
    lastName: s.size(s.string(), 1, 30),
    address: s.string(),
});

export const PatchUser = s.partial(CreateUser);

// app.js에서 코드 삽입
import { assert } from 'superstruct';
import { CreateUser, PatchUser } from './structs.js';

assert(req.body, CreateUser); // post
assert(req.body, PatchUser); // patch

 

오류 처리하기

function asyncHandler(handler) {
  return async function (req, res) {
    try {
      await handler(req, res);
    } catch (e) {
      // 유효성 검사 오류
      if (e.name === 'StructError' ||
        e instanceof Prisma.PrismaClientValidationError
      ) { 
        res.status(400).send({ message: e.message });
      } 
      // 요청한 리소스를 찾을 수 없을 때
      else if (
        e instanceof Prisma.PrismaClientKnownRequestError &&
        e.code === 'P2025'
      ) {
        res.sendStatus(404);
      } else {
        res.status(500).send({ message: e.message });
      }
    }
  };
}
728x90
반응형