Search
moon
sun
✅

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”