TIL 2024-06-11

Taesoo Kim·2024년 6월 11일

Filters

정확하게는 Exception Filters라는 내장 기능이다. 보통 어떤 요청이 컨트롤러에 도착하기 전에 필터와 파이프를 거쳐 재가공 되어 도착하는데, 파이프는 이전에 학습한대로 데이터의 재가공이라던가 암호화, 복호화를 도와주는 계층이라면, 필터는 예외처리 즉, 요청코드를 나누는 계층이라고 보면 된다.
내장된 Exception을 활용해 필요한 Expcetion들의 경우를 나누어준다.

커스텀 필터

import {

  ArgumentsHost,

  Catch,

  ExceptionFilter,

  HttpException,

} from '@nestjs/common';

import { Response, Request } from 'express';

  

@Catch(HttpException)

export class HttpExceptionFilter implements ExceptionFilter {

  catch(exception: HttpException, host: ArgumentsHost) {

    const _ctx = host.switchToHttp();

    const res = _ctx.getResponse<Response>();

    const status = exception.getStatus();

    const request = _ctx.getRequest<Request>();

  

    res.status(status).json({

      statusCode: status,

      timestamp: new Date().toISOString(),

      path: request.url,

    });

  }

}

커스텀 익셉션을 만들어서 사용할 수 있는데, ExcecptionFilter 를 상속받아 만들 수 있다. 그리고, 특히 ArgumentsHost 라는게 눈에 띄는데, 무엇인지 찬찬히 살펴보자.

ArgumentsHost

ArgumentsHost는 다양한 타입의 컨텍스트를 처리할 수 있도록 도와주는 유틸리티입니다. NestJS는 기본적으로 세 가지 종류의 컨텍스트를 지원합니다:

  1. HTTP Context: HTTP 요청과 응답을 처리하는 데 사용됩니다.
  2. RPC Context: 원격 프로시저 호출(Remote Procedure Call)을 처리하는 데 사용됩니다.
  3. WebSocket Context: WebSocket 연결을 처리하는 데 사용됩니다.

ArgumentsHost는 이 세 가지 컨텍스트 타입을 전환(switch)할 수 있는 메서드를 제공합니다.

주요 메서드

  • switchToHttp(): HTTP 컨텍스트로 전환합니다.
  • switchToRpc(): RPC 컨텍스트로 전환합니다.
  • switchToWs(): WebSocket 컨텍스트로 전환합니다.
  • getArgs(): 원래의 인자 배열을 반환합니다.
  • getArgByIndex(index: number): 인자의 특정 인덱스를 반환합니다

라고 나와있다. 내장 http 통신은 express로 이루워지는 것 같다.

그래서,

const _ctx = host.switchToHttp();

const res = _ctx.getResponse<Response>();

const status = exception.getStatus();

const request = _ctx.getRequest<Request>();

를 통해서 현재 컨택스트를 바꾸고, res의 객체를 직접 수정하고, req을 참고 할 수 있게 되는것 같다.

Logger Module

private readonly logger = new Logger();

우리가 잘 아는 그 로거! 로그가 잘 찍힌다.
요것을 좀 더 뜯어서 살펴보자면,

private readonly logger = new Logger(MyappController.name);

을 통해서 컨텍스트를 주입 할 수 있다. (그냥 로그에 어느 컨트롤러인지, 어느 서비스인지 확인 할 수 있다는 뜻)

커스텀 로깅 via 미들웨어

커스텀 로깅을 미들웨어를 통해 특정 컨트롤러에서 로깅을 찍을 수 있게 한다. 이제는 좀 지겹듯이, 이렇게 하는 이유는 당연히 결합도를 낮추고 유지보수를 용이하게 하기 위해!

import { Logger, NestMiddleware } from '@nestjs/common';

import { Request, Response, NextFunction } from 'express';

  

export class LoggingMiddleware implements NestMiddleware {

  private readonly logger = new Logger();

  use(req: Request, res: Response, next: NextFunction) {

    const { method, originalUrl } = req;

    const startTime = Date.now();

  

    res.on('finish', () => {

      const { statusCode } = res;

      const repsonseTime = Date.now() - startTime;

      this.logger.log(`${method} ${originalUrl} ${statusCode} ${repsonseTime}`);

    });

    next();

  }

}

지금 눈치챈건데 여긴 오버라이드 데코레이터가 없어도 되네??

NestMiddleware를 상속받아 주고 use 라는 함수를 오버라이드 해주면 된다. 미들웨어 특징답게 req,res 그리고 next함수를 통해 중간에 가로챌 수 있게 설계되었다.

그후에, main.ts에서

export class AppModule implements NestModule {

  configure(consumer: MiddlewareConsumer) {

    //범용적으로 적용한다면 *, 아니면 특정 컨트롤러를 적으면 됨

    consumer.apply(LoggingMiddleware).forRoutes('*');

  }

}

AppModule에서 NestModule을 받아 미들웨어를 세팅해주면 된다.

profile
뭔 생각을 해. 그냥 하는 거지 뭐

0개의 댓글