본문 바로가기
Nestjs

[NestJs] Interceptors 알아보기

by 동복이 2024. 3. 14.

Interceptor 란?

Interceptor는 메서드 실행 전 후에 추가 로직을 실행할 수 있는 미들웨어와 유사한 클래스를 말합니다.

로깅, 캐시, respone 등의 공통 태스크를 처리하며 코드 재사용성과 코드의 간결화 등을 목적으로 사용합니다.

 

Interceptor 실행 흐름

Interceptor는 Client에서 Controller의 handle가 호출되기 전과 후에 로직을 실행합니다.

filter, pipe, guard와 다르게 전처리와 후처리를 하게 됩니다.

전처리 단계에서는 주로 로깅, 권한 검사, 데이터 변환 등의 작업을 수행하며 이 단계에서 요청을 조작하거나 특정 조건에 따라 요청을 거부할 수도 있습니다.

전처리가 완료 되면 next.handle()을 호출하여 실제 라우트 핸들러를 실행합니다.

라우트 핸들러의 실행이 완료되고 반환된 값이 있을때 후처리 로직이 실행되며 후처리 단계에서는 응답 데이터를 변환하거나 추가 로깅을 수행하는 등의 작업을 합니다.

아직은 pipes, filter, guard, interceptor만 배웠기 때문에 그부분에 대한 흐름만 정의해둔것 Nestjs의 모든 동작을 표현한것은 아닙니다

 

Interceptor 사용하기

로그, 예외 매핑, 캐시 등이 기본 예제 코드로 공식 홈페이지에서 제공되지만 이번에는 respone mapping에 대해 알아보겠습니다.

 

// transform.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs'; // rxjs 라이브러리에서 Observable을 가져옴
import { map } from 'rxjs/operators'; // rxjs 라이브러리에서 map 연산자를 가져옴

// 여기서 T는 제네릭 타입으로, 어떤 타입이든 받을 수 있도록 정의
// 반환되는 데이터의 타입을 Response<T>로 정의
export interface Response<T> {
  data: T;
}

@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
  // ExecutionContext는 현재 실행 컨텍스트에 대한 정보를 제공하는 인터페이스
  // CallHandler는 핸들러 메소드를 호출하는 데 사용되는 인터페이스
  // Observable은 비동기적으로 값을 반환하는데 사용되는 인터페이스
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
    // next.handle()은 핸들러 메소드를 호출하고 반환된 결과를 Observable로 반환
    // map 연산자는 반환된 데이터를 가공하는데 사용
    // 여기서는 반환된 데이터를 { data: 반환된 데이터 }로 가공
    return next.handle().pipe(map(data => ({ data })));
  }
}

 

// app.controller.ts
import { Controller, Get, HttpException, Param, ParseIntPipe, Post, Req, SetMetadata, UseFilters, UseGuards, UseInterceptors, UsePipes } from '@nestjs/common';
import { AppService } from './app.service';
import { TransformInterceptor } from './interceptors/transform.interceptor';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('/transform-interceptor-test')
  @UseInterceptors(TransformInterceptor) // Method scope에 TransformInterceptor를 적용
  transformTest(): string {
    return 'transform test';
  }
}

// 결과
/* 
// Interceptor가 적용되지 않았을 경우

transform test

// Interceptor가 적용됬을 경우

{
  "data": "transform test"
}

*/

 

처음 interceptor에 대해 자료를 찾아봤을때 단순 응답 객체의 형태를 변환해 줄 때 사용하는 기능인 줄 알았습니다.

그런데 controller에서 client로 결과를 보낼때 interceptor를 거친다는 것은 알았지만 controller에 접근하기 전에 또 interceptor를 통과한다는 것과 그 부분에서 각각 다르게 동작하고 단순 객체 형태를 변환해 주는 것뿐만 아니라 많은 기능들이 있다는 것에 놀랐습니다.

728x90

'Nestjs' 카테고리의 다른 글

[NestJs] TypeORM 연결하기  (3) 2024.03.18
[NestJs] Middleware 알아보기  (1) 2024.03.15
[NestJs] Guards 알아보기  (0) 2024.03.13
[NestJs] Pipes 알아보기  (1) 2024.03.12
[NestJs] Exception filters 알아보기  (0) 2024.03.11