coding/Node.js

에러 핸들러

JIN_Coder 2022. 9. 3. 01:43

지금까지 프로젝트를 진행하면서 에러 처리를 항상 try catch 문으로 정의하여 사용했었다.

try문안에서 에러가 발생하면 서버의 오류이기 때문에 500 status와 함께 메시지를 보냈고,

if문을 통해서 클라이언트에게 유요한 값을 받지 못하거나, 사용자가 찾는 값이 db에 없는 경우에는 잘못된 요청이기 때문에 400 status와 오류 메시지를 보냈다.

 

하지만 이렇게 진행할 경우 예외처리가 많아질수록 잘못된 응답이라고 전달해주어야 하는 게 많아져 코드가 지저분해지고, 길어졌다.

 

예전에 에러 미들웨어를 만들어서 try문에서 에러가 발생하거나 예외처리에 걸러지는 경우 catch문으로 에러를 보내서 가장 마지막에 에러 핸들러를 통해서 잘못된 응답을 보내주면 좋다고 들어서 이번 기회에 에러 핸들러를 만들어 보았다.

 

사용 방법

1. 에러를 코스튬 하는 것

2. 에러 핸들러를 만드는 것

3. app.js에 에러 핸들러 배치

4. router에서 에러를 잡아 내는 것

 

에러 코스튬

서버 자체적인 에러라면 500 코드와 함께 에러를 응답하면 되지만, 사용자의 잘못된 요청의 경우 400번대 에러를 보내주어야 하기에 상황에 따라서 에러를 코스튬 하는 클래스를 만든다.

해당 상황의 에러 코드와 메시지를 코스튬 하여 보여준다.

// ./advice/errorCustom.js

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

	// 이 부분은 스택관련이라고하는데 잘모르겠다. 없어도 무방한것같음
    // if (Error.captureStackTrace) {
    //   Error.captureStackTrace(this, ErrorCustom);
    // }

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

module.exports = ErrorCustom;

 

 

에러 핸들러

코드 단에서 생긴 에러를 catch문으로 받아 에러 핸들러에 넘겨주어 에러 응답을 하고, 콘솔에 에러를 찍어볼 수 있다.

해당 에러가 코스튬 클래스로 만들어진 에러라면 상황에 따라 에러코드와 에러 메시지가 상의하기 때문에 if문으로 확인하여 다르게 보여주고, 정말 서버 자체에서 생긴 자연적인 에러라면 500 코드와 함께 에러를 응답한다.

// ./advice/errorHandler.js

const ErrorCustom = require('./errorCustom');

module.exports = (err, req, res, next) => {
  console.log(err);
  if (err instanceof ErrorCustom) {
    return res.status(err.code).json({ ok: false, errMsg: err.message });
  }

  return res.status(500).json({ ok: false, errMsg: err.message });
};

 

 

app.js에 에러 핸들러 배치

에러 핸들러도 미들웨어의 개념이기 때문에 가장 마지막에 배치하여 응답을 보내준다.

// app.js

const errorHandler = require('./advice/errorHandler');

...

app.use('/api', Router);
app.get('/', (req, res) => {
  res.status(200).json({ massage: '연동 잘 됨.' });
});
app.use(errorHandler);

app.listen(port, () => {
  console.log(port, '포트로 서버가 열렸어요!');
});

 

 

router에서 에러 잡아내기

평소와 똑같이 try catch문, if문을 사용하고

다른 점은 next 인자 값을 넣어주고, if문 예외처리에 걸리면 throw new ErrorCustom(status 코드, 에러 메시지);를 통해 에러로 만든다.

catch 문에서 next(err)로 에러 핸들러로 보내준다.

// ./routes/comment.js

// 댓글 작성
router.post('/:selectKey', authMiddleware, async (req, res, next) => {
  try {
    const { userKey, nickname } = res.locals.user;
    const { selectKey } = req.params;
    const { comment } = req.body;

    if (comment === '') {
      throw new ErrorCustom(400, '댓글을 입력해주세요.');
    }
    if (comment.length > 200) {
    throw new ErrorCustom(400, '댓글은 200자 이내로 작성 가능합니다.');
    }

    const data = await Select.findOne({ where: { selectKey } });

    if (!data) {
      throw new ErrorCustom(400, '해당 선택글이 존재하지 않습니다.');
    }

    const newComment = await Comment.create({
      comment,
      selectKey,
      userKey,
    });

    return res.status(200).json({
      ok: true,
      msg: '댓글 작성 성공',
      result: {
        commentKey: newComment.commentKey,
        comment: newComment.comment,
        nickname: nickname,
      },
    });
  } catch (err) {
    next(err);
  }
});

예외처리에 걸러진 에러는 해당 상황에 맞는 상태 코드와 메시지를 입력해주어 코스튬을 해주어서 next로 넘겨준다.

위와 같이 댓글 내용을 입력하지 않으면 if문에 걸려서 코스튬 된 에러가 발생되고 catch문의 next로 넘어가 에러 핸들러에서 코스튬 된 에러이기 때문에 해당 코드와 메시지를 응답으로 보낸다.

 

이렇게 에러 핸들러를 만들어서 모든 코드에 적용하니 불필요하고 중복되는 코드들이 줄어들어 가독성을 높이고 재사용성을 높여주었다.

'coding > Node.js' 카테고리의 다른 글

socket.io - 실시간 채팅 / 채팅방 구현  (2) 2022.09.07
소켓 / 웹소켓  (0) 2022.09.05
Sequelize Op like - 검색 기능  (0) 2022.08.23
페이지네이션  (0) 2022.08.23
express HTTPS 설정  (0) 2022.08.20