Search

250203_1525_[Nest.js] Middleware→ Enhancer (Nest.js에서 로깅을 구현할 때는 Interceptor를 사용하기)

오늘도 내가 정말 존경하는 분의 호스팅을 읽고 작성하려고 한다.

1. Middleware

Express 기반의 전통적인 방식으로, 요청 전/후 처리를 담당
next() 함수 호출을 통해 흐름 제어
인증, 로깅, 데이터 검증 등에 사용됨
Nest.js에서는 NestMiddleware 인터페이스를 구현하여 사용
import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class CustomMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log('Request...'); next(); } }
TypeScript
복사

2. Enhancer (Nest.js 고유 개념)

Middleware를 역할별로 세분화하여 최적화한 개념
Pipe, Guard, Interceptor, Exception Filter 4가지 종류가 존재
ExecutionContext, ArgumentsHost 등의 공통 인터페이스를 사용하여 다양한 Context에서 활용 가능

3. Enhancer 상세 개념

1.
Pipe
PipeTransform 인터페이스를 구현
@Body(), @Query() 등에 적용 가능
transform() 메서드를 통해 데이터 변환 및 검증 수행
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common'; @Injectable() export class ValidationPipe implements PipeTransform { transform(value: unknown, metadata: ArgumentMetadata) { return value; } }
TypeScript
복사
2.
Guard
CanActivate 인터페이스를 구현하여 인증 및 접근 제어 수행
boolean | Promise<boolean> | Observable<boolean> 값 반환
ExecutionContext 활용 가능
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class RolesGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { return true; } }
TypeScript
복사
3.
Interceptor (로깅 구현에 최적)
NestInterceptor 인터페이스를 구현하여 요청/응답 흐름을 제어
ExecutionContext, CallHandler를 사용하여 전/후 처리 가능
rxjs의 tap()을 활용하여 비동기 응답 후 처리 가능
Middleware와 달리 다양한 플랫폼(Context)에서 재사용 가능
import { CallHandler, ExecutionContext, Injectable, NestInterceptor, } from '@nestjs/common'; import { Observable, tap } from 'rxjs'; @Injectable() export class LoggingInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { console.log("before"); return next.handle().pipe( tap(() => console.log('after')) ); } }
TypeScript
복사
4.
Exception Filter
ExceptionFilter 인터페이스를 구현하여 예외 처리 담당
ArgumentsHost를 활용하여 요청 정보 획득 가능
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; import { Response, Request } from 'express'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception.getStatus(); response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: request.url, }); } }
TypeScript
복사

4. Middleware vs. Interceptor (로깅 관점)

비교 항목
Middleware
Interceptor
적용 위치
Express 기반 요청/응답 전후
Nest.js 전체 흐름에서 요청/응답 전후
실행 컨텍스트
HTTP 요청에 한정됨
WebSocket, RPC 등 다양한 Context에서 사용 가능
데이터 접근
요청 정보만 처리 가능
요청 및 응답 데이터 모두 처리 가능
RxJS 지원
(기본적으로 동기)
(비동기 스트림 처리 가능)
코드 재사용성
HTTP 전용
다중 Context에서 활용 가능

5. 결론

Middleware는 Express 기반 요청 처리에 한정됨, WebSocket, RPC 같은 환경에서는 별도 구현 필요
Interceptor는 요청과 응답을 모두 제어할 수 있고, 다양한 플랫폼(Context)에서 재사용 가능
Nest.js 공식 문서 및 Discord 커뮤니티에서도 Interceptor 사용을 권장
특히 로깅을 남길 때는 Interceptor 사용이 더 적합함
즉, Nest.js에서 로깅을 구현할 때는 Interceptor를 사용하는 것이 더 좋은 선택

안녕하세요

관련 기술 문의와 R&D 공동 연구 사업 관련 문의는 “glory@keti.re.kr”로 연락 부탁드립니다.

Hello

For technical and business inquiries, please contact me at “glory@keti.re.kr”