nestjs interceptor(약간의 AOP..)

양진영·2023년 2월 9일
0

nestJs

목록 보기
7/10

드디어... 말로만 들었던 interceptor에 대해 공부해보는 시간을 가졌다. 컨셉은 이미 알고있었다. 뭐 중간중간 데이터를 가공하는데 쓰는거겠지 라고 대충만 알고있었는데 이 대충만 아는것이 또 문제를 일으킬것같아 조금 자세히 알아보는 시간을 가졌다.

interceptor

인터셉터는 중간에서 가로챈다는 뜻이다. 그 어원 그대로 인터셉터의 역할은 요청이 컨트롤러로 들어가기전 혹은 컨트롤러로 들어가서 return을 하고 그 리턴값이 사용자에게 전달되기전 등 프로세스 사이사이에서 값을 가공할수있게 해주는 용도로 사용된다.

사용법

common/interceptors/undefinedToNull.intecrptor.ts
import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Observable, map } from 'rxjs';

@Injectable()
export class UndefinedToNull implements NestInterceptor {
  intercept(
    context: ExecutionContext,
    next: CallHandler<any>,
  ): Observable<any> | Promise<Observable<any>> {

    return next
      .handle()
      .pipe(map((data) => (data === undefined ? null : data)));

  }
}
  • return전에 짜는 로직은 컨트롤러 가기전 로직, return 선언후는 컨트롤러 실행 이후

  • map안 data는 컨트롤러에서 return 해준값이 담길것이고 그 데이터를 한번더 가공해서 뱉을수도 있다. (참고로 여기서 쓰인 map 함수는 js에서 사용하는 map이 아닌 rxjs에서 사용하는 map 이라는 함수가 따로있다.)

위와같이 interceptor를 지정해주고 controller에서 적용하는 방법은 아래와 같다.

@ApiTags('USERS')
@UseInterceptors(UndefinedToNull)
@Controller('users')
export class UserController {
  @Inject()
  private userService: UserService;

  @ApiOperation({ summary: '회원가입' })
  @Post()
  postUsers(@Body() data: JoinRequestDto) {
    this.userService.postUsers(data);
  }
}  

위와같은 방식으로 컨트롤러 내부의 모든 기능마다 붙여줄수도 있지만 개별적으로 적용시켜 줄수도있다.

AOP
AOP(aspect oriented programming)은 모듈화의 강화를 목표로 만들어 졌다. 조금 더 자세하게 풀어보자면 하나의 컨트롤러가 요청을 받아 응답을 내기까지 일련의 과정을 거친다. 이때 요청을 받아 응답을 내는 과정에 있어 공통되는 process들이 있다면 그 process를 하나로 묶어 처리한다. 즉 이 묶어서 처리한다는 말은 모듈화를 한다는 말로, 처음으로 돌아가서 aop의 목표성을 다시 살펴 보자면 일련의 process를 모듈화 하여 진행하지만 여러 컨트롤러가 공통되는 process(모듈)을 진행하여 요청을 처리한다면, 그 공통되는 모듈을 묶어 처리한다. 이때 사용될수있는 컨셉이 interceptor이다.

근데 이거 글을 읽어보면 좀 의아 해질수도 있을것같다. 실제로 내가 의아했던 부분이었는데, 아니 뭐하러 따로 interceptor를 설정해 그냥 middleware로 하던대로 하면 되잖아? 그냥 A - B - C에서 A 와 B사이에 어떤 기능이 필요하면 그 사이에 middleware를 넣으면 되는거잖아? 라고 생각할수 있을것같다. 근데 interceptor를 사용하는 장점은 하나의 interceptor에서는 컨트롤러에 요청이 전달되기전 그리고 전달된후 return을 뱉은후 라고 하였다. 만약 middleware로 전 과 후 모두 처리하고싶다면 2개의 middleware를 만들어야 할것이다. 근데 interceptor는 하나의 interceptor안에 전후 모두 가능하고 또 개인적으로 쓰다보니 뭔가 로직의 흐름이 더 자연스럽게 느껴졌던것 같다.

profile
왜? 라는 질문을 중요시하는 서버 개발자입니다

0개의 댓글