복's

[ Nest JS ] .env 파일 환경별로 설정 / 로깅 라이브러리 세팅 본문

교육/SW 정글 프로젝트(나만무)

[ Nest JS ] .env 파일 환경별로 설정 / 로깅 라이브러리 세팅

나복이 2023. 11. 15. 15:48
728x90

[ 📌 .env 파일 환경별 나눠서 세팅하기 ]

로깅 프레임워크를 nestJS에 설정하고 싶은데 .env 파일에 환경 변수를 세팅해 놓고 싶어졌다. ex) port번호

근데 환경별로 다르게 설정하고 싶은데 ex)개발, 운영... 그 방법을 몰라서 알아보게 되었다.

 

npm install @nestjs/config

.env 파일을 이용하기 위해서 npm install 다운 받는다.

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MoviesModule } from './movies/movies.module';
import { AppController } from './app.controller';

@Module({
    imports: [
        MoviesModule
      , ConfigModule.forRoot({
        isGlobal: true,
        envFilePath: `.${process.env.NODE_ENV}.env`
      })
    ],
    controllers: [AppController],
    providers: [],
})

이전에 express 할 때는 .env 파일에 세팅하고 process.env.환경변수명 이렇게 접근 했었는데 (다른 방법이 있었는지는 모름) 이제는 프로젝트를 진행하니까 환경에 따라서 동적으로 구분짓고 싶어서 env의 file path 설정 방법을 찾다가 알게 되었다.

 

그러면 process.env.NODE_ENV의 NODE_ENV는 어디 있는가 하면 cross-env 모듈을 설치하고 설정해야 한다.

npm install cross-env

설치가 끝나면 이제 환경 변수 값을 세팅 해주기만 하면되는데

[ package.json ]

"start:dev": "cross-env NODE_ENV=dev nest start --watch",
"start:debug": "cross-env NODE_ENV=debug nest start --debug --watch",
"start:prod": "cross-env NODE_ENV=prod node dist/main",

package.json 파일에서 우리가 nestJS 서버 구동할 때 사용하던 명령어 세팅에서 cross-env를 추가하고 환경 변수를 세팅해주면 된다.

 

위와 같이 진행하면 .env 파일을 (나의 경우) .dev.env / .debug.env / .prod.env 이렇게 구동할 환경에 따라 다르게 설정했다.

나중에 DB세팅을 하게 된다면 DB 정보가 다를테니 미리 해두는게 낫겠다 싶어서 해놓았다.


[ 📌 logging framework 세팅하기 ]

  • nestJS 내장 로거 이용하기

Logger는 따로 install 하지 않아도 바로 이용 가능하다.

import { Logger } from '@nestjs/common';
...
Logger.error(`Application running on port ${port}`);
Logger.warn(`Application running on port ${port}`);
Logger.log(`Application running on port ${port}`);
Logger.verbose(`Application running on port ${port}`);
Logger.debug(`Application running on port ${port}`);

[ log level에 따른 색상 ]

위에서 나눈 .env 환경별로 로그 레벨을 지정하도록 할 수 있다.

const app = await NestFactory.create(AppModule,
      {
          logger: process.env.NODE_ENV === 'dev'
        ? ['error', 'warn', 'log', 'verbose', 'debug']
        : ['error', 'warn', 'log']
      }
  );

 

  • Logger Custom 해서 사용하기
import { ConsoleLogger } from "@nestjs/common";

export class DoWithLogger extends ConsoleLogger {
    // error 뿐 아니라 다른 것도 가능
    error(message: any, stack?: string, context?: string): void{
        super.error.apply(this, arguments);
        this.doSomething();
    }

    privatedebug(message: any, context?: string): void{
        super.debug.apply(this, arguments);
        console.log(`debug method is called in Custom Logger`);
    }

    private doSomething(){
        console.log(`Do Something like DB I/O`);
    }
}

인터페이스 LoggerService를 구현해서 사용하는 방법도 있지만, 로그 레벨별로 색상이라던지 다른 정보를 출력하기 위해서 ConsoleLogger를 상속받아서 필요한 메소드를 오버라이딩 해서 사용할 수 있다.

 

추가로 그 사이에 DB에 로그를 쌓는다던가 다른 작업을 할 수 있다.

Logger 모듈을 만들어서 해당 다른 모듈에서 사용할 수 있도록 하면 된다.

 

