개발일지

Nest.JS 인터셉터

index.ys 2023. 8. 19. 23:49

인터셉터

  • 인터셉터란 요청과 응답을 중간에 가로채 변형하여 전달하는 컴포넌트
  • 요청과 응답이 라우터로 전달되거나 응답이 끝난 후에 인터셉터에서 요청과 응답을 가로채 원하는 형태로 가공하여 요청과응답을 전달함
  • 미들웨어와 수행하는 일이 비슷하지만 수행 시점에 차이가 있음 미들웨어는 요청이 라우트 핸들러로 전달되기 전에 동작함
  • 인터셉터는 라우트 핸들러의 처리 전/후 호출되어 요청과 응답을 다룰 수 있음

  • 미들웨어는 요청이 라우터 핸들러로 전달되기 전에만 바인딩 될 수 있음, 응답은 변경할 수 없음
  • 특정 미들웨어가 요청이 라우터 핸들러도 전달되기 전에 요청의 생명주기를 종료할 수 있음

인터셉터 활용

  • 메서드 실행 전/후 추가 로직을 바인딩
  • 함수에서 반환된 결과를 변환
  • 함수에서 뎐져진 예외를 변환
  • 기본 기능의 동작을 확장
  • 특정 조건에 따라 기능을 완전히 재정의 ex) 캐싱

로그 인터셉터

  • 인터셉터는 Nest에서 제공하는 NestInterceptor 인터페이스를 구현한 클래스
  • 요청이 라우터 핸들러에 전달되기 전후로 콘솔을 출력하는 인터셉터 구현

Logging-interceptor.ts

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, Inject } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
//Nest에서 제공하는 NestInterceptor 클래스
export class LoggingInterceptor implements NestInterceptor {

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
  	//요청이 라우터 핸들러에 전달되기 전 출력
    console.log('Beofore..')
    //요청을 처리한 후 출력
    const now= Date.now();
    return next.handle().pipe(tap(()=> console.log(`After...${Date.now() - now}ms`)))
  }
}

전역 인터셉터 설정

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging/logging.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
//전역으로 인터셉터를 적용
  app.useGlobalInterceptors(new LoggingInterceptor())
  await app.listen(3000);
}
bootstrap();

응답 맵핑 인터셉터

  • 응답을 객체로 감싸서 전달하는 인터셉터
  • NestInterceptor 인터페이스에서 Generic으로 T,R 타입 2개를 선언
  • 둘다 any 타입이기 때문에 어떤 타입이 와도 상관없음
  • T는 응답 스트림을 지원하는 Observable 타입 ,R은 응답의 값을 Observable로 감싼 타입을 지정
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, Inject } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';

export interface Response<T>{
	data:T
}

@Injectable()
//
export class TransFormInterceptor<T> implements NestInterceptor<T, Response<T> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      return next
      .handle()
      .pipe(map(data  => {
        return { data }
      }))
  }
}

main.ts

  • 전역 인터셉터에 추가
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor , TransformInterceptor} from './logging/logging.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
//전역으로 인터셉터를 적용, 변형 인터셉터 추가
  app.useGlobalInterceptors(new LoggingInterceptor(),new TransformInterceptor())
  await app.listen(3000);
}
bootstrap();