Api 요청 유효성 검사 적용

유댕·2023년 12월 12일

회사

목록 보기
7/8

Api 요청 유효성 검사에 express-validator를 사용했습니다 . express-validator는 express에서 사용할 수 있는 유효성 검사 모듈입니다.

체크해야할 항목

  • 필수 파라미터 체크
  • 파라미터 타입 체크
  • 정의된 파라미터 외 제거 후 api 요청

💡 사용

  1. 모듈 설치

npm install express-validator

  1. 유효성 검사 목록 정의
const { query } = require('express-validator');

const searchItemQuery = [
  // 각 매개변수에 대한 검증 규칙 추가
query('minPrice').optional().isNumeric().withMessage('minPrice parameter is not correct'),
  query('maxPrice').optional().isNumeric().withMessage('maxPrice parameter is not correct'),
  query('usedType').optional().isString().withMessage('usedType parameter is not correct'),
  query('hasDeliveryFee')
    .optional()
    .isBoolean()
    .withMessage('hasDeliveryFee parameter is not correct'),
  query('brandIdx').optional().isNumeric().withMessage('brandIdx parameter is not correct'),
  query('sort').optional().isString().withMessage('sort parameter is not correct'),
  query('page').isNumeric().optional().withMessage('page parameter is not correct'),
  query('limit').isNumeric().optional().withMessage('limit parameter is not correct'),
];

module.exports = {
  searchItemQuery
};
  1. 미들 웨어 추가해 유효성 검사
const { validationResult } = require('express-validator');

const onValidate = async (req, res, query) => {
  // 정의된 유효성 검사
  await Promise.all(query.map((validation) => validation.run(req)));

  // 유효성 검사 오류 확인
  const errors = validationResult(req);

  // 유효성 검사 오류 발생시
  if (!errors.isEmpty()) {
    res.json({ status: 400, message: errors.array()[0].msg });
    throw new Error('유효성 검사 실패');
  }
};

module.exports = onValidate;

validationResult 는 request로 넘어오는 파라미터들을 정의한 부분의 유효성을 검증한 후 에러가 발생하면 배열 형태로 반환하는 함수입니다. 따라서 errors가 비었으면 유효성 검증이 통과된 것입니다.

유효성 검사 오류 발생시 res.json으로 400코드와 해당 에러 메세지를 넘깁니다. 후에 예외처리로 에러를 던진 후 함수를 중지시켜 Api통신을 하지 않게합니다.

  1. 사용
searchItemList: async (req, res, next) => {
    const { searchItemQuery } = require('./validator');
    await onValidate(req, res, searchItemQuery);
    try {
      const queryData = querystring.stringify(req.query);
      const url = `${config['search']['item']}?${queryData}`;
      if (req.headerConfig.headers['Authorization']) {
        const token = await jwt.decodeToken(req.headerConfig.headers['Authorization']);
        req.headerConfig.headers['Authorization'] = token.token;
      }
      const searchData = await axios.getUrl(url, req.headerConfig);
      res.json(searchData);
    } catch (err) {
      next(err);
    }
  },

유용한 express-validator 함수들

  • trim() : 공백을 제거해줍니다.
  • isNumeric() : number 형태이지 확인한다. string이어도 해당 string이 숫자인지 확인해줍니다.
  • isString() : string 형태이지 확인한다.
  • isBoolean() : boolean 형태이지 확인한다.
  • isLength(num) : 길이가 num인지 확인해줍니다. { min: num, max: num } 과 같이 최소, 최대 값도 지정할 수 있습니다.
  • .optional() : 해당 파라미터가 없어도 유효성 검사가 실행되지 않으며 에러로 처리되지 않습니다.

💡 Folder Structure

각 api마다 종속성 있도록 작성

const { query } = require('express-validator');

