NestJs 스터디(5)

연꽃·2022년 2월 20일
0

NestJs

목록 보기
5/7
post-thumbnail

예외필터(Exception filters)

🏀 예외필터란?

  • 개발을 하는데 있어서 예외처리는 매우 중요한 작업이다.
  • Nest에는 애플리케이션에서 처리되지 않은 예외를 처리해주는 예외 계층이 있다. 덕분에 예외가 처리되지 않더라도 요청-응답 사이클이 망가지지 않으며, Nest가 발생한 예외를 처리하고 사용자 친화적인 방식의 응답으로 바꾸어 클라이언트에게 전송해준다.
  • 이런 일을 해주는 계층은 Nest에 내장된 전역 예외 필터이다.

🏀 표준 예외 발생

  • Nest는 @nestjs/common 패키지를 통해 HttpException 클래스를 제공한다.
  • 이를 사용하는 것은 HTTP REST/GraphQL API 애플리케이션에서는 일어나는 각종 오류 상황을 표준 HTTP 응답으로 처리하기 좋은 방법이다.

아래의 예시를 살펴보자

import { HttpException, HttpStatus } from '@nestjs/common';

@Get()
async findAll() {
  throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}

위 예시는 Get요청에서 임의로 예외를 발생 시킨 상황이다.

  • HttpException의 생성자는 response, status라는 두 가지 인수를 받는다.
  • 먼저 response는 JSON 응답의 내용으로 string 타입 또는 object 타입일 수 있으며, JSON 응답의 message만 바꾸려면 string 타입의 문자열을 생성자의 response 인수로 전달거나 JSON 응답 객체 전체를 통째로 바꾸고 싶다면 object 타입의 객체를 response 인수로 전달합니다.
  • status는 응답할 상태코드로서 @nestjs/common 패키지에 있는 HttpStatus 열거형을 사용하면 쉽게 입력할 수 있다. 추가적으로 여기서 사용한 HttpStatus 열거형은 @nestjs/common 패키지에 있는 헬퍼 열거형이며 컴파일 시, 404이나 500 등의 응답 코드 숫자로 대치되므로, 열거형의 도움 없이 숫자를 직접 입력해도 된다고 한다.

위 작업에 대한 응답은 다음과 같다.

{
  "statusCode": 403,
  "message": "Forbidden"
}

JSON 응답은 statusCode(HTTP 상태 코드, 생성자의 status 인자로 전달된 HTTP 상태코드)와 message(status 인자에 기반한 HTTP 에러의 설명 문자열)라는 두 가지 프로퍼티를 갖는다.

🏀 기본 제공되는 표준 HTTP 예외

  • Nest는 HttpException에서 파생된 각종 표준 HTTP 예외 클래스를 내장하고 있으며, @nestjs/common 패키지에서 가져올 수 있다.
  • 이는 매우 많기 때문에 필요한 경우 공식문서를 참조해 보자^^

🏀 커스텀 예외 필터

  • 만약 예외 처리 필터를 완전히 커스텀하고 마음대로 제어하고 싶다면 커스텀 예외 필터를 직접 정의해서 등록할 수 있다.
  • 기본 예외 필터를 대체해서 예외에 대한 로그 기능을 추가할 수도 있고 예외에 따른 JSON 응답의 형태를 바꾸고 동적인 요소를 넣고 싶다거나 하는 등의 일이 가능해진다.
  • 예외 필터를 구현하려면 ExceptionFilter를 구현하는 클래스를 정의한다. 해당 인터페이스에는 catch() 메서드만 정의되어있다. 첫 번째 인자는 발생한 예외 객체이며, 두 번째 인자는 후술할 ArgumentsHost 객체다.
// http-exception.filter.ts

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,
      });
  }
}

위 예제는 HttpException 예외 발생 시에 적용되는 커스텀 응답 로직을 구현한다고 하는데 아직은 공부와 실전연습이 좀 필요해 보인다.

🏀 필터 등록

  • 필터를 등록은 크게 3가지 즉, 핸들러 메서드 수준, 컨트롤러 수준, 전역으로 등록할 수 있다.

핸들러 메서드 수준

@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}

컨트롤러 수준

@UseFilters(new HttpExceptionFilter())
export class CatsController {}

전역으로

// main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

참고: 네스트 공식문서

profile
우물에서 자라나는 중

0개의 댓글