개발일지
Nest.JS 인터셉터
index.ys
2023. 8. 19. 23:49
인터셉터
- 인터셉터란 요청과 응답을 중간에 가로채 변형하여 전달하는 컴포넌트
- 요청과 응답이 라우터로 전달되거나 응답이 끝난 후에 인터셉터에서 요청과 응답을 가로채 원하는 형태로 가공하여 요청과응답을 전달함
- 미들웨어와 수행하는 일이 비슷하지만 수행 시점에 차이가 있음 미들웨어는 요청이 라우트 핸들러로 전달되기 전에 동작함
- 인터셉터는 라우트 핸들러의 처리 전/후 호출되어 요청과 응답을 다룰 수 있음
- 미들웨어는 요청이 라우터 핸들러로 전달되기 전에만 바인딩 될 수 있음, 응답은 변경할 수 없음
- 특정 미들웨어가 요청이 라우터 핸들러도 전달되기 전에 요청의 생명주기를 종료할 수 있음
인터셉터 활용
- 메서드 실행 전/후 추가 로직을 바인딩
- 함수에서 반환된 결과를 변환
- 함수에서 뎐져진 예외를 변환
- 기본 기능의 동작을 확장
- 특정 조건에 따라 기능을 완전히 재정의 ex) 캐싱
로그 인터셉터
- 인터셉터는 Nest에서 제공하는 NestInterceptor 인터페이스를 구현한 클래스
- 요청이 라우터 핸들러에 전달되기 전후로 콘솔을 출력하는 인터셉터 구현
Logging-interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, Inject } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
//Nest에서 제공하는 NestInterceptor 클래스
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
//요청이 라우터 핸들러에 전달되기 전 출력
console.log('Beofore..')
//요청을 처리한 후 출력
const now= Date.now();
return next.handle().pipe(tap(()=> console.log(`After...${Date.now() - now}ms`)))
}
}
전역 인터셉터 설정
main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging/logging.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
//전역으로 인터셉터를 적용
app.useGlobalInterceptors(new LoggingInterceptor())
await app.listen(3000);
}
bootstrap();
응답 맵핑 인터셉터
- 응답을 객체로 감싸서 전달하는 인터셉터
- NestInterceptor 인터페이스에서 Generic으로 T,R 타입 2개를 선언
- 둘다 any 타입이기 때문에 어떤 타입이 와도 상관없음
- T는 응답 스트림을 지원하는 Observable 타입 ,R은 응답의 값을 Observable로 감싼 타입을 지정
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, Inject } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map, tap } 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<any> {
return next
.handle()
.pipe(map(data => {
return { data }
}))
}
}
main.ts
- 전역 인터셉터에 추가
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor , TransformInterceptor} from './logging/logging.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
//전역으로 인터셉터를 적용, 변형 인터셉터 추가
app.useGlobalInterceptors(new LoggingInterceptor(),new TransformInterceptor())
await app.listen(3000);
}
bootstrap();