Nest.js 에서 Interceptor 주요 기능과 특징
1. 컨트롤러 실행 전후 로직 : Interceptor는 컨트롤러 메서드가 실행되기 전과 후에 특정 로직을 수행할 수 있다. 이를 통해 요청을 가로채거나 응답을 수정할 수 있다.
2. 응답변형 : 인터셉터를 사용하여 컨트롤러에서 반환된 응답을 변형하거나, 특정 형식으로 포멧팅할 수 있다.
3. 비동기처리: Interceptor는 RxJS 의 Observable 을 사용한다. 이를 통해 비동기 데이터 스트림을 관리하고, 효율적인 비동기 처리를 할 수 있다.
4. 로깅 및 모니터링: 요청과 응답에 대한 로깅을 수행하거나 실행시간을 측정하는 등의 모니터링 작업을 인터셉터에서 처리할 수 있다.
구현코드
일단 인터셉터를 구현하려면 NestInterceptor 를 implments 하고 사용하려는 엔드포인트에 UseInterceptor 를 하면 해당 엔드포인트에 인터셉터를 적용시킬 수 있다.
intercept 메소드를 구현해야하는데 해당 메소드는 두개의 파라미터를 받는다.
- ExecutionContext
ExecutionContext는 현재 실행되고 있는 컨텍스트에 대한 상세정보를 제공한다. 이를 통해 현재 처리되고 있는 HTTP 요청과 관련된 다양한 정보를 접근할 수 있다.
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = conext.switchToHttp().getReqest();
const response = context.switchToHttp().getResponse();
...
}
- CallHandler
CallHandler 는 NestJS 의 요청 처리 파이프라인에서 다음으로 실행될 핸들러를 나타낸다. 이 객체를 사용하여 현재 요청의 처리를 계속 진행하거나 처리과정을 변경할 수 있다.
CallHanlder는 handle 메소드는 Observable 을 반환한다. 이 Observable은 컨트롤러 메소드의 실행 결과를 나타내며, 이를 구독하고 처리하여 응답을 변경하거나 추가 로직을 실행할 수 있다.
intercept(context: ExecutionContext, next: CallHandler): Observable<any>{
return next
.handle() //다음 핸들러(컨트롤러 메서드)의 처리를 진행함
.pipe(
// 이곳에서 RxJS 연산자를 사용하여 응답을 변형하거나 추가 처리를 진행할 수 있다.
);
로그 인터셉터
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
import { Observable, map, tap } from "rxjs";
@Injectable()
export class LogginInterceptor implements NestInterceptor{
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const path = request.originalUrl;
const now = new Date();
console.log(`${path} TIME: ${now.toLocaleString('kr')}`);
return next
.handle()
.pipe(
tap((observable) => console.log(observable)),
map((observable) => ({
message: '인터셉터에서 추가한 메시지',
data: observable
}))
);
}
}
여기서 중요한 것은 CallHandler.handle() 이 실행되기 전까지는 핸들러에 도달하기 전 상태이다. handle() 이 실행되면 핸들러에 도달하고 도달하면서 컨트롤러에 선언한 기능들이 동작한다. 그 다음 응답을 보낼때는 pipe() 를 통해 처리하는데 여기서는 주로 map, tap 으로 웬만한 걸 처리할 수 있다.
map()
- map 연산자는 Observable 에서 방출된 각 값에 대해 제공된 함수를 실행하고, 그 결과를 새로운 Observable 로 변환한다.
이를 통해 응답데이터를 변환하거나 조작할 수 있다.
return next.handle().pipe(
map(data => ({
...data, //기존에 컨트롤러에서 반환한 데이터
addProperty: '추가된 응답값'
})));
tap()
- tap 연산자는 Observable 에서 방출된 각 값에 대한 부수효과를 수행한다. tap 은 데이터 자체를 변형하지 않고 로깅, 디버깅 등의 용도로만 사용한다.
return next.handle().pipe(
tap(() => console.log('응답 나가는 중'))
);
Controller
@Get('all')
@UseInterceptors(LogginInterceptor)
async allData(): Promise<string> {
return '테스트';
}
UserInterceptos 로 지정해줘야만 해당 엔드포인트에 인터셉터가 정상작동한다.
'Nest.js' 카테고리의 다른 글
Nest.js - onModuleInit, onModuleDestroy 서버 실행과 종료시 실행되는 로직 구현 (0) | 2024.04.17 |
---|---|
Jest - Cannot find module (0) | 2024.03.17 |
Nest.js - Molecular 서비스 브로커 예제 (0) | 2023.12.18 |
Nest.js - TypeORM 설정 (0) | 2023.11.26 |