[Project] Nest Lifecycle 이해하기
시작하며
링크프렌즈 프로젝트를 진행하면서 어떤 상황에서 Interceptor를 써야 하고 어떤 상황에서 쓰지 말아야 할지에 대한 궁금증이 있었습니다.
해당 궁금증을 해결하기 위해서는 NestJs LifeCycle에 대한 전반적인 이해가 필요하다고 생각했고, 궁금증을 해결하기 위한 과정과 얻게 된 지식을 기록하려 합니다.
마주친 문제
NestJs 공식문서를 보면 다양한 개념들이 나옵니다. Controller, Middleware, Pipes, Interceptor 등 NestJs의 주요 개념들의 실행 순서와 역할을 정확하게 이해하지 못해 해당 프로젝트의 AuthInterceptor부분의 착오가 있었습니다.
NestJs Lifecycle
☞ 우선 Middleware와 Interceptor의 차이점을 알아보고 Nest Lifecycle에 대해서 알아보겠습니다.
NestJs Middleware는 Request와 response의 중간에서 값을 가져갔다가 다시 원래 목적지로 되돌려주는 기능을 합니다.
공식문서를 보면 헷갈리는 부분이 있습니다.
(위 글은 공식문서에 설명되어 있습니다.) 미들웨어는 요청과 응답객체에 접근할 수 있다고 설명되어 있는데요. 여기서 응답객체는 미들웨어에서 오는 응답객체를 뜻하지 않습니다.
NestJs Interceptor는 request와 response의 중간에서 값을 가로챈 뒤, 보내는 역할을 합니다. 공식문서를 보면 Interceptor를 사용하는 대표적인 케이스가 Logger입니다. Logger의 경우 request와 response에 대한 정보를 로깅해야 하기 때문에 Interceptor로 구현하기 알맞은 경우라고 생각하면 됩니다.
위에서 미들웨어와 인터셉터의 간단한 차이점을 알아보았습니다. 혹시, 더 자세한 개념과 내용이 궁금하시면 공식문서를 참고하세요.
이제 Lifecycle에 대해서 순차적으로 설명하겠습니다.
우선, Request가 들어옵니다.
1. Middleware를 지나게 됩니다. Middleware는 request와 response객체 중간에 로직은 추가합니다.
2. Guard를 지나게 됩니다. Guard에서는 인증, 인가의 역할을 합니다. 예를 들어, HTTP Header에 사용자의 정보가 담긴 Token 등을 보내면, 서버의 Guard가 유효한 사용자인지 권한이 있는 사용자인지 확인합니다.
3. Pre Interceptor를 지나게 됩니다. Interceptor는 request와 response 중간에 로직을 추가합니다.
4. Pipe를 거치게 됩니다. Pipe의 역할은 Request가 왔을 때, body나 params, query에 대해서 validation, transformation을 실행합니다. Pipe의 대표적인 예로 입력데이터를 원하는 출력으로 변환시켜 주는 transformation, 입력 데이터를 검증하는 validation을 사용합니다.
5. Controller를 지나갑니다. 일반적으로 service에 라우팅을 해주는 역할로 쓰입니다.
6. Post Interceptor를 지나칩니다. 이때, 알아야 할 것은 interceptor에서 들어올 때 실행할 로직과 나갈 때 실행할 로직을 잘 구별해서 구현해야 합니다.
7. 마지막으로 Exception filter를 거치고 400, 500번대 에러를 처리합니다. 일반적으로 global exception filter를 선언하여 에러핸들링을 합니다. 이후, server response가 나가며 Lifecycle이 종료됩니다.
마치며
어떤 언어, 프레임워크등 해당 기술의 본질과 기본적이 개념들을 정확하게 숙지하며 개발해야 한다고 느꼈습니다. 처음부터 기술의 개념을 완벽하게 숙지하며 개발할 수 없지만, 해당 기술과 언어를 쓰면서 기본적인 개념과 흐름을 이해해 가는 기본이 튼튼한 개발자가 되고 싶습니다.