ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Prisma - 🐠시작하기 환경설정, 쿼리 로깅, CRUD
    FrameWork/ORM 2024. 4. 12. 10:52

    Prisma 설정하기

     

    [Quickstart]

    https://www.prisma.io/docs/getting-started/quickstart

     

    Quickstart with TypeScript & SQLite | Prisma Documentation

    Get started with Prisma ORM in 5 minutes. You will learn how to send queries to a SQLite database in a plain TypeScript script using Prisma Client.

    www.prisma.io

     

    nodeJs-express 서버에서 prisma 사용하기

    prisma 의존성 설치

    yarn add prisma --dev

     

     

    prisma init

    npx prisma init

     

    이후 생성되는 파일과 폴더


    Prisama로 DB와 연결하고 마이그레이션

    prisma/schema.prisma 파일에 정의된 스키마

    // This is your Prisma schema file,
    // learn more about it in the docs: https://pris.ly/d/prisma-schema
    
    // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
    // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
    
    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "mysql"
      url      = env("DATABASE_URL")
    }
    
    enum ArticleState{
      DRAFT
      PUBLISHED 
    }
    
    model Article{
      id Int @id @default(autoincrement())
      title String
      content String
      state ArticleState
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
    }

     

    마이그레이션 명령어

    dotenv -e .env.local -- npx prisma migrate dev

     

    로컬에서 이러한 마이그레인셔을 실행할려고 하면 위 명령어를 사용하는 것이 좋다. 왜냐하면 이 명령어는 shadow 데이터베이스를 생성하고 그것에서 모든 마이그레이션을 실행하려고 시도한다. 이때 뭔가 실패하면 오류 메시지가 표시된다. 그리고 모든 것이 성공적으로 작동한다면 실제환경에서 마이그레이션이 실행된다. 하지만 해당 명령은 프로덕션 환경에서는 권장 되지 않으므로 proudct서버에서는 사용하지 않는 것이 좋다. 

     

    즉 위 명령어는 개발 중에 오류를 파악하기 위한 개발 중에 사용하기 적절한 명령어이다. 

    Enter a name for the new migration > CreateArticlesTable
    // 마이그레이션 이름을 묻는다.

     

    그러고 나면 테이터과 스키마가 동기화 되었다는 뜻의 콘솔이 출력된다. 


    마이그레이션을 사용하는 이유

    Article 테이블 명을 → articles로 마이그레이션하기 

    schema.prisma

    model Article{
      id Int @id @default(autoincrement())
      title String
      content String
      state ArticleState
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
      @@map("articles")
    }

     

    마이그레이션 명령어

    dotenv -e .env.local -- npx prisma migrate dev

     

     

    마이그레이션으로 추적 가능해진 테이블의 변화

     

    /*
      Warnings:
    
      - You are about to drop the `Article` table. 
      If the table is not empty, all the data it contains will be lost.
    
    */
    -- DropTable
    DROP TABLE `Article`;
    
    -- CreateTable
    CREATE TABLE `articles` (
        `id` INTEGER NOT NULL AUTO_INCREMENT,
        `title` VARCHAR(191) NOT NULL,
        `content` VARCHAR(191) NOT NULL,
        `state` ENUM('DRAFT', 'PUBLISHED') NOT NULL,
        `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
        `updatedAt` DATETIME(3) NOT NULL,
    
        PRIMARY KEY (`id`)
    ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

     

    prisma 폴더 하위를 살펴보면 그동안 npx prisma migrate dev 명령어를 사용해서 생성된 쿼리를이 저장되어 있는 것을 확인할수 있다. Article 테이블을 articles 테이블로 이름을 수정할 때 생성된 쿼리도 확인할 수 있다. 

     

    마이그레이션을 사용하면 테이블에 대한 변경사항도 git을 통해 추적할 수 있다. 그래서 테이블의 칼럼을 추가하거나 Type의 변경 데이터베이스 구조와 관련된 모든 변경 사항은 마이그레이션을 통해 수행되면 체계적으로 관리할 수 있다. 협업을 하는 경우 데이터베이스를 모든 팀과 동기화 하는 것에도 도움이 된다. 


    Prisma를 사용하는 CRUD 

    Prisma 클라이언트 인스턴스화 

     

    Prisma 클라이언트 설치

    yarn add @prisma/client

     

    위 모듈이 설치되면 Prisma는 클라이언트를 인스턴스화 하게된다. 프리즈마 클라이언트는 DB와 상호작용하면서 prisma가 수행해야하는 모든 쿼리를 만들고 수행한다. 

     

     

    Prisma 클라이언트 인스턴스 생성 

    import express from "express"
    import * as dotenv from 'dotenv'
    process.env.NODE_ENV == 'prod'?
                    dotenv.config({path:'./.env.prod'})
                    : dotenv.config({path:'./.env.local'});
    
    import bodyParser from "body-parser";
    import { PrismaClient } from "@prisma/client"
    
    const app = express()
    
    const prisma = new PrismaClient()
    
    app.use(bodyParser.json())

     

    article 데이터 생성 

     

    코드에 prisma. 만 입력해도 자동완성 추천 항목에 article이 제안되는 것을 확인할 수 있다. 

     


    Prisma를 이용한 create 코드

    하나의 articles 생성하기

    app.post('/articles', async (req, res) =>{
        await prisma.article.create({
            data : req.body 
        });
        res.json({success:true});
    });

     

     

    여러개의 articles 동시에 생성하기

    app.post('/multiple-articles', async (req, res) =>{
        await prisma.article.createMany({
            data: req.body
        });
    });

     


     

    Prisma 쿼리 로깅하기 

    ORM이라는 이름에서 알수 있듯이 ORM을 사용하면 로우 SQL을 작성하는 것 대신 객체의 상호작용으로 이것을 다루면 훨씨 간단하고 단순해진다.

     

    로깅 설정

    const prisma = new PrismaClient({
        log:["query"]
    })

     

    ORM을 통한 메서드가 생성하는 SQL을 검증하려는 경우 new PrismaClient()를 사용해 Prisma 클라이언트를 인스턴스화 한 것을 활용하면 된다. 이 인스턴스를 생성시 몇가지 설정사항을 전달할 수 있다. 

     

    로깅 내용 

     

    위 설정 사항을 설정하고 나서 post './articles'를 실행하면 해당 해당 메소드가 작동하면서 실행된 쿼리가 기록된다. 따라서 prisma ORM 이 제공하는 메소드를 사용하면서 실제 실행된 쿼리를 제대로 추적하고 디버깅할 수 있게된다.

     

    Prisma를 이용한 article 검색

    모든 article 검색

    app.get('/articles', async(req,res) =>{
        //1.모든 기사 검색하기 
        const articles = await prisma.article.findMany();
        res.json(articles);
    })

     

    findMnay()는 where절 없이도 많은 작업을 수행할 수 있다. 즉 모든 article이 검색되고 반환된다. 

     

    특정 article 하나만 검색

    app.get('/articles/:id', async(req,res) =>{
        //2.특정 기사 하나 검색 
        const article = await prisma.article.findFirst({
            where: {
                id: +req.params.id
            }
        })
    
        res.json(article);
    })

     

    여기서는 findFirst()메서드를 사용한다.  해당 메서드의 조건에 넣는ID와 일치하는 첫번째 레코드를 가져온다.

     

    특정 조건에 부합하는 article 검색

    app.get('/articles', async(req,res) =>{
        //3.특정 조건에 부합하는 기사들 검색
        //(fetch all article in draft state)
        const articles = await prisma.article.findMany({
            where:{
                state:req.query.state
            }
        });
    
        res.json(articles);
    });

     

     


    Prisma를 이용한 update 코드

    updateMany 메소드

    app.put('/articles/:ids', async(req, res) =>{
    const idList = req.params.ids.split(',').map(id => +id);
    const updatedCount = await prisma.article.updateMany({
       where:{
           id:{
               in : idList
           }
       },
       data:{
           title: req.body.title
       }
    });
        res.json(updatedCount);
    });

     

    위 코드에서 updateMany의 결과로 반환되는것은 update결과가 아니라 update된 레코드의 숫자이다. 

     

    upsert메소드

    upsert()메소드가 updateMany()메소드와 다른점은 데이터베이스에 해당 조건의 레코드가 있으면 해당 레코드를 update하고 없을 경우는 새로 생성하는 것이다. 

     


    Prisma를 이용한 delete 코드

    특정 article 삭제

    app.delete('/articles/:id', async (req,res) =>{
        const deleted = await prisma.article.delete({
            where:{
                id: +req.params.id
            }
        });
    
        res.json(deleted);
    })

     

     

    모든 article 삭제

    //await prisma.article.deleteMany({});

     

    where절로 별다른 조건을 지정하지 않고 deleteMany()를 실행하면 테이블의 모든 레코드가 삭제되므로 사용할때는 주의를 기울인다. 

     

     

    [출처 - Building Production-Ready Apps with Prisma Client for NodeJS, Naimish Verma]

    https://www.udemy.com/course/building-production-ready-apps-with-prisma-client-for-nodejs/?couponCode=KEEPLEARNING

     

    댓글

Designed by Tistory.