본문 바로가기
좌충우돌 산악회 홈페이지 만들기

[좌충우돌 산악회 홈페이지 만들기 #4] Nest.js에서 Exception Filter 만들기

by dinB 2022. 4. 17.

* 정보 제공용 글이 아닌 개인 개발 일지 작성용입니다~ 비판 환영

 

1. 서론

이번에 만들어볼건 Nest.js에서 Exception Filter이다. 지난 시간에는 Response Interceptor를 구현해서 언제 일정한 Response를 두었는데, Exception Filter의 경우 내가 발생시키는 HttpException를 캐치해서 내가 원하는 Response로 정제해서 클라이언트 측에 제공할 수 있다.

 

그냥 throw new HttpException() 으로 날려버리면 Response는 이쁘게 떨어지는데 왜 이걸 만드냐! 하면 이유는 간단하다. 내가 Exception Layer를 직접 제어하고 싶기 때문이다! 일단 생각나는건 Response에 success 키를 붙이고, data 키를 붙이려고 한다. 추후 혹시 추가적으로 필요한 데이터가 있으면 data 키에 붙여서 클라이언트에게 보내줄 수도 있을 것이다!

 

오늘도 역시 공식 도큐먼트의 도움을 받는다.

 

 

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 Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

2. 구현

나는 common/filter 안에 http-exception.filter.ts라는 파일을 만들었다.

Exception Filter를 구현하기 위해서는 ExceptionFilter를 implements 해야한다고 한다. 또한, 클래스 데코레이터로 @Catch()를 사용할 수 있다는데, 해당 데코레이터를 사용함으로써 발생하는 예외를 잡아서 Filter 단으로 보내버린다고 한다.

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  Injectable,
} from '@nestjs/common';

// HttpException만 캐치
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter<HttpException> {
  catch(exception: HttpException, host: ArgumentsHost): any {
    const response = host.switchToHttp().getResponse();
    const statusCode = exception.getStatus();
    const message = exception.message;

    // Response Mapping
    return response.status(statusCode).json({
      success: false,
      statusCode: statusCode,
      msg: message,
      data: [],
    });
  }
}

구현도 매우 간단하다. @Catch() 데코레이터 안에 내가 캐치하고 싶은 Exception의 종류를 명시해주었다. 나는 HttpException 예외만 잡아서 필터를 적용하려고 한다. 만일, @Catch() 데코레이터에 아무 것도 안 적어주면, 모든 종류의 예외가 필터로 잡힌다고 한다.

 

ExceptionFilter는 ExecutionContext를 사용하지 않고, ArgumentsHost를 사용하는 듯하다. 뭐 사용법은 ExecutionContext와 동일하다.

 

나는 Response Mapping에 success와 data 키를 넣고, statusCode와 msg를 각각 exception 변수에서 추출해서 넣어주었다.

 

추후 해당 예외에 대한 다른 처리가 필요하면 해당 클래스 안에서 처리하면 될 것이다!

 

만든 ExceptionFilter는 app.module에 global하게 지정해두었다.

 

3. 결과!

동작을 확인하기 위해 지난 시간에 만든 예제 컨트롤러의 예제 생성 API에 바로 HttpException을 날려봤다. 요청이 들어오면 해당 예외가 발생하고, HttpException은 내가 구현한 HttpExceptionFilter에 걸려서 새로운 Response로 정제되어 결과가 날아올 것이다.

 

잘 날아온다~

 

4. 다음 시간엔?

다음 시간에는 Transaction을 처리해봐야겠다. 이걸 처리하고 난 뒤에는 Swagger OpenAPI도 적용해봐야겠다.