나만의 작은 도서관

[TIL] 240527 캠프 43일차: 유효성 검사 Joi패키지, 정규식, Prisma Client DB 2개 연결 본문

Today I Learn

[TIL] 240527 캠프 43일차: 유효성 검사 Joi패키지, 정규식, Prisma Client DB 2개 연결

pledge24 2024. 5. 27. 21:41

오늘 배운 내용                                     

요청 헤더에 속성을 추가하면 다음 미들웨어에서 해당 속성을 사용할 수 있다.

express를 사용하다보면 미들웨어가 줄줄이 연결되어 있는 경우가 자주 있는데, 이 때 이전 미들웨어에서 계산한 결과값을 다음 미들웨어가 사용하고 싶은 경우가 발생하기도 한다. 이럴 때 이전 미들웨어에서 요청의 헤더 속성으로 지정해 저장을 하게 되면 다음 미들웨어부터 해당 속성으로 값에 접근이 가능하다.

// 인증 미들웨어(auth)
export default async function (req, res, next) {
 
 	// 토큰이 유효한지 테스트
	.
    .
    .

    // 토큰이 유효하다면, req.account에 사용자 정보를 저장합니다.
    req.account = account;

    next();
 }
 
 // 캐릭터 삭제(DELETE Method) API : 인증 미들웨어 사용
router.delete("/characters/:characterId", auth, async (req, res) => {
  .
  .
  .

    // 캐릭터가 존재하지 않거나, 본인 캐릭터가 아닌 캐릭터를 삭제하려는 경우,
    // 해당 사실을 클라이언트에 전달합니다.
    if (!character) {
      return res
        .status(404)
        .json({ errorMessage: "존재하지 않는 캐릭터입니다." });
    } else if (character.accountId !== req.account.accountId) {
      return res
        .status(403)
        .json({
          errorMessage: "본인 캐릭터가 아닌 캐릭터는 삭제 할 수 없습니다.",
        });
    }

   .
   .
   .
});

정규식 사용법

정규식을 사용하면 짧은 코드로 유효성 검사를 할 수 있다. 하지만 모르고 보면 어려워보이기만 하고 이해가 되지 않아 한 번 알아보았다. 

// 예시(이메일 주소 패턴)
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

// ^: 문자열의 시작, $: 문자열의 끝을 의미
// [a-zA-Z0-9._%+-]: a~z, A~Z, 0~9, 그리고 특수문자('.', '_', '%', '+', '-' 총 다섯 개)사용가능
// +: 한 개 이상 반복가능
// [a-zA-Z0-9.-]: a~z, A~Z, 0~9, 그리고 특수문자 '-' 사용가능
// +: 한 개 이상 반복가능
// [a-zA-Z]: a~z, A~Z 사용가능
// {2,} : 최소 길이 2개, 최대 길이 제한없음

 

유효성 검증 패키지 Joi 사용법

유효성 검증을 하는 데에 용이하게 사용할 수 있는 joi 패키지에 대해서 사용법을 한 번 더 알아보았다. joi에서는 정규식을 통한 유효성 검증 규칙을 넣을 수 있으며, 그 외에서도 min, max와 같이 최소/최대 문자열 길이를 제한할 수도 있다. 제작한 검증 규칙으로 검증하고 싶다면 joi.validate()함수를 이용하여 검증한다.

// 터미널에서 joi 패키지를 추가하는 명령어
yarn add joi

// 파일에서 추가한 joi패키지를 임포트
import Joi from "joi"

// 유효성 체크를 위한 스키마 생성.
const schema = Joi.object().keys({
  id: Joi.string()
    .pattern(new RegExp("^[a-z]+[0-9]+$"))
    .min(3)
    .max(20)
    .required(),
  password: Joi.string()
    .min(6)
    .required(),
});

// 유효성 검증(오류 발생시 error에 저장)
const {error} = schema.validate({ id: accountId, password: accountPassword })

 

Prisma DB 2개 같이 사용하는 법