하지만 매번 로거를 가져와서 사용하기 싫다면 전역적으로 설정해서 사용할 수 있다.

[ main.ts ]
...
app.useLogger(app.get(DoWithLogger));

app.module.ts에 내가 만들어서 사용할 커스텀 모듈을 import한 상태에서 main.ts에서 app에 로거를 등록해줘서 내가 만든 로거를 사용할 수 있게 했다.

 

  • nest-winston 사용하기(라이브러리)

winston과 nest-winston 라이브러리 설치

npm i nest-winston winston

설치 후 app.module에 옵션들을 세팅한다.

import * as winston from 'winston'
import {
    utilities as nestWinstonModuleUtilities,
    WinstonModule
} from 'nest-winston';
...
@Module({
    imports: [
        DoWithLoggerModule
      , ConfigModule.forRoot({
        isGlobal: true,
        envFilePath: `.${process.env.NODE_ENV}.env`
      })
      , WinstonModule.forRoot({
          transports: [
              new winston.transports.Console({
                  level : process.env.LOG_LEVEL,
                  format: winston.format.combine(
                      winston.format.timestamp(),
                      nestWinstonModuleUtilities.format.nestLike('DoWith', {prettyPrint: true})
                  ),
              }),
          ],
      }),
    ],
    controllers: [AppController],
    providers: [],
})
...

timestamp도 로그에 같이 찍히도록 설정 하였고 level은 .env에서 가져오도록 세팅 했다.

/**
 * winston log level
 * error  : 0
 * warn   : 1
 * info   : 2
 * http   : 3
 * verbose: 4
 * debug  : 5
 * silly  : 6
 */

winston이 갖는 로그 레벨은 이렇게 구성되어 있고, 설정된 로그 보다 높은 레벨까지 출력되게 설정되어있다.

 

nest-winston는 LoggerService를 구현한 WinstonLogger 클래스가 있기 때문에 아까전에 만든 커스텀 로그 클래스를 대체해서 사용하면 될 것같다.

import { WINSTON_MODULE_PROVIDER } from 'nest-winston'
...
app.useLogger(app.get(WINSTON_MODULE_PROVIDER));
...

이전에 사용하던 로거는 지우고, WINSTON_MODULE_PROVIDER를 넣어줬다.

 

다른 모듈에서 사용할 때는 커스텀 로그와 똑같이 의존성 주입을 통해서 사용하면 된다.

constructor(
        @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: WinstonLogger,
    ) {}

그런데 이렇게 모듈에만 추가한채로 실행하면 Nest 로거가 계속해서 나오게된다.

부트스트래핑 과정에서는 winston 라이브러리가 사용 불가능한 시점이기 때문인데

[ console ]

NestFactory.create 함수에 로거 인스턴스를 인자로 넣어주면 해결

[ main.ts ]
...
	const app = await NestFactory.create(AppModule,
        {
            logger: WinstonModule.createLogger({
                transports: [
                    new winston.transports.Console({
                        level : process.env.LOG_LEVEL,
                        format: winston.format.combine(
                            winston.format.timestamp(),
                            nestWinstonModuleUtilities.format.nestLike('DoWith', {prettyPrint: true})
                        ),
                    }),
                ],
            }),
        }
    );
...

이제 사용할 모듈에 Logger를 추가해주고

@Module({
    controllers: [MoviesController],
    providers: [MoviesService, Logger]
})

사용할 모듈에서 주입받아서 사용하면 된다.

@Inject(Logger) private readonly logger: LoggerService

[  Console ]

근데 나 흰색이니까 너무 밋밋해서.... option을 하나 추가해야겠다.

winston.format.colorize()

위에서 설정한 format 옵션에 colorize를 추가해주면

[ Console ]

크게 편해진건 없지만 밋밋하지는 않으니까 좋네... 하지만~ 

nestWinstonModuleUtilities.format.nestLike('DoWith', {
                          colors     : true,
                          prettyPrint: true
                      })

요기에 colors 옵션을 넣게 된다면 훨씬 보기 편해진다.

[ Console ]

 


https://github.com/gremo/nest-winston

 

GitHub - gremo/nest-winston: A Nest module wrapper form winston logger

A Nest module wrapper form winston logger. Contribute to gremo/nest-winston development by creating an account on GitHub.

github.com

사용법과 옵션은 이곳에서 보면 될 것같다. 

728x90