CodingSpace

[NodeJS/Express] express-validator 라이브러리를 이용한 유효성 검사 구현 본문

Back-End/NodeJS

[NodeJS/Express] express-validator 라이브러리를 이용한 유효성 검사 구현

개발자_조이킴 2022. 12. 21. 23:00


Intro.

유효성 검사(validation)는 말 그대로 유저(클라이언트)로부터 서버로

전달된 데이터유효한지를 검사하는 것을 의미합니다.

 

express를 사용하는 경우,

유효성 검사 기능을 구현하기 위해

주로 class-validatorexpress-validator 라이브러리를 사용합니다.

 

이번 글에서는 express-validator 라이브러리를 사용해

유효성 검사를 구현해봅니다.


Description.

1. npm 프로젝트 시작하기

npm init 명령어를 입력해서 새로운 프로젝트를 생성한다!

// npm 프로젝트 생성
npm init

명령어를 입력하고 Enter를 계속 입력해주면

package.json 파일이 생성된다!

 

 

2. express, express-validator 설치하기

npm install express express-validator 명령어를 입력해서 express와 express-validator를 설치한다.

// express, express-validator 설치
npm install express express-validator

 

3. POST 요청에서 body 값 유효성 검사 구현

먼저 POST 요청에서 전달되는 body 값 유효성 검사를 구현해보자.

유효성 검사는 Router 레벨에 적용했다.

테스트가 진행될 POST 요청 예제는 '회원가입(signup)'으로 선택했다.

body 값의 각 파라미터 유효성 조건은 다음과 같이 정했다:

  • email
    • required 파라미터
    • 이메일 형식 (ex. joykim9311@gmail.com)
  • password
    • required 파라미터
    • 최소 길이: 4
    • 최대 길이: 25
    • 영어 대소문자 포함

 

3.1. express-validator 함수

email과 password 파라미터 유효성 검사를 위해 express-validator 내장 함수들을 사용했다:

  • notEmpty()
  • isEmail()
  • isLength()
  • matches

유효성 검사를 통과하지 못했을 때

각 유효성 검사에 매칭되는 에러 메시지를 표현하기 위해

withMessage() 내장 함수를 사용했다.

  • withMessage()

 

3.2. Router 레벨에 적용한 유효성 검사 코드

앞서 이야기한대로 유효성 검사는 Router 레벨에서 이뤄지도록 구현했다.

// user.route.js 파일

import express from "express";
import { check, } from "express-validator";
import UserController from "../controller/user.controller.js";

const userController = new UserController();
const userRoute = express.Router();

userRoute.post(
    '/signup', [
        check('email') // email 파라미터 유효성 검사
                .notEmpty() // 1. 파라미터가 비어있으면 에러
                .withMessage(`email parameter is empty`)
                .isEmail() // 2. 파라미터가 이메일 형식이 아니면 에러
                .withMessage(`email parameter is not email format`)
        ,
        check('password') // password 파라미터 유효성 검사
                .notEmpty() // 1. 파라미터가 비어있으면 에러
                .withMessage(`password parameter is empty`)
                .isLength({ // 2. 파라미터의 길이가 4이상 25이하가 아니면 에러
                    min: 4,
                    max: 25
                })
                .withMessage(`password parameter is satisfied by following a condition; 4 <= password.length <= 25`)
                .matches(/^.*[a-z].*$/)
                .withMessage(`password parameter should contain at least one lower case`)
                .matches(/^.*[A-Z].*$/)
                .withMessage(`password parameter should contain at least one upper case`)
    ],
    userController.signup
);

export default userRoute;

 

3.3. 유효성 검사 에러 확인 및 반환

유효성 검사를 통과하지 못하면 에러가 생성된다.

생성된 에러들은 express-validator 내장 함수 validationResult()를 사용해 받을 수 있다.

 

코드의 가독성을 높이고자

유효성 검사를 통해 생성된 에러 확인 및 반환은

Controller에서 구현했다. (에러 확인 및 반환을 middleware로 따로 구현하면 코드 가독성을 더 향상시킬 수 있음!)

// user.controller.js

import UserService from "../service/user.service.js";
import { validationResult } from "express-validator";

export default class UserController {

    constructor() {
        this.userService = new UserService();
    }

    signup = (req, res) => {
        // 유효성 검사에서 생성된 에러를 errors 변수로 받는다
        const errors = validationResult(req);
        // 유효성 검사에서 생성된 에러가 있는 경우
        // 400 상태코드와 함께 에러들을 반환한다.
        if (!errors.isEmpty()) {
            return res.status(400).send(errors.array());
        }
        // 유효성 검사를 통과한 경우
        // 유저를 DB에 추가한다 (본 프로젝트에서는 DB가 아닌 서버 메모리에서 처리함)
        const { email, password } = req.body;

        const userInfo = {
            email,
            password,
        }

        const user = this.userService.createUser(userInfo);

        res.status(201).send({
            success: true,
            message: `user is created`,
            data: user,
        });
    }
}

 