Prisma에서는 @Prisma/client와 같이 하나의 client를 사용해야 할 것 같지만 client를 각 DB마다 만들어 준다면 두 client를 사용할 수 있으며, 즉  DB 2개를 같이 사용할 수 있다. 하지만 DB 2개를 같이 사용하려면 다음과 같은 절차가 필요하다.

 

  1. .prisma파일 1개 더 추가하기
  2. 각 .prisma파일에 output변수 설정하기
  3. .env파일에 있던 DB_URL 2개로 나눠서 연결하기
  4. db 연동하기
    $ npx prisma db pull --schema ./prisma/test.prisma​
  5. client 생성하기
    $ npx prisma generate --schema ./prisma/test.prisma​

자세한 절차와 내용은 다른 분이 자세히 정리해놨다.
https://velog.io/@nohsangwoo/prisma-%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%98-db-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0

 

prisma - 여러개의 db 연결하기

이후 root경로에 prisma/schema.prisma가 생길것이다.나는 이미 존재하는 여러개의 DB를 끌어다가 사용하려고 하기때문에 각각 schema 별로 client를 각각 생성해줘야 한다.따라서 아래와 같이 schema파일의

velog.io

 

오늘의 Trouble Shooting                  

Problem 1. Joi.validate()의 오류 시 반환 값 문제

joi패키지를 이용해서 유효성 검사를 하려했지만 잘못된 id와 password에도 계속해서 통과되는 문제가 발생했다. joi 패키지를 잘 사용하지 않았던지라 어디서 문제가 발생했는 지 알 수가 없었다... 

// 시도한 코드 1
if(!schema.validate({ id: accountId, password: accountPassword })){
  return res
    .status(400)
    .json({ message: "아이디 또는 비밀번호가 조건에 맞지 않습니다." });
}

// 시도한 코드 2
try{
  schema.validate({ id: accountId, password: accountPassword })
}
catch(error){
  return res
    .status(400)
    .json({ message: "아이디 또는 비밀번호가 조건에 맞지 않습니다." });
}

Solve. Joi.validate()는 오류 발생 시, 오류 속성이 추가되는 방식이다.

Joi.validate()는 boolean값을 반환하지도, 오류를 발생시키지도 않았기 때문에 위 두 방식으로 오류를 잡으려 해도 잡히지 않았던 것이다. Joi.validate()는 오류가 발생하면 error라는 속성이 추가되는 방식이므로, error 속성이 존재하는 지 if문으로 확인하면 되었다.

// 오류 발생 시 error가 존재하게 된다.
const {error} = schema.validate({ id: accountId, password: accountPassword });
if(error){
  return res
    .status(400)
    .json({ message: "아이디 또는 비밀번호가 조건에 맞지 않습니다." });
}

Problem 2. Error [ERR_UNSUPPORTED_DIR_IMPORT]: .../prisma\userClient is not supported resolving ES modules imported from .../src\utils\prisma\prisma_userClient.js 오류 발생

DB를 하나만 쓰다가 2개를 사용하기 위해 설정을 하고 있는 도중 위와 같은 오류가 발생하면서 계속 연결이 되지 않았다. 

Solve. @prisma/client와 달리 /client/index.js까지 입력

이 오류는 Prisma Client를 생성할 때 디렉토리에서 모듈을 직접 가져오려고 시도했기 때문에 발생하는 것이다. 즉, 경로의 문제였고, 경로를 제대로 설정해주면 정상적으로 각 DB에 연결이 된다. 

// prisma_gameDataClient.js

// 이렇게 변경!
//import { PrismaClient } from '../../../prisma/gameDatasClient';
import { PrismaClient } from '../../../prisma/gameDatasClient/index.js';

export const prisma = new PrismaClient({
  // Prisma를 이용해 데이터베이스를 접근할 때, SQL을 출력해줍니다.
  log: ['query', 'info', 'warn', 'error'],

  // 에러 메시지를 평문이 아닌, 개발자가 읽기 쉬운 형태로 출력해줍니다.
  errorFormat: 'pretty',
}); // PrismaClient 인스턴스를 생성합니다.

 

 

오늘 한 일                                       

더보기
  • Node.js 과제 필수 요구사항 코드 최종 수정 및 마무리
  • Node.js 과제 선택 요구사항: 아이템, 유저 데이터베이스 분리해서 각각 연결, 돈 벌기 API 제작
  • 네트워크 계층 글 초안 작성