[NestJS] 미들웨어부터 필터까지: 요청 라이프사이클 심층 분석
1. 미들웨어(Middleware): 가장 바깥쪽의 문지기
많은 분이 가장 궁금해하시는 미들웨어는 사실 NestJS만의 개념이 아니라, 뿌리인 Express(또는 Fastify)에서 온 개념입니다.
1.1. 미들웨어가 정확히 뭔가요?
미들웨어는 요청(req)과 응답(res) 객체 사이에서 동작하는 함수입니다. 이 함수는 다음의 세 가지 권한을 가집니다.
- 요청/응답 객체 수정: 헤더를 추가하거나 쿠키를 파싱하는 등 데이터를 미리 손질합니다.
- 응답 종료: 인증되지 않은 요청이면 다음 단계로 넘기지 않고 여기서 바로 에러 응답을 보내 끝낼 수 있습니다.
next() 호출: 모든 작업이 끝나면 다음 미들웨어나 라이프사이클 단계로 바톤을 넘깁니다. 만약 next()를 호출하지 않으면 요청은 거기서 멈추고 타임아웃이 발생합니다.
1.2. 실무 예시
- CORS 설정: 특정 도메인에서만 접근 가능하도록 헤더를 체크합니다.
- 로깅: "어떤 IP에서 어떤 URL로 요청이 왔는지"를 콘솔에 찍습니다.
- Body Parsing: 네트워크를 타고 온 0101 데이터를 우리가 읽기 편한 JSON으로 미리 변환해둡니다.
2. 라이프사이클 단계별 상세 분석
NestJS는 미들웨어 이후에 '컨텍스트(Context)'를 아는 똑똑한 단계들을 추가했습니다.
2.1. Guard (가드): "누구냐 넌?" (인가 계층)
가드는 미들웨어 다음으로 실행됩니다. 미들웨어와 가장 큰 차이점은 ExecutionContext에 접근할 수 있다는 점입니다.
- 심화 정보: 가드는 현재 실행될 컨트롤러가 무엇인지, 어떤 메서드인지(메타데이터)를 알 수 있습니다. 그래서 "이 유저가 '관리자' 권한이 필요한 메서드에 접근하는가?"를 아주 정교하게 체크할 수 있습니다.
- 실무 활용: JWT 토큰 검증, Role 기반 접근 제어(RBAC).
2.2. Interceptor (인터셉터): "관찰하고 변형하라" (AOP 계층)
인터셉터는 라우트 핸들러(컨트롤러) 실행 전과 후를 모두 가로챌 수 있습니다.
- 심화 정보: 자바스크립트의 비동기 처리(RxJS)를 활용하여 응답 시간을 측정하거나, 컨트롤러가 던진 데이터를 다른 형태로 감싸서 내보낼 수 있습니다.
- 실무 활용:
- 전처리: 캐시된 데이터가 있으면 컨트롤러를 아예 안 거치고 응답 보내기.
- 후처리: 모든 성공 응답을
{ "success": true, "data": ... } 포맷으로 통일하기.
2.3. Pipe (파이프): "데이터를 다듬고 검증하라" (검증 계층)
파이프는 컨트롤러에 정의된 인자(Arguments)를 대상으로 동작합니다.
- 심화 정보: 파이프는 역직렬화(Deserialization)의 핵심입니다. 문자열로 들어온 숫자를 진짜 숫자 타입으로 바꾸거나, DTO 클래스를 보고 데이터의 유효성을 꼼꼼히 따집니다.
- 실무 활용:
ValidationPipe를 이용한 유효성 검사, ParseUUIDPipe를 이용한 ID 형식 체크.
2.4. Exception Filter (예외 필터): "최종 안전망"
라이프사이클 중 어느 곳에서든 throw가 발생하면 예외 필터로 모입니다.
- 실무 활용: 500 에러 발생 시 유저에게는 "서버 점검 중입니다"라고 친절하게 보여주고, 개발자 슬랙에는 에러 로그를 쏘는 등의 처리를 합니다.
3. 핵심 비교: 미들웨어 vs 가드 vs 인터셉터
이 부분이 시니어 레벨에서 가장 중요한 Trade-off 포인트입니다.
| 구분 | Middleware | Guard | Interceptor |
|---|
| 순서 | 가장 빠름 (1순위) | 2순위 | 3순위 (전처리) |
| Nest 컨텍스트 | 모름 (익명) | 앎 (클래스/메서드 정보) | 앎 (응답 객체 제어 가능) |
| 주요 역할 | 공통 로깅, HTTP 조작 | 인증 및 권한 부여 | 비즈니스 로직 전후 처리 |
| 기반 기술 | Express/Fastify 함수 | NestJS Class | RxJS Observable |
4. 마치며
NestJS의 요청 라이프사이클을 이해한다는 것은 "책임의 분리"를 이해한다는 것과 같습니다.
- 공통적인 네트워크 처리는 미들웨어에,
- 보안과 권한은 가드에,
- 데이터 형식의 검증은 파이프에,
- 응답의 가공과 모니터링은 인터셉터에 맡기세요.
이 구조만 잘 지켜도 여러분의 백엔드 코드는 훨씬 더 깔끔하고 견고해질 것입니다.
참고 자료: