Search

#025 #Interceptors/AOP

 인터셉터

인터셉터는 요청의 컨트롤러 요청의 전후에 추가로직을 덧붙일 수 있다. 쉽게 말해, 공통적인 에러처리는 filter로 해결을 했다면, 인터셉터는 공통적인 성공로직을 처리하기 위해 사용한다고 생각하면 된다고 한다.

 AOP란?

AOP란 관점 지향 프로그래밍으로서 각 모듈의 공통 관심사를 분리하여 따로 처리하는 프로그래밍 패러다임이다. 기존 코드 자체를 수정하지 않고 코드를 추가하여 추가 동작을 수행(Advice)한다.
Class A, B, C 를 컨트롤러라고 가정하고 각각 Users, Cats, Blog 컨트롤러가 있다고 가정해보자. 각 컨트롤러에는 공통적인 기능이 logging이 필요하다. 이러한 공통 관심사를 처리로직을 분리하여 모듈화 하는 작업이 AOP이다.

 요청의 생명주기

  위는 문서에 나와있는 내용인데, 순서는 아래와 같다.   요청 → 미들웨어 → 가드 → pre인터셉터 → 파이프 → 컨트롤러 → 서비스 → post인터셉터 → 예외처리 → 응답

 인터셉터 구현

 폴더 생성

→ 프로젝트 내부에 공통관심사 폴더를 만들고, 인터셉터폴더를 만들어서 파일을 생성하자. → src > common > interceptors

 interceptor 정의

import { CallHandler, ExecutionContext, Injectable, NestInterceptor, } from '@nestjs/common'; import { Observable, tap } from 'rxjs'; @Injectable() export class SuccessInterceptor implements NestInterceptor { intercept( context: ExecutionContext, next: CallHandler<any>, ): Observable<any> { console.log('Before...'); const now = Date.now(); return next .handle() .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`))); } }
JavaScript
복사
위는 Nest 공식 문서에 게시된 인터셉터 기본 문법이다.

 폴더 정리

전역적으로 사용하는 exceptions / interceptors / middlewares / pipescommon 이란 폴더를 만들어서 관리하자
 

 인터셉터 사용

위는 문서에 게시된 interceptor를 사용하는 방법이다.

 코드 구현

catsController 위에 UseInterceptor 데코레이터를 통해서 사용하면 된다.

 테스트 확인

포스트맨으로 요청해서 로그를 확인해보자.
이렇게 매 요청마다 전처리 후처리 작업을 하게 된다.

 ApiUtil 처럼 사용할 수 있는 인터셉터 기능

인터셉터에서 post인터셉터 부분에서 데이터형태를 일관성있게 맞추서 보내주는 설정이 가능하다. 이전 스프링 프레임워크에서 ApiUitl같은 객체를 사용해서 { statusCode: ‘’, success: ‘’, message: ‘’} 처럼 형태를 만들어서 데이터를 일관성 있게 반환해줄 수 있다.
빨간 네모박스의 응답부분을 처리하는 인터셉터에서 반환 데이터를 원하는 형태로 제공이 가능하다. Observable데이터가 반환되는 형태였지만, map 을 사용해서 응답 데이터의 형태를 가공할 수 있다.

 테스트

이렇게 다른 라우터에 요청을 해도, 응답이 성공적이라면 인터셉터에서 정의한 형태로 일관성있게 반환이 될 것이다. { “success” : true, “data” : “one cat with 213” }