// 검색 목록 검증 규칙
const searchValidation = [
  query('q').optional().isString().withMessage('q parameter is not correct'),
  query('minPrice').optional().isNumeric().withMessage('minPrice parameter is not correct'),
  query('maxPrice').optional().isNumeric().withMessage('maxPrice parameter is not correct'),
  query('usedType').optional().isString().withMessage('usedType parameter is not correct'),
  query('hasDeliveryFee')
    .optional()
    .isBoolean()
    .withMessage('hasDeliveryFee parameter is not correct'),
  query('sort').optional().isString().withMessage('sort parameter is not correct'),
  query('page').optional().isNumeric().withMessage('page parameter is not correct'),
  query('limit').optional().isNumeric().withMessage('limit parameter is not correct')
];

module.exports = {
  query: searchValidation,
};
const { query } = require('express-validator');

// 검색 아이템 목록 검증 규칙
const searchItemValidation = [
  query('q').optional().isString().withMessage('q parameter is not correct'),
  // categoryId의 파라미터를 비교는는게 맞나?? 어떻게?
  query('categoryId').optional().isString().withMessage('categoryId parameter is not correct'),
  query('minPrice').optional().isNumeric().withMessage('minPrice parameter is not correct'),
  query('maxPrice').optional().isNumeric().withMessage('maxPrice parameter is not correct'),
  query('usedType').optional().isString().withMessage('usedType parameter is not correct'),
  query('hasDeliveryFee')
    .optional()
    .isBoolean()
    .withMessage('hasDeliveryFee parameter is not correct'),
  query('sort').optional().isString().withMessage('sort parameter is not correct'),
  query('page').optional().isNumeric().withMessage('page parameter is not correct'),
  query('limit').optional().isNumeric().withMessage('limit parameter is not correct')
];

// 나의 아이템 목록 검증 규칙
const searchMyItemListValidation = [
  query('q').optional().isString().withMessage('q parameter is not correct'),
  query('categoryId').optional().isString().withMessage('categoryId parameter is not correct'),
  query('minPrice').optional().isNumeric().withMessage('minPrice parameter is not correct'),
  query('maxPrice').optional().isNumeric().withMessage('maxPrice parameter is not correct'),
  query('sellState').optional().isString().withMessage('sellState parameter is not correct'),
  query('page').optional().isNumeric().withMessage('page parameter is not correct'),
  query('limit').optional().isNumeric().withMessage('limit parameter is not correct')
];

// 회원샵 아이템 목록 검증 규칙
const searchShopItemListValidation = [
  query('memberIdx').optional().isNumeric().withMessage('memberIdx parameter is not correct'),
  query('q').optional().isString().withMessage('q parameter is not correct'),
  query('categoryId').optional().isString().withMessage('categoryId parameter is not correct'),
  query('sellState').optional().isString().withMessage('sellState parameter is not correct'),
  query('page').optional().isNumeric().withMessage('page parameter is not correct'),
  query('limit').optional().isNumeric().withMessage('limit parameter is not correct')
];

module.exports = {
  searchItemQuery: searchItemValidation,
  searchMyItemListQuery: searchMyItemListValidation,
  searchShopItemListQuery: searchShopItemListValidation
};

node 버전 12부터 ES6의 구조 분해 할당 문법이 지원되는데 우리 서버는 10점대이므로 수정이 필요

// 전
const { query, check } = require('express-validator');

// 후
const expressValidator = require('express-validator');
const query = expressValidator.query;
const check = expressValidator.check;

🐞 ERROR

알파배포 후 502
알파/리얼 빌드 둘다 성공
젠킨스에서도 오류 없음

11트만에 드디어 해결………………

"express": "^4.18.2" 버전을 사용

해당 버전과 호환되는 express-validator 버전 6.x.x

"express-validator"의 7.x.x 버전은 Express.js 5.x.x 버전과 함께 사용하기 위해 개발

왜 에러가 안뜨지..🧐

rebase까지 완료~!


[참고 Docs ]

npm: express-validator

express-validator | express-validator

https://github.com/validatorjs/validator.js

0개의 댓글