본문 바로가기
Nest

[Nest] nest winston 로그 관리

by chu_dw 2024. 4. 20.

저번 logger 기능 에선 인터셉터를 사용해 특정 컨트롤러의 로그를 출력했는데

이번엔 winston 라이브러리를 활용해 middleware에서 전체 응답에 대한 로깅을 정리해보겠다.

 

winston이란?

Nodejs에서 지원하는 로깅 라이브러리로 다양한 수준의 로그를 기록하고 관리할 수 있다.

다양한 저장소를 지원해 콘솔이나 파일에 로그를 기록할 수 있다.

또한 로그 메세지에 다양한 메타데이터를 추가할 수 있어 디버깅과 모니터링을 용이하게 해준다.

 

winston 모듈 설치

$ npm i winston winston-daily-rotate-file nest-winston

winston-daily-rotate-file은 로그 파일을 관리해 주는 모듈로 날짜별로 로그를 관리해 주기때문에 같이 설치한다.

nest-winston은 Nestjs에서 winston을 쉽게 설정하고 통합하게 해주는 모듈이다.

그리고 main.ts에 winston을 애플리케이션의 로거로 설정해 준다.

 

logger.config 설정

먼저 import부분을 보면

nest-winston 모듈에서 utilities와 winstonModule을 가져온다.

utilities는 winston사용 도구 함수를 제공한다.

winstonModule은 Nestjs에서 winston 로깅을 구성하기 위한 모듈로 로깅 형식을 구조화하는데 도움을 준다.

 

isProduction 변수는 환경변수에 저장된 현재 애플리케이션 실행환경을 저장한다.

이전 logger에서 main.ts에서 직접 적용해줬던 부분이다.

logDIr 변수는 로그 파일이 저장될 디렉터리 경로를 설정한다.

 

dailyOptions 메서드는 일별 로그 파일의 옵션을 설정한다.

로그 레벨에 따라 다른 옵션을 생성하고 반환한다.

 

createLogger()를 사용해 winstonLogger라는 로그를 생성한다.

transports로 로그를 출력한 대상을 지정한다.

첫 번째 winston.transport.Console() 객체는 로그를 console에 출력한다.

isProduction에 따라 level을 설정해주고, format으로 로그 형식을 지정한다.

나머지 객체는 파일에 출력한다. 레벨에 대한 설정은 위에서 만든 dailyOption을 사용한다.

 

 

nest에서 Middleware 구현

이제 위에서 설정해준 log형식을 middleware를 구현해 전체 요청에 적용할 것이다.

그전에 middleware 구현 방법에 대해 먼저 정리하겠다.

middleware는 클라이언트로부터 받은 요청이 헨들러로 가기 전 입구에서 처리해 주는 기능을 한다.

 

nest에서 midlleware을 구현하기 위해서는 NestMiddleware 인터페이스를 implenets 하여 구현한다.

위처럼 use함수에서 미들웨어를 구현한다. req는 http 요청 객체, res는 http 응답 객체이다.

next은 다음 미들웨어를 호출하는 함수이다.

이 함수 안에 데이터를 전달하여 다음 미들웨에서 추가 작업도 가능하다.

마지막 Next는 요청을 컨트롤러에 전달한다. 이 순서에 관해선 app.module에서 설정해 준다.

app.module에서 NestModule에서 가져온 configure메서드를 사용해 middleware를 등록한다.

MiddlewareConsumer를 인자로 받아 등록하는데 이 안에는 middleware를 등록하고 지정하는 메서드가 들어있다.

.apply() : 미들웨어를 등록하고 적용한다. 미들웨어 인스턴스를 전달받아 현재 라우트에 적용한다.

.forRoutes() : 특정 라우트나 컨트롤러를 지정해 미들웨어 적용한다.

.with() : 미들웨어에 추가적 옵션을 전달한다.

 

Logger Middleware 구현

그럼 모든 request에 대해 위에서 설정한 로깅이 적용되도록 middleware를 구현해 준다.

하면 될 줄 알았는데 에러가 계속 안 잡힌다....

그냥 완전 처음부터 해봐야 할 거 같다...  winston-daily-rotate-file 버전 문제인가..?

 

이것저것 해봐도 안 돼서 새로 간단한 프로젝트를 파서 해보았다.

결론적으론 간단하게 찍는 거에 성공했는데

계속 에러가 나던 app.module provider에 생성한 logger가 타입문제로 안 들어갔었는데

주입을 안 해주고 그냥 import 해서 가져다 쓰는 건가..?

역기 기본이 중요하다.. 하나씩 천천히 알아보겠다.

 

middleware에서 의존성 주입

