기술과 산업/언어 및 프레임워크

NestJS 마스터 시리즈 10화. 미들웨어와 인터셉터 – 요청 흐름을 설계하는 법

B컷개발자 2025. 5. 5. 13:38
728x90

“NestJS에서 흐름을 다룬다는 건 미들웨어와 인터셉터를 설계한다는 뜻이다”

 

NestJS의 미들웨어와 인터셉터 개념을 설명하고, 요청 흐름을 설계하는 구조적 방식에 대해 다룹니다. 로깅, 인증, 응답 변환, 실행 시간 측정 등 실무 적용 예제를 포함합니다.

 


 

요청 흐름을 통제하는 두 가지 축

 

NestJS의 요청 흐름은 크게 두 축으로 나눌 수 있다.

계층역할예시

미들웨어 (Middleware) 요청 전 전처리 인증, 로깅, IP 차단
인터셉터 (Interceptor) 요청 전/후 중간 개입 응답 포맷 변환, 실행 시간 측정, 캐싱

이 두 계층을 적절히 활용하면, 컨트롤러 내부의 로직을 건드리지 않고도 서비스 흐름의 품질을 제어할 수 있다.

 


 

미들웨어 – Express 스타일 요청 전처리

 

NestJS는 Express 기반이기 때문에 미들웨어의 구조 역시 매우 유사하다.

 

 

기본 미들웨어 예제

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`[${req.method}] ${req.originalUrl}`);
    next();
  }
}

 

적용 방식

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';

@Module({})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*'); // 전체 라우트에 적용
  }
}

 

  • 특정 경로나 컨트롤러에만 제한적으로 적용할 수도 있다.
  • 주로 로깅, 인증 토큰 전처리, 보안 필터링 용도로 사용된다.

 


 

인터셉터 – 요청-응답 흐름의 양방향 개입

 

인터셉터는 @Injectable()로 선언하며, 요청 전, 응답 후 양방향에서 흐름을 가로챌 수 있다.

 

 

기본 인터셉터 예제

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

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const now = Date.now();
    return next.handle().pipe(
      tap(() => console.log(`Execution time: ${Date.now() - now}ms`)),
    );
  }
}

 

적용 방식

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

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: LoggingInterceptor,
    },
  ],
})
export class AppModule {}

 

 


 

실무 활용 예시

용도미들웨어인터셉터

사용자 인증 처리 O X
요청 로깅 O O (응답 포함 시 인터셉터 사용)
응답 구조 통일 X O
실행 시간 측정 X O
캐싱 처리 X O (CacheInterceptor)
다국어 응답 변환 X O

 

 


 

Nest 내장 인터셉터 활용

 

NestJS는 기본적으로 다음과 같은 유용한 인터셉터를 제공한다:

 

  • ClassSerializerInterceptor : 응답 객체를 DTO에 맞게 직렬화
  • CacheInterceptor : 캐시 자동화
  • TimeoutInterceptor : 응답 타임아웃 제한

 

이들은 대부분 @UseInterceptors() 데코레이터나 APP_INTERCEPTOR 전역 주입 방식으로 활용된다.

 


 

사용자 정의 응답 포맷 예제

return next.handle().pipe(
  map(data => ({
    success: true,
    data,
    timestamp: new Date().toISOString(),
  })),
);

 

  • 이렇게 응답 포맷을 통일해두면 클라이언트는 항상 동일한 구조를 받을 수 있어 프론트엔드 개발이 편해진다.

 


 

마무리 인사이트

 

NestJS에서 흐름을 제어하고 설계하는 방법은 두 가지다:

미들웨어로 요청 전처리, 인터셉터로 요청-응답 가공.

이 두 계층을 적절히 분리하면, 비즈니스 로직은 본연에 집중하고, 시스템 전체 흐름은 공통 계층에서 일관되게 관리할 수 있다.

 

  • 인증은 미들웨어에서
  • 응답 포맷과 성능 로깅은 인터셉터에서
  • 흐름의 구조화가 품질을 만든다

 

“흐름을 설계하지 않으면, 흐름에 끌려간다”

 


 

다음 회차 예고

 

NestJS 마스터 시리즈 11화. 파이프(Pipe) – 요청 데이터의 정제와 전처리 전략

Transform과 ValidationPipe, 커스텀 파이프 설계까지 자세히 분석합니다.

728x90