본문 바로가기

Backend/Node.js

Node.js exception handler - custom error

Node.js에서 커스텀한 메시지를 내려볼게요.

실제로 발생하는 오류가 아닌 "비밀번호 불일치", "게시글 없음"과 같은 오류를 전달할거에요.

바로 예제로 가볼게요. Express Framework 환경이구요.

 

아마 에러 핸들러를 만드는 최소한의 코드일거에요.

수정하셔서 사용하시면 될 것 같습니다.

일단 custom-error, error-handler라는 파일을 만들었어요.

custom-error.js

class CustomError extends Error {
  constructor(code, message, ...params) {
    super(...params)

    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError)
    }

    this.code = code
    this.message = message
  }
}

module.exports = CustomError

error-handler.js

const CustomError = require('./custom-error')

module.exports = (err, req, res, next) => {
  if (err instanceof CustomError) {
    return res.status(err.code).json(err)
  }
  console.log(err)
  return res.status(500).json(err)
}

app.js

다음의 코드를 추가해주세요.

꼭! routes 설정 밑에다가 추가해주셔야 해요.

자바스크립트라 위에서부터 차례로 읽습니다.

 

var errorHandler = require('./src/advice/error-handler')

app.use('/user', require('./src/routes/user-route'))
app.use('/boards', require('./src/routes/boards-route'))

app.use(errorHandler)

 

 

설정은 위에가 끝이구요.

이제 CustomError를 이용해서 메시지를 응답해볼게요.

user-route.js

간단하게 로그인 API 를 만들어봤어요.

저 같은 경우는 파라미터 validation과 session 관련 로직을 route에서 구현하고

이외의 비즈니스 로직은 service에 작성하는 편이에요.

 

const express = require('express')
const router = express.Router()

const userService = require('../services/user-service')

router.post('/signin', async (req, res, next) => {
  let { email, password } = req.body
  let session = req.session
  try {
    let resBody = await userService.signin(email, password)
    session.userId = resBody.id
    session.userName = resBody.name
    return res.json(resBody)
  } catch (err) {
    next(err)
  }
})

 

user-service.js

이렇게 service에서 throw new CustomError로 에러를 발생시키면 되요.

 

const pool = require('../datas/pool')
const CustomError = require('../advice/custom-error')

const bcrypt = require('bcrypt')

exports.signin = async (email, password) => {
  const fetched = await pool.query(`
    select 
      id,
      email,
      name,
      gender,
      password,
      createdAt,
      updatedAt
    from User 
    where email = ?`,
    [email]
  )
  const users = fetched[0]
  if (users.length == 0) {
    throw new CustomError(404, '사용자를 찾을 수 없습니다.')
  }

  let user = users[0]
  if (!bcrypt.compareSync(password, user.password)) {
    throw new CustomError(404, '패스워드가 다릅니다.')
  }

  return user
}

 

호출 테스트를 해볼게요.

원래 비밀번호는 1234인데 일부로 틀리게 해봤어요.

 

POST http://localhost:3000/user/signin
Content-Type: application/json

{
  "email": "hkhong91@gmail.com",
  "password": "1235"
}

 

HTTP/1.1 404 Not Found
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 43
ETag: W/"2b-C4eEPL9kL/1ulbx7lYBFmrDpheU"
Set-Cookie: connect.sid=s%3AH3JXPMe-0PXFWZZom_hrEevDYM-TlDN_.%2B77iaoBwu4EcIVo7U53PwHXvLni9DLsdO7yhL5X6UtQ; Path=/; HttpOnly
Date: Fri, 04 Sep 2020 10:45:28 GMT
Connection: close

{
  "message": "패스워드가 다릅니다."
}