NestJS Interceptor 개발 - Global

 Interceptors의 공식 설명 : https://docs.nestjs.com/interceptors


인터셉터(Interceptors)는 Client와 Server사이에 요청과 응답을 가로채서 조작을 한후 기존 데이터 흐름을 유지하는 개념이다.


사진1) 기존 통신방법

기존은 서버와 클라이언트가 서로 통신을 그대로 한다.


사진2) Interceptors가 추가된 통신

그런데 요청, 응답값에 항상 일정한 데이터를 추가하거나 규격을 만들려고 할때 인터셉터를 사용하는 것이 편리하다. 코드마다 응답값을 추가하는 것이 아니라 Interceptors에서 작성해서 일괄적으로 적용하는 것이다.


사진3) 기존 응답

NestJS의 프로젝트를 생성하고 가장 먼저 나오는 API는 '/' 루트의 GET 요청이다. 해당 요청은 NestJS에서 프로젝트 생성시 자동으로 만들어 진다. 기존의 응답은 "Hello World!"의 String만 응답한다.


하지만 응답방법을 변경할려고 한다.


// src/common/interceptor/response.interceptor.ts

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

export interface Response<T> {
  data: T;
}

@Injectable()
export class ResponseInterceptor<T> implements NestInterceptor<T, Response<T>> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {

    const dateTime: Date = new Date(); // 날짜 데이터를 생성(UTC)

    return next.handle().pipe(
      // 파이프에서 해당 데이터를 추출후 응답값을 수정한다.
      map((data) => ({
        data, // data의 키값에 응답값을 저장
        dateTime // 생성한 날짜데이터를 저장
      }))
    )

  }
}


위 파일을 작성하고 모든 controller에 적용하기 위해서 main.ts파일을 수정해야 한다.


// src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { ResponseInterceptor } from './common/interceptor/response.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Swagger Document를 설정
  const options = new DocumentBuilder()
    .setTitle('nest API')
    .setVersion('1.0')
    .build();

  // Swagger Document의 문서를 api(/api-docs)로 설정할수 있게 셋팅
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('api-docs', app, document);

  // 모든 응답값이 적용되도록 설정
  app.useGlobalInterceptors(new ResponseInterceptor());


  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();


해당 main.ts을 수정시 응답값은 모두 "ResponseInterceptor'를 통과해서 응답하게 된다.


사진4) Interceptor를 거친 응답값

사진3과 사진4를 비교할때 기존에는 data값만 응답했지만 Interceptor를 거친 응답값은 가공된 것을 확인할수 있다.

댓글

이 블로그의 인기 게시물

Lesson 12_1 프로퍼티 노드(Property Node)

DAQ로 전압 측정하기-2

Lesson 12_2 참조를 이용한 프로퍼티노드(Property Node)