복's

[ Nest JS ] 예외 처리 (Exception Handling) 및 예외 필터(Exception filters) 본문

교육/SW 정글 프로젝트(나만무)

[ Nest JS ] 예외 처리 (Exception Handling) 및 예외 필터(Exception filters)

나복이 2023. 11. 15. 23:51
728x90

1) 예외 처리하기

[ Exceptions layer ]

nestJS는 프레임워크 내부에 예외 레이어가 있어서 유저가 어플리케이션단에서 처리하지 못한 예외들(Unhandled exceptions)을 캐치해서 처리해준다.

이 때 적절하게 유저가 알아보기 쉬운(user-friendly) 형태로 응답해 주는데 json 타입을 말하는 것 같다.

{
  "statusCode": 500,
  "message": "Internal server error"
}

500대 코드로 서버에서 요청 처리하는 과정에서 발생하는 에러로 변환되어서 반환된다.

예외가 인식 불가능한 경우(Unrecognized) - HttpException이 아니면서 HttpException을 상속 받는 에러도 아닌경우 InternalServerErrorException로 변환한다.

[ InternalServerErrorException ]

InternalServerErrorException는 HttpException을 상속받고 있고

[ HttpException ]

HttpException는 Error를 상속받고 있다. 

HttpException는 2개의 필수 인자를 받는데

  • response: string이나 object가 될 수 있고, response body의 json이 될 인자 값
    • StatusCode: GTTP status code
    • message: code에 대한 메세지
  • status: enum 타입으로 정의된 HTTP status code
  • option: response로 serialized 되지는 않지만 logging 목적으로 쓰이는 인자 값
constructor(response: string | Record<string, any>, status: number, options?: HttpExceptionOptions);

실제 코드에서 throw를 통해서 에러를 발생 시켜보면

throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);

[ Response Body - Postman ]

별다른 try - catch 없이도 에러를 처리해서 응답까지 완료한 모습

export declare class BadRequestException extends HttpException {

다른 HTTP code에 따른 예외도 정의되어 있다.

[ HttpException을 상속한 HTTP code status ]

사실 에러를 상속받아서 오버라이딩해서 커스텀한 에러를 사용하려고 알아보다 보니까 예외 필터(Exception Filter) 레이어를 만들어서 전역적으로 사용할 수 있다는걸 알게 되었다.


2) 예외 필터 만들기

예외 필터 만드는 방법도 일단 docs만 봤을 때는 간단하다.

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch()
export class DoWithExceptionFilterFilter<T> 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();

        // if로 custom exception 처리하면 될듯 (throw로 예외 처리 하는 것들)

        response.status(status)
                .json({
                    statusCode: status,
                    timestamp: new Date().toISOString(),
                    path: request.url,
                });
    }
}

나는 모든 예외를 잡아내고 싶어서 HttpException이 아니라 @Catch에 아무것도 넣지 않았다.

나중에 Exception을 커스텀해서 throw 할 것이기 때문에 대신 if 처리로 instanceof로 내 커스텀 에러인지 확인해서 상태 코드만 200으로 변경해줄 생각이다. (예정임)

 

필터 적용은 더 쉬운 것 같다.

특정 엔드 포인트 / 컨트롤러 / 어플리케이션 전체(global) 이렇게 적용 가능한데 나는 global로 설정했다.

...
app.useGlobalFilters(new DoWithExceptionFilterFilter());
...

[ Response Body - Postman ]

필터에 들어가서 내가 원하던 대로 결과가 내려갔다.

Exception 처리 하면서 console창에 log도 찍고싶어졌다.

Logger를 생성자 주입 받아야 하는지 잘 모르겠어서 내가 하고싶은데로 했다...(문제가 클라나)

...
app.useGlobalFilters(new DoWithExceptionFilter(new Logger()));
...

new 연산으로 인스턴스 객체 넘겨줬는데 inject를 사용했어야 했는지는 잘 모르겠다. nestJS 이제 2일차 공부하는건데 모르는게 너무 많다... 어떻게 프로젝트 진행하지 ㅠㅠ

[ Log in Filter ]

 

 

https://docs.nestjs.com/exception-filters

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea

docs.nestjs.com

 

728x90