Interceptors
@Injectable 데코레이터가 달려서 의존성 주입이 가능했음.
AOP에서 영향을 받은거라고 함.
AOP(Aspect Oriented Programming) : 관점 지향 프로그래밍
이게 뭐냐…

만약 어떤 프로그램에 4개의 기능이 있다고 친다.
그러면 그 4개의 기능 하나당 모듈이 하나씩이라고 생각해보자.
그러나 그 4개의 모듈을 아우르는 공통된 기능이 필요할 수 있다. (가장 대표적으로 logging)
우리는 지난시간에 middleware를 통해서 logging을 구현한바 있다.
그러나 Interceptor를 통해서도 그런 공통된 기능을 구현할 수 있다는 것이 요지이다.
Request LifeCycle
Incoming request
Globally bound middleware
Module bound middleware
Global guards
Controller guards
Route guards
Global interceptors (pre-controller)
Controller interceptors (pre-controller)
Route interceptors (pre-controller)
Global pipes
Controller pipes
Route pipes
Route parameter pipes
Controller (method handler)
Service (if exists)
Route interceptor (post-request)
Controller interceptor (post-request)
Global interceptor (post-request)
Exception filters (route, then controller, then global)
Server response
위와 같은데
- Request가 오면
- Middleware를 타고
- guard를 탄다고 하고
- 그다음이 Interceptors 이다. (precontroller)
그리고
- pipes
- Controller
- Service
- 다시 Interceptors (post intercept)
- Filter
- Respose (최종)
이런 순서임을 알 수 있다.
그러면 구현해보자
지난번에 실패했을 때 전용 Filter를 만들었으니 이번에는 성공했을 때 전용 Logger를 만들어보자
success.intercepters.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class SuccessInterceptor 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`)),
);
}
}
이렇게 올려두고
cats.controllers.ts 에서
@Controller('cats')
@UseInterceptors(SuccessInterceptor)
위와 같이 설정해주면
Before After를 가져오게 된다.
다음과 같이 코딩하면..
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
@Injectable()
export class SuccessInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
return next.handle().pipe(map((data) => ({
success: true,
data,
})));
}
}
응답하는 데이터를 감싸서 success:true와 함께 보낼 수 있게 된다.
그렇게 되면 성공시에는 무조건 success:true를 넣어서 보내는 공통 로직이 구현이 되는 것이다.
너무 복잡하게 생각하지 말고 일단 형식만 볼 것.