기술과 산업/언어 및 프레임워크
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