복's
[ Nest JS ] .env 파일 환경별로 설정 / 로깅 라이브러리 세팅 본문
[ 📌 .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}`);
위에서 나눈 .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 라이브러리가 사용 불가능한 시점이기 때문인데
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
근데 나 흰색이니까 너무 밋밋해서.... option을 하나 추가해야겠다.
winston.format.colorize()
위에서 설정한 format 옵션에 colorize를 추가해주면
크게 편해진건 없지만 밋밋하지는 않으니까 좋네... 하지만~
nestWinstonModuleUtilities.format.nestLike('DoWith', {
colors : true,
prettyPrint: true
})
요기에 colors 옵션을 넣게 된다면 훨씬 보기 편해진다.
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
사용법과 옵션은 이곳에서 보면 될 것같다.
'교육 > SW 정글 프로젝트(나만무)' 카테고리의 다른 글
[ Nest JS ] File Upload (0) | 2023.11.24 |
---|---|
[ Nest JS ] 예외 클래스 만들기 및 필터에서 예외 받기 (1) | 2023.11.16 |
[ Nest JS ] 예외 처리 (Exception Handling) 및 예외 필터(Exception filters) (1) | 2023.11.15 |
[ Nest JS ] 미들웨어(Middleware) 설정 (0) | 2023.11.15 |
[ 나만무 ] 주제 정하기, 팀 규칙 정하기, 화면 설계, API 정리, ERD 그리기, Meta Data 정리, Jira 정리 (1) | 2023.11.15 |