JaveScript/NestJS

예외 필터

알면 알 수록 재밌다! 2024. 6. 13. 22:51

 

 

NestJS에서 필터, 미들웨어, 가드, 파이프 등 다양한 기능을 설정할 때, 인스턴스 대신 클래스를 사용하는 것이 더 좋다고 합니다.

 


1. 인스턴스 대신 클래스를 사용하는 이유

  1. 메모리 사용량 감소:
    • NestJS는 클래스를 사용하여 인스턴스를 생성할 때, 해당 클래스의 단일 인스턴스를 모듈 전체에서 재사용합니다.
    • 인스턴스를 직접 생성하면 각 요청마다 새로운 인스턴스를 생성할 수 있지만, 클래스를 사용하면 싱글톤 패턴에 따라 한 번만 인스턴스화되어 메모리 사용량이 줄어듭니다.
  2. 성능 최적화:
    • 클래스를 통해 생성된 싱글톤 인스턴스는 여러 곳에서 재사용되므로, 인스턴스 생성과 소멸의 오버헤드가 줄어들어 성능이 향상됩니다.
  3. 일관성 있는 상태 관리:
    • 싱글톤 인스턴스를 사용하면 상태를 중앙 집중적으로 관리할 수 있습니다. 이는 상태 관리와 동기화 문제를 해결하는 데 도움이 됩니다.
  4. 의존성 주입(DI):
    • NestJS는 의존성 주입 컨테이너를 사용하여 클래스 인스턴스를 관리합니다. 클래스 기반으로 주입 설정을 하면 의존성 주입이 더 쉽고 일관성 있게 관리됩니다.
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus ? exception.getStatus() : 500;

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

// 모듈에서 필터 등록 [추천]
import { Module } from '@nestjs/common';
@Module({
  providers: [HttpExceptionFilter], // 클래스 등록
})
export class AppModule {}


// 모듈에서 필터 인스턴스 등록 [비추천]
import { Module } from '@nestjs/common';
const httpExceptionFilterInstance = new HttpExceptionFilter();
@Module({
  providers: [{ provide: HttpExceptionFilter, useValue: httpExceptionFilterInstance }], // 인스턴스 등록
})
export class AppModule {}

 

NestJS에서 필터, 미들웨어, 가드, 파이프 등을 설정할 때 클래스를 사용하면 메모리 사용량을 줄이고, 성능을 최적화하며, 일관된 상태 관리와 의존성 주입을 더 쉽게 할 수 있습니다.

따라서 인스턴스 대신 클래스를 사용하는 것이 더 좋다고 합니다.

 


2. ctx

import { Catch, ExceptionFilter, ArgumentsHost, HttpException, HttpStatus } 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,
      });
  }
}

 

예외 필터에서 host.switchToHttp()를 사용하여 HTTP 요청과 응답 객체에 접근하는 예제입니다.

 

  • host.switchToHttp()를 사용하여 HTTP 컨텍스트를 가져옵니다. 이 컨텍스트에는 HTTP 요청 및 응답 객체가 포함되어 있습니다
  • ctx.getResponse<Response>()와 ctx.getRequest<Request>()를 사용하여 각각 HTTP 응답과 요청 객체를 가져옵니다.

 

@Get(':id')
findOne(@Param('id') id: string, @Req() request: Request, @Res() response: Response) {
  console.log('Request URL (using request):', request.url); // 현재 요청의 URL 출력
  return response.status(HttpStatus.OK).send(`Item ${id} found`);
}

@Post()
create(@Body() item: any, @Req() request: Request, @Res() response: Response, @ExecutionContext() context: ExecutionContext) {
  console.log('Request URL (using context):', context.switchToHttp().getRequest().url); // ExecutionContext를 사용하여 요청 URL 출력
  return response.status(HttpStatus.CREATED).json(item);
}

 

 

 

그래서 request 객체를 이용해 url에 접근하거나 context 객체로 request를 가져와서 url에 접근하거나 똑같은 방식입니다.


참고

 

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