express 프로젝트 중 문득 궁금한게 생겼다. express 같은 경우 예기치 않은 에러가 발생했을때 try-catch등으로 방지를 안했을 경우 서버가 종료된다. 이는 매우 치명적으로 다가올 수 있기 때문에 꼭 try-catch등으로 예기치 않은 에러를 대비해야 한다.
하지만 nest에서는 controller-layer에서 try-catch 등으로 에러를 처리해주지 않아도 자동으로 Internal server error를 응답한다.
아마도 exception filter가 처리해주는 것으로 보이는데 정확히 알고있지 않기에 자세하게 공부해 볼려고 한다.
nestJs 공식문서에 따르면 다음과 같다.
위 내용을 요약하면 다음과 같다.
express에서는 status와 message를 함께 담아 error를 throw할 경우 다음과 같이 코드를 작성해야 한다.
const error = new Error("존재하지 않는 예약 정보입니다.");
error.status = 404;
throw error;
하지만 모든 error에 대해 일일히 코드를 작성하면 번거롭기에 별도의 class를 생성해서 코드를 간략하게 한다.
// 별도 클래스 작성
export class HttpException extends Error {
constructor(status, message) {
super(message);
this.status = status;
}
}
// 코드 간략화 및 가독성 높이기
throw new HttpException(404, "존재하지 않는 예약 정보입니다.");
nest에서는 express와 달리 대부분의 Http 예외가 내장되어 있다.
다음과 같이 내장되어 있는 HttpException을 사용해 예외를 처리 할수 있다.
// forbidden
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, HttpStatus.FORBIDDEN, {
cause: error
});
그리고 또한 코드의 가독성 및 효율성을 높여주는 커스텀 예외 또한 존재한다.
// forbidden
throw new ForbiddenException();
nest는 기본적으로 다음과 같은 커스텀 예외를 지원하며 이를 활용하는 것은 코드에 매우 도움이 될 것이다.
기본적으로 내장되어 있는 예외 필터의 응답을 바꾸고 싶거나 예외가 발생했을때 특정 기능을 수행하고 싶을경우 직접 exception filter를 작성할 수 있다.
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url + "<- 여기서 발생한 에러임",
});
}
}
위와 같이 추가적으로 응답을 수정하거나 혹은 다른 기능을 수행하는 방향으로 커스터함 예외 필터를 작성할 수도 있다.