
NestJS 요청 라이프사이클은 미들웨어 → 가드 → 인터셉터(전) → 파이프 → 라우트 핸들러 → 인터셉터(후) → 응답 순서로 흐릅니다. 어느 단계에서든 예외가 발생하면 예외 필터로 모입니다. 미들웨어는 Express/Fastify 기반이라 Nest 컨텍스트를 모르고, 가드와 인터셉터는 ExecutionContext를 알기 때문에 더 정교한 제어가 가능합니다. 각 계층에 책임을 나눠 맡기면 백엔드 코드가 훨씬 깔끔하고 견고해집니다.
미들웨어는 NestJS만의 개념이 아니라, 뿌리인 Express(또는 Fastify)에서 온 개념입니다.
미들웨어는 요청(req)과 응답(res) 객체 사이에서 동작하는 함수입니다. 이 함수는 세 가지 권한을 가집니다.
next() 호출: 모든 작업이 끝나면 다음 미들웨어나 라이프사이클 단계로 바톤을 넘깁니다. next()를 호출하지 않으면 요청은 거기서 멈추고 타임아웃이 발생합니다.NestJS는 미들웨어 이후에 컨텍스트(Context)를 아는 단계들을 추가했습니다.
가드는 미들웨어 다음으로 실행됩니다. 미들웨어와 가장 큰 차이점은 ExecutionContext에 접근할 수 있다는 점입니다.
인터셉터는 라우트 핸들러(컨트롤러) 실행 전과 후를 모두 가로챌 수 있습니다.
{ "success": true, "data": ... } 포맷으로 통일합니다.파이프는 컨트롤러에 정의된 인자(Arguments)를 대상으로 동작합니다.
ValidationPipe를 이용한 유효성 검사, ParseUUIDPipe를 이용한 ID 형식 체크.라이프사이클 중 어느 곳에서든 throw가 발생하면 예외 필터로 모입니다.
이 부분이 설계에서 가장 중요한 Trade-off 포인트입니다.
| 구분 | Middleware | Guard | Interceptor |
|---|---|---|---|
| 순서 | 가장 빠름 (1순위) | 2순위 | 3순위 (전처리) |
| Nest 컨텍스트 | 모름 (익명) | 앎 (클래스/메서드 정보) | 앎 (응답 객체 제어 가능) |
| 주요 역할 | 공통 로깅, HTTP 조작 | 인증 및 권한 부여 | 비즈니스 로직 전후 처리 |
| 기반 기술 | Express/Fastify 함수 | NestJS Class | RxJS Observable |
NestJS의 요청 라이프사이클을 이해한다는 것은 책임의 분리를 이해한다는 것과 같습니다.
이 구조만 잘 지켜도 백엔드 코드는 훨씬 깔끔하고 견고해집니다.
참고 자료: