•
오늘도 내가 정말 존경하는 분의 호스팅을 읽고 작성하려고 한다.
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”