전역 미들웨어는 애플리케이션이 초기화되는 시점에서 등록되며, 의존성 주입은 이전에 발생한다.

따라서 전역 미들웨어에 등록 된 의존성은 초기화되기 전에 주입될 수 없다.

그래서 위에 처럼 common모듈을 따로 만들어주고 전역 미들웨어가 아닌 모듈미들웨어로 등록한다.

그 후 forRoutes 설정을 통해 모든 라우트에 적용해 전역 미들웨어처럼 사용한다.

 

module provider

이 부분 때문에 한참을 막혔던 거 같다.

nestjs에서 provider를 주입하기 위해선 해당 모듈에 provider에 의존성을 등록해줘야 한다.

계속 해오던 거였긴한데 해당 logger는 클래스가 아니라 객체였다.

그래서 아래와 같이 객체를 바로 provider로 등록해 주니 에러가 났다.

Nestjs는 객체를 provider로 인식하지 못한다고 한다.

따라서 아래처럼 명시적으로 token을 사용해서 provider로 등록해줘야 한다.

이걸 몰라서... common모듈이 문제인가 싶어서 app모듈에 하니 전역 모듈이라 거기서도 안되고..

이래서 고치는데 오래 걸린 것 같다..

 

그래서 간단하게 따로 만든 코드를 살펴보면

전체 구성은 logger.config에서 winston logger 설정을 해주고

logger.middleware에서 미들웨어를 만들어주고 winston logger를 주입하여 log를 찍는다.

그리고 common모듈에서 위처럼 미들웨어를 등록해 주고 app모듈에 common모듈을 import 한다.

 

그럼 다시 프로젝트로 돌아가서 파일에 따로 로그 찍는 거 까지 해보겠다.

 

logger 생성

src/config/logger.config.ts

 

middleware 구현

src/middleware/logger.middleware.ts

 

middleware등록

src/common/common.module.ts

 

이렇게 구현해 준 후 app모듈에 common모듈 import 해주고

main.ts에서 logger를 winstonlogger로 replace 해주면 된다.

 

 

결과

지정한 디렉터리에 레벨별로 폴더가 생기고 로그가 저장되게 된다.

설정 해준대로 잘 저장된다!

 

 

https://pypystory.tistory.com/80

 

[NestJS] winston을 사용해서 logger middleware, filter로 로깅하기. 로그 관심사 분리

왜 winston을 고르게 되었는가? NestJS에서 logging을 구현하는 방법에는 여러가지가 있다. 기본적으로 @nestjs/common에 내장된 logger가 있긴하지만, package에는 편리한 기능들이 구현되어 있다. pino, morgan

pypystory.tistory.com

https://www.npmjs.com/package/nest-winston

 

nest-winston

A Nest module wrapper for winston. Latest version: 1.9.4, last published: 8 months ago. Start using nest-winston in your project by running `npm i nest-winston`. There are 249 other projects in the npm registry using nest-winston.

www.npmjs.com

https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-Winston-%EB%AA%A8%EB%93%88-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%84%9C%EB%B2%84-%EB%A1%9C%EA%B7%B8-%EA%B4%80%EB%A6%AC

 

[NODE] 📚 Winston 모듈 사용법 - 서버 로그 관리

Winston 모듈 어떤 서버든지 실제로 서비스를 운영하려면 로그를 꼼꼼히 남기는 것은 필수이다. Log는 에러를 파악할 수 있는 열쇠이기 때문에 서버를 운영한다고 하면 로그 시스템을 구축해서 시

inpa.tistory.com

https://velog.io/@coalery/nest-injection-how

 

Nest.js는 실제로 어떻게 의존성을 주입해줄까?

Nest.js의 의존성 주입 부분을 삽으로 파봅니다.

velog.io

https://one-armed-boy.tistory.com/entry/NestJS-Request-Lifecycle-1-Middleware

 

NestJS Request Lifecycle (1) - Middleware

이전 글 2022.12.22 - [Backend/NestJS] - NestJS Request Lifecycle (0) - 개요 미들웨어 ( in NestJS ) 미들웨어란 NestJS 요청 생명주기에서 클라이언트로부터 들어오는 request가 가장 먼저 처리되는 핸들러이다. Node.j

one-armed-boy.tistory.com

 

'Nest' 카테고리의 다른 글

[Nest] Bull사용한 병렬처리  (0) 2024.04.19
[Nest] Worker thread pool 구현  (0) 2024.04.18
[Nest] Nestjs logger와 middleware, intercepter  (0) 2024.04.16
[Nest] Nestjs 멀티 스레드 (Worker)  (0) 2024.04.13
[Nest] NestFactory 동작  (0) 2024.03.30