본문 바로가기

node.js

Nest.js - 예외 필터

예외 필터

Nest에는 애플리케이션 전체에서 처리되지 않은 모든 예외를 처리하는 예외 레이어 가 내장되어 있습니다. 애플리케이션 코드에서 예외를 처리하지 않으면 이 계층에서 예외를 포착한 다음 자동으로 적절한 사용자 친화적인 응답을 보냅니다.

 

표준 예외 던지기 

Nest는 패키지 HttpException에서 노출되는 내장 클래스를 제공합니다. @nestjs/common일반적인 HTTP REST/GraphQL API 기반 응용 프로그램의 경우 특정 오류 조건이 발생할 때 표준 HTTP 응답 개체를 보내는 것이 가장 좋습니다.

 

예를 들어, CatsController에는 findAll()메소드( GET라우트 핸들러)가 있습니다. 이 라우트 핸들러가 어떤 이유로 예외를 던졌다고 가정해 봅시다. 이를 시연하기 위해 다음과 같이 하드 코딩합니다.

 

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

클라이언트가 이 끝점을 호출할 때 응답은 다음과 같습니다.

 

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

HttpException생성자는 응답을 결정하는 두 개의 필수 인수를 취합니다 .

  • response인수는 JSON 응답 본문을 정의합니다 . string 또는 object아래에 설명된 대로 일 수 있습니다 .
  • status인수는 HTTP 상태 코드를 정의합니다 .

기본적으로 JSON 응답 본문에는 두 가지 속성이 포함됩니다.

  • statusCodestatus: 기본값은 인수 에 제공된 HTTP 상태 코드입니다.
  • message: HTTP 오류에 대한 간략한 설명status

JSON 응답 본문의 메시지 부분만 재정의하려면 response인수에 문자열을 제공합니다. 전체 JSON 응답 본문을 재정의하려면 response인수에 개체를 전달합니다. Nest는 객체를 직렬화하고 JSON 응답 본문으로 반환합니다.

두 번째 생성자 인수 - status-는 유효한 HTTP 상태 코드여야 합니다. 모범 사례는 에서 HttpStatus가져온 열거형 을 사용하는 것 @nestjs/common입니다.

다음은 전체 응답 본문을 재정의하는 예입니다.

@Get()
async findAll() {
  throw new HttpException({
    status: HttpStatus.FORBIDDEN,
    error: 'This is a custom message',
  }, HttpStatus.FORBIDDEN);
}

위를 사용하면 응답이 다음과 같이 표시됩니다.

{
  "status": 403,
  "error": "This is a custom message"
}

사용자 정의 예외 

대부분의 경우 사용자 지정 예외를 작성할 필요가 없으며 다음 섹션에 설명된 대로 기본 제공 Nest HTTP 예외를 사용할 수 있습니다. 사용자 지정 예외를 만들어야 하는 경우 사용자 지정 예외가 기본 클래스 에서 상속되는 고유한 예외 계층 을 만드는 것이 좋습니다.HttpException이 접근 방식을 사용하면 Nest가 예외를 인식하고 자동으로 오류 응답을 처리합니다. 이러한 사용자 정의 예외를 구현해 보겠습니다.

 
export class ForbiddenException extends HttpException {
  constructor() {
    super('Forbidden', HttpStatus.FORBIDDEN);
  }
}

ForbiddenExceptionextends base 이므로 HttpException내장 예외 처리기와 원활하게 작동하므로 findAll()메서드 내에서 사용할 수 있습니다.

 
@Get()
async findAll() {
  throw new ForbiddenException();
}

 

예외 필터 

기본(내장) 예외 필터가 자동으로 많은 경우를 처리할 수 있지만 예외 레이어를 완전히 제어 할 수 있습니다. 예를 들어, 일부 동적 요소를 기반으로 로깅을 추가하거나 다른 JSON 스키마를 사용할 수 있습니다. 예외 필터 는 정확히 이러한 목적을 위해 설계되었습니다. 이를 통해 정확한 제어 흐름과 클라이언트로 다시 전송되는 응답 내용을 제어할 수 있습니다.

 

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();
    const error = exception.getResponse() as
      | string
      | { error: string; statusCode: number; message: string | string[] };

    if (typeof error === 'string') {
      response.status(status).json({
        success: false,
        timestamp: new Date().toISOString(),
        path: request.url,
        error,
      });
    } else {
      response.status(status).json({
        success: false,
        timestamp: new Date().toISOString(),
        ...error,
      });
    }
  }
}

예외 필터를 만들고 

 

 // cats/
  @Get()
  @UseFilters
  getAllCat() {
    console.log('hello controller');
    return { cats: 'get all cat api' };
  }

@UseFilter를 사용해 사용할 수 있다.

 

만약 글로벌하게 filter를 사용하고 싶다면

 

import { HttpExceptionFilter } from 'src/common/exceptions/http-exception.filter';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

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

main.ts로 가서app.useGlobalFilters(new HttpExceptionFilter());  처럼 필터를 등록해주면 된다.

 

 

'node.js' 카테고리의 다른 글

Nest.js - 인터셉터  (0) 2022.08.20
Nest.js - pipes  (0) 2022.08.20
Nest.js - 미들웨어  (0) 2022.08.20
Nest.js - 모듈  (0) 2022.08.20
Nest.js - Providers  (0) 2022.08.20