라봉이의 개발 블로그

node.js express 6. express의 오류처리 본문

Node.js/express

node.js express 6. express의 오류처리

Labhong 2019. 4. 5. 15:25
반응형

이전 포스트: node.js express 5. middleware란? 미들웨어 정의, 미들웨어 유형
저번 포스트에는 express의 미들웨어 개념을 알아봤습니다. (시간이 꽤 오래 지나버렸다..)

이번에는 express의 오류 처리 방법에 대해 알아보도록 하겠습니다.
이 포스트에 대한 내용은 express 공식 페이지에서 더 자세하게 알아볼 수 있습니다. express 오류처리

에러 핸들링

404 에러 처리

express는 미들웨어 중간에 오류가 발생하면 다음 에러 처리 미들웨어로 error 객체를 넘겨 error를 처리할 수 있도록 만들었습니다.
다음 코드는 app.js의 맨 밑에 있는 코드입니다.

// 라우터 등록
app.use('/', indexRouter);
app.use('/users', usersRouter);

// 등록되지 않은 path로 요청이 왔으면 404 페이지를 만들어야함.
// http-errors 모듈로 error 객체 생성 후 에러 처리 핸들러로 넘김
app.use(function(req, res, next) {
  // error 생성 후 next
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // error 템플릿에 전달할 데이터 설정
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
})

이 코드는 등록되지 않은 url에 요청이 온다면 404 Not Found 페이지를 표시하기 위해 오류처리를 한 것입니다.
위의 등록된 url 외의 요청이 온다면 http-errors 모듈을 사용하는 미들웨어로 가게 됩니다.
그 미들웨어에서 error를 생성한 뒤 에러 처리 핸들러로 error를 넘기게 됩니다.

에러 처리 핸들러는 기존 미들웨어와 다르게 4개의 파라미터 즉, err, req, res, next를 가진다는 점입니다.
여기서 중요한 점은 에러 처리 핸들러를 등록하기 위해선 다른 app.use() 및 라우트 호출을 정의한 후에 마지막으로 정의해야 합니다.

라우터의 오류 처리

에러 처리 핸들러는 위에서 설명한 대로 다른 app.use() 에서도 사용 가능합니다.
만약 /user 요청에 사용자 정보가 없을 때의 오류 처리 예시를 보도록 하겠습니다.

const usersRouter = require('./routes/users');

...

app.use('/users', usersRouter, function (err, req, res, next) {
  console.log("User Not Found");
  if(err.message === 'user_not_found') {
      res.status(400)
      .type('html')
      .end("User doesn't exist");
  } else {
      res.status(500)
      .type('html')
      .end("500 error");
  }
});

앞의 라우터 usersRouter에서 error가 발생했을 때만 오류 처리를 하고 싶을 땐 app.use()에 따로 등록할 수도 있습니다.
혹은 error 타입마다 오류를 다르게 처리할 수도 있습니다.

필자는 Node.js의 Error 모듈을 상속받는 새로운 타입의 Error 객체를 정의하고 Error 타입마다 다른 방식의 오류 처리 핸들러를 구현한 적도 있습니다. Error 타입만 잘 설정하면 따로 Error 처리에 신경을 쓰지 않아도 되기 때문에 매우 편리했다.

간단하게 예를 들어보겠습니다.

// ClientError.js
module.exports = class ClientError extends Error {
  constructor (message, status) {
    super(message);
    Error.captureStackTrace(this, this.constructor);

    // status를 따로 설정하지 않으면 default로 400이 설정된다.
    this.status = status || 400;
  }
};

---------------

// userRouter.js

...

const ClientError = require('../ClientError');
let myError = new ClientError("Test Error");
next(myError);

...

이를 이용해 핸들러에서 if(err instanceof ClientError)로 error 타입 구분하신 뒤에 따로 처리할 수도 있습니다.

결론

express는 각 라우터에서 발생하는 error를 개별적으로 처리하지 않고 에러 처리 핸들러를 통해 묶어서 처리할 수 있다는 것을 알게됐습니다. 이를 통해 서버 오류를 쉽게 핸들링하고 묶어서 관리할 수 있습니다.

반응형
Comments