인터셉터
- Nest.js 의 인터셉터 클래스는
@Injectable
데코레이터를 추가해야 한다.NestInterceptor
인터페이스를 상속해야 한다.
인터셉터는 Aspect Oriented Programming 기술에서 영감을 받았다.
- 메서드 실행 전 후에 추가 로직 바인딩
- 함수 결과를 변환
- 함수 예외를 변환
- 함수 동작을 확장
- 조건부 함수 완전 재정의 (ex. 캐싱 목적)
기초
- 인터셉터는
intercept()
메서드를 구현해야 한다. - 메서드엔 두개의 인자가 있다.
- 1번째 인자, ExecutionContext: 요청의 타입 정보나 호출된 컨트롤러 메서드 정보 등을 가져올 수 있다.
- ex) http 에서 헤더, 쿠키 등의 정보 그리고 컨트롤러 메서드 정보
- 이는 ArgumentsHost 를 상속한다.
- 2번째 인자,
Call handler
:handle()
메서드를 이용해 본래 호출된 메서드를 매핑할 때 사용한다.Observable
을 반환하여 RxJS 연산자로 응답을 추가 조작할 수 있다.- 객체지향에서는 이
handle()
메서드를 포인트컷이라고 한다.
- 1번째 인자, ExecutionContext: 요청의 타입 정보나 호출된 컨트롤러 메서드 정보 등을 가져올 수 있다.
예제1: 로깅
인터셉터 작성
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> {
console.log("Before...");
const now = Date.now();
return next
.handle()
.pipe(tap(() => console.log(`After... ${Date.now() - now}ms`)));
}
}
컨트롤러에 적용
@UseInterceptors(LoggingInterceptor)
export class CatsController {}
결과
Before...
After... 1ms
글로벌 적용
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new LoggingInterceptor());
// app.module.ts
import { Module } from "@nestjs/common";
import { APP_INTERCEPTOR } from "@nestjs/core";
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],
})
export class AppModule {}
예제2: 응답 매핑 (변환)
데이터를 객체 안에 넣기
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
export interface Response<T> {
data: T;
}
@Injectable()
export class TransformInterceptor<T>
implements NestInterceptor<T, Response<T>>
{
intercept(
context: ExecutionContext,
next: CallHandler
): Observable<Response<T>> {
return next.handle().pipe(map((data) => ({ data })));
}
}
{
"data": []
}
null 인 경우 공백 출력하기
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
@Injectable()
export class ExcludeNullInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(map((value) => (value === null ? "" : value)));
}
}
예제3: 예외 재정의
import {
Injectable,
NestInterceptor,
ExecutionContext,
BadGatewayException,
CallHandler,
} from "@nestjs/common";
import { Observable, throwError } from "rxjs";
import { catchError } from "rxjs/operators";
@Injectable()
export class ErrorsInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next
.handle()
.pipe(catchError((err) => throwError(() => new BadGatewayException())));
}
}
예제 4: 스트림 오버라이딩
- 호출하는 메서드를 보고 응답이 이미 연산된 결과면 캐시된 결과를 내보낼 수 있음
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from "@nestjs/common";
import { Observable, of } from "rxjs";
@Injectable()
export class CacheInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const isCached = true;
if (isCached) {
return of([]);
}
return next.handle();
}
}
예제 5: 타임아웃 구성하기
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
RequestTimeoutException,
} from "@nestjs/common";
import { Observable, throwError, TimeoutError } from "rxjs";
import { catchError, timeout } from "rxjs/operators";
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
timeout(5000),
catchError((err) => {
if (err instanceof TimeoutError) {
return throwError(() => new RequestTimeoutException());
}
return throwError(() => err);
})
);
}
}
반응형
'프레임워크 > Nest.js' 카테고리의 다른 글
Nest.js 웹소켓 (WebSockets) 이란? + 사용법 (0) | 2024.02.11 |
---|---|
Nest.js 미들웨어 (Middleware) 란? (0) | 2024.02.10 |
Nest.js 의 Class Validator 란? (0) | 2024.02.02 |
Nest.js 의 가드(Guard) 란? (0) | 2024.02.02 |
Nest.js 의 파이프(Pipes) 란? (0) | 2024.01.13 |