본문 바로가기

NestJS

[NestJS] request lifeCycle 정리

개요

  • NestJS 를 사용해왔는데 라이프사이클을 까먹은것 같다.
  • 내 기억 저장소로 라이프사이클에 대해서 정리하려고 한다.

기본 개념들

  • Middleware
    • 클라이언트의 요청을 처리하기 전에 수행되는 컴포넌트
    • 사용 방식은 express 의 middleware와 동일.
  • Guard
    • 요청을 다음 단계로 진행할지 말지 결정해 주는 클래스
    • 주로 인증, 인가를 위해 사용한다.
    • 미들웨어에서도 인증과 인가처리를 할 수 있지만, 미들웨어는 실행 컨텍스트에 접근하지 못하기 때문에 다음에 어떤 핸들러가 실행될지 알 수 없고 가드는 실행 컨텍스트 인스턴스에 접근할 수 있어 다음에 실행될 작업을 정확히 알고 있다.
  • Interceptor
    • 아래와 같은 기능을 사용할 수 있다.
      • 메소드 실행 전/후에 추가 로직 바인딩
      • 함수에서 반환 된 결과를 변환
      • 함수에서 발생 된 예외 변환
      • 기본 기능 확장
      • 특정 조건에 따라 기능을 완전히 재정의
    • 기본적으로 인터셉터를 사용하여 사용자 상호 작용을 기록한다.
  • pipe
    • 파이프는 @Injectable() 데코레이터로 주석이 달린 클래스를 의미한다.
    • data 변환과 검증을 위해 사용
    • 메소드가 호출되기 직전에 파이프를 삽입하고 파이프는 메소드로 향하는 인수를 수신하고 이에 대해 작동
    • 파이프 사용 방법
      • Handler level Pipe: @UsePipes 데코레이터를 이용해서 사용. 이 파이프는 모든 파라미터에 적용된다.
      • Parameter Level Pipe: 특정 파라미터에만 적용이 되는 파이프
      • Global level Pipe: 클라이언트에서 들어오는 모든 요청에 적용. 가장 상단 영역 main.ts 에 넣어준다.
  • Exception filter
    • 예외처리 할 때 사용하는 클래스
    • 프로그래밍을 하다 보면 항상 예외처리를 해줘야하는데 중복되는 예외처리가 많고 이를 모든 코드에 넣을 수 없기 떄문에 따로 분리해서 사용한다.
    • try/catch 로도 잡지 못한 예외가 발생하면 나머지 lifecycle 이 무시되고 필터로 바로 건너뛴다.
    • filter도 각 함수마다 적용할 수 있고, 컨트롤러 위에도 적용 가능하다 (@UseFilters), 전역에서 또한 사용 가능하다.(app.useGlobalFilters())

Request lifecycle

NestJS Request Lifecycle

(출처: https://hotovo.com/2021/06/30/inside-nestjs-project/)

Express로 로직을 개발하면 사용자의 권한에 따른 처리를 미들웨어에서 하는 경우가 잦다. 근데 NestJS 에서는 가드라는 생명주기에서 따로 처리하는 이유는 무엇인가

미들웨어는 본질적으로 똑똑하지 못합니다. 미들웨어는 next() 함수가 호출된 뒤 어떤 핸들러가 실행되는지 모르기 때문입니다. 반면, 가드는 ExecutionContext 객체에 접근할 수 있기 때문에 이후 어떤 핸들러가 실행되는지 정확히 알 수 있습니다. 가드는 Pipe, Interceptor, Exception filter와 비슷하게 디자인되어, 요청/반환 주기 내 적절한 지점에 더 선언적으로 포함시킬 수 있습니다. 결론적으로, 코드를 더 선언적이고 DRY 원칙을 따르도록 유지할 수 있습니다.

  • ExecutionContext: NestJS 내에서 사용자의 요청, 반환 정보를 담고 있을 뿐만 아니라 해당 요청이 어떤 컨트롤러의 어떤 메서드를 통해서 처리되는지에 대한 정보도 가지고 있는 객체이다.