3.4. Postman 유효성 검사 테스트

설계한대로 유효성 검사 기능이 구현되었는지 확인하고자 Postman을 사용하여 테스트를 진행했다.

 

1) email 파라미터가 비어있는 경우

notEmpty() 및 isEmail() 함수 모두 통과하지 못해 2가지 에러가 발생했다.

email 파라미터가 비어있는 case

 

2) password 파라미터의 길이가 4보다 작거나 25보다 큰 경우

isLength() 함수를 통과하지 못해 에러가 발생했다.

password 파라미터의 길이가 4보다 작은 case
password 파라미터의 길이가 25보다 큰 case

 

3) password 파라미터에 영어 대소문자가 포함되지 않은 경우

matches() 함수를 통과하지 못해 에러가 발생했다.

password 파라미터에 영어 대문자가 포함되지 않은 case
password 파라미터에 영어 소문자가 포함되지 않은 case

 

4) 모든 유효성 검사가 통과되고 유저가 생성된 경우

모든 유효성 검사가 통과된 case


References. 

- 전체 코드:

1) 프로젝트 구조

 

2) app.js 

더보기
// app.js

import express from "express";
import userRoute from "./routes/user.route.js";

const app = express();
const port = 3333;

app.use(express.json());
app.use('/user', userRoute);

app.get('/', (req, res) => {
    console.log('server for express-validator example');
});

app.listen(port, () => {
    console.log(`server is running at ${port}`);
});

 

3) user.route.js

더보기
// user.route.js

import express from "express";
import { check, } from "express-validator";
import UserController from "../controller/user.controller.js";

const userController = new UserController();
const userRoute = express.Router();

userRoute.post(
    '/signup', [
        check('email')
                .notEmpty()
                .withMessage(`email parameter is empty`)
                .isEmail()
                .withMessage(`email parameter is not email format`)
        ,
        check('password')
                .notEmpty()
                .withMessage(`password parameter is empty`)
                .isLength({
                    min: 4,
                    max: 25
                })
                .withMessage(`password parameter is satisfied by following a condition; 4 <= password.length <= 25`)
                .matches(/^.*[a-z].*$/)
                .withMessage(`password parameter should contain at least one lower case`)
                .matches(/^.*[A-Z].*$/)
                .withMessage(`password parameter should contain at least one upper case`)
    ],
    userController.signup
);

userRoute.get(
    '/:userNo', [
    check('userNo')
        .isInt()
    ],
    userController.selectUser
);

export default userRoute;

 

4) user.controller.js

더보기
// user.controller.js

import UserService from "../service/user.service.js";
import { validationResult } from "express-validator";

export default class UserController {

    constructor() {
        this.userService = new UserService();
    }

    signup = (req, res) => {

        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            return res.status(400).send(errors.array());
        }

        const { email, password } = req.body;

        const userInfo = {
            email,
            password,
        }

        const user = this.userService.createUser(userInfo);

        res.status(201).send({
            success: true,
            message: `user is created`,
            data: user,
        });
    }

    selectUser = (req, res) => {

        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            return res.status(400).send(errors.array());
        }

        const userNo = req.params.userNo

        const user = this.userService.selectUser(userNo);

        res.status(200).send({
            success: true,
            message: `user is selected`,
            data: user,
        });
    }
}

 

5) user.service.js

더보기
// user.service.js

export default class UserService {
    constructor() {
        // 생성된 유저들을 담는 배열
        this.userList = [];
        // 유저의 번호 (unique)
        this.userNo = 0;
    }

    createUser = (userInfo) => {
        userInfo['no'] = this.userNo;
        this.userNo = this.userNo + 1;
        this.userList.push(userInfo);
        return userInfo;
    }

    selectUser = (userNo) => {
        return this.userList[userNo];
    }
}

 

- express-validator 공식 문서: https://express-validator.github.io/docs/index.html

 

Getting Started · express-validator

express-validator is a set of [express.js](http://expressjs.com/) middlewares that wraps

express-validator.github.io

 

- node.js + express 이미지 출처: https://velog.io/@gidong_e/Node.js-Express

 

[Node.js] Express

이전 시간에 Node.js HTTP 모듈에 대해 배웠고, 오늘은 Express 모듈에 대해 설명해보려고 한다.expressjs.com/ko/ 에서 설명하는 바는 다음과 같다."Express는 웹 및 모바일 애플리케이션을 위한 일련의 강력

velog.io

 

Comments