NestJS 공식문서, 서적을 참고한 예외 필터 공부 기록
개요
Nest는 모든 예외를 처리하는 기본 제공 예외 레이어를 가지고 있다.
만약 코드에서 예외를 처리하지 않으면 예외 레이어에서 자동으로 예외를 보낸다.
기본적으로 위 작업은 HttpException 유형의 예외를 처리하는 예외 필터에 의해 수행된다.
예외가 인식되지 않은 경우 500 에러를 보낸다.
{
"statusCode": 500,
"message": "Internal server error"
}
HttpException
HttpException은 결국 자바스크립트의 Error 객체를 상속한다.
따라서 모든 예외는 Error 객체로부터 파생됐다고 볼 수 있다.
HttpException 클래스를 보자.
export declare class HttpException extends Error {
...
constructor(response: string | Record<string, any>, status: number);
...
}
- response : JSON 응답 본문. 문자열이나 Record<string, any> 타입의 객체를 전달할 수 있다.
- status : 에러의 속성을 나타내는 HTTP 상태 코드
상황별 에러들은 아래 링크에 잘 정리되어있다.
예외 필터
Nest에서는 앞서 말했듯 예외 필터 레이어가 있어서 원하는 대로 예외를 다룰 수 있다.
예외가 일어났을 때 로그를 남기거나 응답 객체를 변경하는 등의 동작이 그 예시이다.
예외가 발생했을 때 모든 예외를 잡아 요청 URL과 예외가 발생한 시각을 콘솔에 출력하는 예외 필터를 만들어 보자.
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
InternalServerErrorException,
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const req = ctx.getRequest<Request>();
const res = ctx.getResponse<Response>();
if (!(exception instanceof HttpException)) {
exception = new InternalServerErrorException();
}
const response = (exception as HttpException).getResponse();
const log = {
timeStamp: new Date(),
url: req.url,
response,
};
console.log(log);
res.status((exception as HttpException).getStatus()).json(response);
}
}
- @Catch : 처리되지 않은 모든 예외를 잡으려고 할 때 사용
- Nest에서 처리하는 것과 동일하게 HttpException이 아닌 예외는 500 에러로 처리했다.
이제 예외 필터를 적용해 보자.
@Controller('users')
@UseFilters(HttpExceptionFilter)
export class UsersController {
...
}
필터는 위처럼 컨트롤러 전체에 적용할 수도 있고, 특정 엔드포인트에 적용할 수도 있다.
또한 useGlobalFilters를 이용해 어플리케이션 전체에도 적용할 수 있다.
이제 처리하지 못한 예외가 발생하면 아래처럼 로그가 출력되는 것을 확인할 수 있다.
예외 필터에 로거 적용
저번 기록에서 만든 로거를 예외 필터에 적용해 보자.
import { Logger, Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { HttpExceptionFilter } from './HttpException.filter';
@Module({
providers: [Logger, { provide: APP_FILTER, useClass: HttpExceptionFilter }],
})
export class ExceptionModule {}
먼저 ExceptionModule을 만들어준다.
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
InternalServerErrorException,
Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
constructor(private logger: Logger) {}
catch(exception: Error, host: ArgumentsHost) {
...
const stack = exception.stack;
...
const log = {
timeStamp: new Date(),
url: req.url,
response,
stack,
};
this.logger.log(log);
...
}
}
그리고 로거를 만든 필터에 주입해서 사용하면 된다.
코드로 처리하지 못한 예외가 정상적으로 출력된 것을 볼 수 있다.
참고
마치며
잘못된 정보에 대한 피드백은 환영입니다.
감사합니다.
'Backend > NestJS' 카테고리의 다른 글
[NestJS] Logger(Custom, Winston) (0) | 2023.02.14 |
---|---|
[NestJS] MiddleWare(Logger, MiddlewareConsumer) (0) | 2023.02.08 |
[NestJS] NestJS 공식 문서 정독(2)(Dynamic Module) (0) | 2023.01.26 |
[NestJS] NestJS 공식 문서 정독(1)(Custom Provider,Async Provider) (0) | 2023.01.24 |
[NestJS] 커스텀 유효성 검사기 작성(커스텀 데커레이터) (0) | 2023.01.22 |