[Nest] Nestjs logger와 middleware, intercepter
전 글에서 worker를 위해 프로젝트에서 편지 단어 랭크를 만드는 기능을 추가했는데
워커 스레드 사용 전후 응답시간 차이를 확인하기 위해 logger midllerware를 먼저 정리하겠다.
logger란?
logger는 애플리케이션에서 로그를 기록하고 관리하는데 사용되는 모듈이다.
이 기록을 통해 문제 발생시 원인을 파악한다.
- 로그 레벨 설정 : debug, info, warn, error 등의 레벨을 설정
- 로그 메세지 기록 : 다양한 로그 메세지 기록 가능
- 로그 포멧 지정 : 로그 메제시 형식 지정
- 로그 디렉토리 지정 : 로그 파일 저장 위치 지정
logger사용이유
지금 까진 그냥 로그를 console.log()를 통해서 찍고 이걸로 에러를 해결했었다.
빠르고 간단한 방법 대신 logger 모듈을 사용하는 이유는?
1. logger는 로그 레벨을 기록 가능하다.
로그 레벨은 애플리케이션의 로깅을 관리하고 유지보수 하는데 매우 중요하다.
로그 레벨을 통해 로그를 필터링해 로그 파일의 크기를 줄이고, 관리하기 편리하게 해 준다.
또한 실행 중 발생하는 이벤트의 적절한 중요도를 기록할 수 있다.
2. 로깅 설정의 집중화가 가능하다
로깅설정을 로깅 모듈에서 중앙집중화 하여 관리한다.
애플리케이션 전체에 일관된 로깅 적용 가능하다.
3. 유연성 확장성 증가
로그 메세지를 보내는 대상 쉽게 변경 가능하다. 개발 중엔 콘솔에 로그를 출력하고
프러적션 환경에선 파일로 로그 출력을 변경하기 쉽다.
로그 기본 사용
@nestjs/common에서 Logger 가져와 주입하여 사용한다.

위처럼 logger 주입해준 후 로그레벨과 함께 사용하면 된다.
클래스명. name은 로깅 정보에 해당 클래스에서 발생한 로그라는 것을 알려주기 위한 것이다.
로그 레벨별 접근
실행 환경 별로 접근할 수 있는 로그레벨을 설정해준다.
main.ts에서 아래처럼 설정해준다.

실행 환경에선 log이상, 그 외 환경은 debug이상 로그 레벨을 출력한다.
로그 레벨 : debug(0), verbase(1), log(2), warn(3), error(4)
middleware란?
cors정리할 때 간단히 정리했었다
middleware는 요청과 응답사이에서 작동하며 주로 http 요청의 처리 중간에서 가로채고 동작을 수행한다.
주로 로깅이나, 보안검사 등에 사용된다.
nestjs에서 Middleware는 NestMiddleware 인터페이스를 구현하여 사용한다.
NestMiddleware의 use메서드에 미들웨어의 동작을 구현하면 된다.
middleware특징
미들웨어의 경우 모든 http 요청에 대해 실행되고 응답 요청사이에 있다.
따라서 지금 하려는, 특정 메서드의 실행 시간을 구하는 작업에는 적합하지 않은 거 같다.
middleware는 http관련 로그를 쌓을 때 주로 사용하는 거 같다.
이때 winston모듈과 함께 많이 사용하는거 같은데 이는 따로 정리해보도록 하겠다.
inteceptor란?
interceptor는 nestjs의 컨트롤러의 메서드 실행 전후에 실행되며,
메서드의 실행 결과를 변형하거나 수정하는 기능이다.
미들웨어와 다르게 특정 컨트롤러에만 적용된다.
현재 내가 하려는 로그는 모든 메서드에 필요하지도 않고,
http응답 시간이 아니라 메서드의 실행 시간이 궁금한 것이기 때문에 인터셉터를 사용해서 구현해 보겠다.
interceptor 구현
intercepter는 NestInterceptor 인터페이스를 구현하여 만들어준다.

intercept 메서드에 인터셉트 동작을 구현하면 된다.
매개변수로 ExecutionContext랑 CallHandler를 받고 Observable<any>를 반환한다.
-ExecutionContext : 현재 요청이나 응답에 관련된 정보가 들어있다.
-CallHandler : 현재 실행 중인 요청을 처리하고 다음 핸들러로 전달한다.
-Observable : 현재 요청에 대한 처리 결과를 나타내는 데이터 스트림이다.
이런 식으로 정리되는데 잘 모르겠다.. 실제 동작 과정 보면
요청이 들어오면 컨트롤러로 들어가기 전에 요청이 인터셉터로 들어온다.
이 요청에 대한 모든 정보는 ExecutionContext가 가지고 있다. (http 요청객체, 라우트, 핸들러)
그리고 요청에 대한 추가작업을 진행한다.
CallHandler를 통해 추가작업된 내용을 다음 핸들러(보통 컨트롤러)에 전달한다. (.handle()메서드)
이때 위 코드에선 observer로 반환하면서 추가작업으로 .pipe()를 사용했는데 이는 따로 정리하겠다.

사용법은 이렇게 사용할 모듈에 등록해 주고

@UserInterceptor로 사용해 주면 된다.

결과는 위와 같이 나온다.
최종적으로 logger를 사용하는 코드로 바꿔주며 추력 형식도 정리해주면 아래와 같이 구현할 수 있다.


https://www.daleseo.com/nestjs-logging/
NestJS에서 로깅(logging)하기
Engineering Blog by Dale Seo
www.daleseo.com
[NestJS] Logging 알아보기 (feat. winston)
이번 포스팅은 Interceptor의 개념을 알고 있는 상태여야 이해하기가 쉬운 내용이 포함되어 있습니다. Interceptor에 대한 설명은 다음 링크를 참고해주세요. [NestJS] Interceptor 개념정리 (+간단한 Logger) 1
cdragon.tistory.com
https://any-ting.tistory.com/142
[Nest.js] 심화 - 인터셉터(Interceptors) 개념 및 사용법
- 개요 안녕하세요. 이번 시간에는 인터셉터(Interceptors)에 대해 알아보겠습니다. 인터셉터를 접하게 되면 항상 따르는 AOP(Aspect Oriented Programming) 기술을 강조하고 있습니다. 메서드 실행 전/후 추
any-ting.tistory.com