interceptor
https://docs.nestjs.com/interceptors
interceptor 의 조건
다음 조건을 만족하는 클래스이다.
@Injectable()
로 데코레이터 돼있다.NestInterceptor
인터페이스를 구현한다.
Interceptors's AOP technique
Interceptors 는 Aspect Oriented Programming 에 영감을 받았다.
- 메서드 실행 전후로 추가적인로직을 바인드 할 수 있다.
- 함수로부터 반환된 결과를 변형할 수 있다.
- 함수로부터 던져진 예외를 변형할 수 있다.
- 기본 함수의 행위를 확장할 수 있다.
- 특정 조건에 의존하고 있는 함수를 완전히 override 할 수 있다. (e.g., for caching purposes)
#
Basics- interceptor 는
intercept()
를 구현한다.
#
ExecutionContext- ArgumentsHost 를 확장하며, 새로운 헬퍼 메서드를 가진다.
- 현재 실행 프로세스의 세부정보를 가진다.
- Controller, Methods, Execution Contexts 에서 광범위하게 작동할수 있는 generic 한 interceptors 를 만들 수 있다.
- 현재 실행 프로세스의 세부정보를 가진다.
#
Call handlerCallHandler
인터페이스는handle()
을 구현한다.handle()
는 Interceptor 에서 원하는 시점에, Route Handler 메서드를 호출할 수 있게 해준다.handle()
을 구현하지 않으면, Route Handler 메서드는 실행되지 않는다.
intercept()
메서드는 효율적으로 Request/Response 스트림을 래핑한다.그 결과, 마지막 route handler 의 실행 전후에 커스텀 로직을 구현할 수 있다.
handle()
이 호출되기 전에 실행되는interceptor()
메서드에, 코드를 작성할 수 있다.handle()
메서드는Observable
을 반환하기 때문에, 강력한RxJS
연산자를 이용하여 Response 를 추가적으로 조작할 수 있다.Aspect Oriented Programming 기술을 사용하자면,
Pointcut
→ Route Handler 의 호출(handle() 을 호출하는것)- 추가적인 로직이 삽입되는 지점을 의미한다.
예를들어,
POST/cats
요청에서, CatsController 컨트롤러 내부에 create() 핸들러를 목적으로 했을 때,- handle() 을 호출하지 않는 interceptor 가 호출되었을 때, create() 는 실행되지 않는다.
#
Aspect interceptionlogging.interceptor.ts :: storing user calls, asynchronously dispatching events or calculating a timestamp
NestInterceptor<T, R>
T
Observable<T>
의 타입,- response 스트림을 서포트 한다.
R
Observable<R>
에 의해 래핑된 값의 타입
note
Interceptor 는
- controllers, providers, guards 등과 같이, 생성자에서 주입될 수 있다.
- handle() 는 RxJS Observable 을 리턴한다
- RxJS 으로, stream 을 조작할 수 있는 많은 연산자를 가진다.
tap()
- observable stream 이 정상적으로 종료되거나, 예외적으로 종료될 때 익명로깅을 호출한다.
- 그렇지 않는 경우에도 Response 사이클에 방해되지 않는다.
#
Binding interceptorscats.controllers.ts:: 프레임워크에게 초기화와 생성자 주입의 책임을 넘긴다.
interceptor 의 scope
- controller-scoped
- method-scoped
- global-scoped
cats.controller.ts
전역 Interceptor 바인딩::모듈밖에 있기 때문에 의존성주입을 할 수 없다.
app.module.ts::모듈을 사용하여 전역 Interceptor 사용하기
#
Response mapping- handle() 은 Observable 을 반환하고, stream 에는 route handler 에서 반환된 값이 포함되어 있으므로,
- RxJS 의
map()
연산자를 사용하여 쉽게 변경할 수 있다.
transform.interceptor.ts
tip
async intercept(...) 비동기 메서드로 선언할 수 있다.
transform each occurrence of a null value to an empty string ''
#
Exception mappingerrors.interceptor.ts :: RxJS's catchError() - override thrown exceptions
#
Stream overridingcache.interceptor.ts
핸들러의 호출을 막고 different Value 를 반환하고 싶은 경우
- 응답속도 향상을 위한 cache 구현
- 일반적인 방법으로 구현하고 싶다면,
Reflector
와 커스텀 데코레이터로 구현할 수 있다.
#
More Operatorstimeout.interceptor.ts :: handle timeouts on route requests