프로그래밍/Nest.js

Nest.js의 인터셉터: 요청과 응답을 최적화하는 강력한 도구

shimdh 2025. 3. 20. 14:40
728x90

Nest.js는 현대적인 웹 애플리케이션 개발을 위한 강력한 프레임워크로, 다양한 기능을 제공하여 개발자들이 효율적으로 작업할 수 있도록 돕습니다. 그 중에서도 인터셉터(Interceptors)는 요청과 응답 사이에서 특정 로직을 처리할 수 있는 중요한 구성 요소입니다. 이번 포스트에서는 인터셉터의 역할, 사용법, 그리고 실용적인 예제에 대해 자세히 알아보겠습니다.

인터셉터의 역할

인터셉터는 클라이언트의 요청이 컨트롤러에 도달하기 전에 또는 서버의 응답이 클라이언트에게 전송되기 전에 실행됩니다. 이를 통해 다음과 같은 기능을 수행할 수 있습니다.

  1. 요청 변환

    • 클라이언트가 보낸 요청 데이터를 수정하거나 추가 정보를 삽입할 수 있습니다.
    • 예: 인증 토큰을 요청 헤더에 추가하거나, 요청 본문에 특정 필드를 추가하여 서버가 필요한 정보를 쉽게 처리할 수 있도록 합니다.
  2. 응답 변환

    • 서버에서 반환하는 응답 데이터를 가공하여 클라이언트에게 필요한 형식으로 제공합니다.
    • 이를 통해 클라이언트는 일관된 형식의 데이터를 받을 수 있으며, 데이터의 구조를 통일시켜 클라이언트 측의 처리 과정을 단순화할 수 있습니다.
  3. 로깅

    • 요청 및 응답 시간을 기록하거나 특정 데이터 포인트를 추적하여 성능 모니터링에 활용할 수 있습니다.
    • 예: 각 요청의 처리 시간을 기록하여 성능 병목 현상을 식별하고, 이를 통해 애플리케이션의 성능을 최적화할 수 있습니다.
  4. 예외 처리

    • 예외 상황 발생 시 적절한 처리를 수행하여 사용자에게 더 나은 경험을 제공합니다.
    • 예: 특정 오류가 발생했을 때 사용자에게 친절한 오류 메시지를 반환하거나, 오류 로그를 기록하여 개발자가 문제를 쉽게 파악할 수 있도록 돕습니다.

인터셉터 사용법

인터셉터를 사용하려면 다음과 같은 단계를 따릅니다:

  1. 인터셉터 클래스 생성

    • NestInterceptor 인터페이스를 구현하는 클래스를 작성합니다. 이 클래스는 요청과 응답을 가로채고, 필요한 로직을 추가하는 역할을 합니다.
    import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
    import { Observable } from 'rxjs';
    import { map } from 'rxjs/operators';
    
    @Injectable()
    export class TransformInterceptor implements NestInterceptor {
        intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
            const request = context.switchToHttp().getRequest();
            console.log('Before...');
    
            return next.handle().pipe(
                map(data => {
                    console.log('After...');
                    return {
                        data,
                        timestamp: new Date().toISOString(),
                    };
                }),
            );
        }
    }
  2. 인터셉터 등록

    • 작성한 인터셉터는 글로벌 또는 모듈 레벨에서 등록할 수 있습니다. 글로벌 등록을 통해 애플리케이션 전역에서 사용할 수 있으며, 특정 컨트롤러에만 적용할 수도 있습니다.

    • 글로벌 등록:

      import { Module } from '@nestjs/common';
      import { APP_INTERCEPTOR } from '@nestjs/core';
      

    @Module({

    providers: [
        {
            provide: APP_INTERCEPTOR,
            useClass: TransformInterceptor,
        },
    ],

    })
    export class AppModule {}

    
    - **특정 컨트롤러에만 적용**:
    ```typescript
    import { Controller, Get, UseInterceptors } from '@nestjs/common';
    
    @Controller('cats')
    @UseInterceptors(TransformInterceptor)
    export class CatsController {
        @Get()
        findAll() {
            return [{ name: 'Tom' }, { name: 'Jerry' }];
        }
    }
  3. 테스트 및 검증

    • 이제 서버를 실행하고 /cats 엔드포인트에 GET 요청을 보내보세요. 로그 메시지가 출력되고 결과가 변형된 것을 확인할 수 있을 것입니다. 이 과정에서 요청과 응답의 흐름을 명확히 이해할 수 있습니다.
    Before...
    After...
    Response:
    {
        "data": [{ "name": "Tom" }, { "name": "Jerry" }],
        "timestamp": "2023-10-01T12:00:00Z"
    }

실용적인 예제

  • API 응답 표준화

    • 여러 API 엔드포인트에서 동일한 형태의 응답 구조를 유지해야 할 때 유용합니다. 이를 통해 클라이언트는 다양한 API 호출에 대해 일관된 방식으로 데이터를 처리할 수 있습니다.
  • 성능 분석 도구 통합

    • 각 요청의 시작 시간과 끝 시간을 기록해 성능 문제를 진단하는 데 사용할 수 있습니다. 이러한 데이터는 성능 최적화의 기초 자료로 활용될 수 있습니다.
  • 데이터 캐싱 구현

    • 자주 사용하는 데이터는 캐시하여 반복된 데이터베이스 호출 횟수를 줄이는 데 도움을 줍니다. 이를 통해 서버의 부하를 줄이고, 응답 속도를 향상시킬 수 있습니다.

결론

인터셉터는 Nest.js 애플리케이션 내에서 다양한 공통 작업을 효율적으로 관리하고 최적화하는 데 매우 유용한 도구입니다. 이러한 기능들을 통해 개발자는 더욱 깔끔하고 유지보수하기 쉬운 코드를 작성할 수 있게 되며, 애플리케이션의 전반적인 품질을 높일 수 있습니다. 인터셉터를 적절히 활용하여 여러분의 Nest.js 애플리케이션을 한층 더 발전시켜 보세요.

728x90