AOP(Aspect Oriented Programming) 영감을 받았다.
그림설명
핵심기능 3가지가 있고 핵심 기능이 각각의 컨트롤러라고 생각해보자.
각각의 컨트롤러는 저마다 수행하는 기능이 있지만 공통적으로 수행하는 기능도 존재한다.
예를 들어 클라이언트가 서버에게 어떤 요청을 보냈는지에 대한 정보를 출력하는 Logging기능이 각 컨트롤러에 공통적으로 존재controller 가 시작하기 전과 끝났을 때 나눠서 코딩을 할 수 있는것이다.
실패했을 때 에러를 exception filter 로 만들고
전체모듈에서 공통적으로 사용 가능하기 때문에
commom > interceptors > successInterceptor.ts 폴더 정리하기.
nestJS-공식문서내용 붙여넣기
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> {
// (1)
console.log('Before...');
const now = Date.now();
return next.handle()
.pipe(
tap(() => console.log(`After... ${Date.now() -now}ms`)),
);
// (2) Exception filter 처럼 성공시 데이터가 success: true가 포함되게하자.
return next.handle()
.pipe(map((data) => ({ success: true, data,})),);
}
}
- rxjs 형식에서 return next.handle().pipe(map((data) => ())
map을 통해 data를 인자로 받고 응답을 해주는 로직이다.map은 rxjs에서 나온것인데 nest와 별개 라이브러리이고
nest에서 사용할 때는 형식이 정해져 있다. data는 response의 인자를 받는것이다.
controller가 먼저 실행 되기때문에 controller에서 return 한 값을 받는것이다.
사용하기 위해 의존성 주입하기 catsController.ts
@Controller('cat')
@UseInterceptors(SuccessInterceptor) // 사용 할곳에 인폴트하기
@UseFilters(HttpExceptionFilter) // exception filter와 비슷하게 사용한다.
export class UserController {
사용할 곳에 console.log를 찍어보자! catsService.ts
// (1)
// @Get()
// getAllCat() {
// console.log('hi controller')
// return 'get all cats'
// }
// (2)
@Get()
getAllCat() {
console.log('hi controller')
// 실제 restAPI 처럼 키벨류 형식으로 작성하기.
return {'cat': 'get all cats'}
}
---------------------------------
- postman 에 GET http://localhost:3000/cats 보내기
// (1)
get all cats (postman 응답 시)
console.log 찍힌것
// Before...
// hi controller
// After
- 해당 클래스에 @UseInterceptors(SuccessInterceptor) 를 의존성 주입을 했다.
@Get() 해당 함수에 요청을 보내면 console.log('hi controller') 이 찍힌다.
인터셉터를 보면 Before...는 와 After...가 있는데
Before는 pre-controller 로 controller 시작전에 실행하는것이고
After는 post-request 로 controller 후에 실행하는 인터셉터이다.
이렇게 공통된것을 AOP(Aspect Oriented Programming) 시각으로 모듈화를 시킨것이다.
// (2)
{
"success": true,
"dat": { "cat": "get all cats"}
}
- 이렇게 하면 데이터 형식을 유지하면서 프론트한테 보내줄 수 있다.
프론트에서는 success를 기준으로 성공,실패 어떤 응답인지 구분하기 쉬워진다.
- 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를 거쳐
guards 거쳐
interceptors(pre-controller)를 거쳐
pipes 거친 파라미터 결과값이
controller에서 사용되고
service에서 데이터가 사용이되고
interceptor (post-request) 거친다.
여기서 쭉 오다가 exception이 발생되면 Exception filters 로 나가게 된다.
그리고 사용자에게 response를 넘겨주게 된다.
유익한 정보를 제공해주셔서 감사합니다.