[Node.js] winston을 이용하여 logger 구현
![[Node.js] winston을 이용하여 logger 구현](/content/images/size/w1920/2024/12/nodejspng-2.png)
Node.js에서 Winston으로 로그 시스템 구현하기
Node.js 애플리케이션에서 로그 기능은 상태를 모니터링하고 문제가 발생했을 때 그 원인을 찾기 위해 꼭 필요하다. 이번 포스트에서는 Winston, winston-daily-rotate-file, process를 사용하여 로그 기능을 구현해본다.
1. 사용된 라이브러리 소개
1.1 Winston
Winston은 Node.js에서 가장 인기 있는 로깅 라이브러리 중 하나다. 다양한 로그 레벨을 지원하고, 로그를 파일이나 콘솔에 출력하는 등 다방면으로 활용할 수 있다. 일종의 멀티툴 같은 역할이다.
1.2 winston-daily-rotate-file
이건 Winston과 함께 사용해서 로그 파일을 매일 새로운 파일로 나눠서 저장하는 역할을 한다. 날짜별로 파일을 만들어 관리하는 거라, 한눈에 로그를 확인하기도 쉽고 관리도 편리하다.
1.3 process
Node.js의 process
객체는 현재 실행 중인 프로세스의 정보를 담고 있는데, 주로 환경 변수를 사용해 개발 환경과 운영 환경에서 다른 설정을 적용할 수 있다. 예를 들어, 개발 중에는 로그를 콘솔에 출력하고, 운영 중에는 파일에만 저장하도록 하는 것처럼.
2. logger.js
: Winston과 winston-daily-rotate-file 설정하기
기본 log 기능 구현인 logger.js
파일에서 어떻게 로그 기능을 구현했는지 살펴보자.
2.1 코드 설명
import winston from "winston";
import winstonDaily from "winston-daily-rotate-file";
import process from "process";
const { combine, timestamp, label, printf } = winston.format;
// 로그 파일 저장 경로 설정 (현재 작업 디렉토리 내 nodeLogs 폴더)
const logDir = `${process.cwd()}/nodeLogs`;
// 로그 포맷 정의
const logFormat = printf(({ level, message, label, timestamp }) => {
return `${timestamp} [${label}] ${level}: ${message}`; // 로그 출력 형식 정의
});
// Winston logger 생성
export const logger = winston.createLogger({
format: combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // 날짜 및 시간 형식 설정
label({ label: 'WOOBOLAB' }), // 로그 라벨 설정 (어플리케이션 이름)
logFormat // 위에서 정의한 로그 포맷 사용
),
transports: [
// 일반 로그 파일 설정
new winstonDaily({
level: 'info',
datePattern: 'YYYY-MM-DD',
dirname: logDir,
filename: `%DATE%.log`,
maxFiles: 30, // 최근 30일치 로그 파일 유지
zippedArchive: true // 로그 파일 압축 여부
}),
// 에러 로그 파일 설정
new winstonDaily({
level: 'error',
datePattern: 'YYYY-MM-DD',
dirname: `${logDir}/error`,
filename: `%DATE%.error.log`,
maxFiles: 30,
zippedArchive: true
}),
],
// 예외 처리 로그 설정
exceptionHandlers: [
new winstonDaily({
level: 'error',
datePattern: 'YYYY-MM-DD',
dirname: logDir,
filename: `%DATE%.exception.log`,
maxFiles: 30,
zippedArchive: true
})
],
});
// 개발 환경에서 콘솔에도 로그 출력
if (process.env.NODE_ENV !== 'production') {
logger.add(
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(), // 로그 레벨에 색상을 추가해서 출력
winston.format.simple() // 간단한 형식으로 콘솔에 출력
),
})
);
}
2.2 주요 포인트
- 로그 파일 경로 설정
- 로그 파일은 현재 작업 디렉토리 안의
nodeLogs
폴더에 저장된다.process.cwd()
는 현재 애플리케이션의 실행 경로를 반환하는데, 이를 이용해 어디서든 로그를 저장할 수 있다.
- 로그 파일은 현재 작업 디렉토리 안의
- 로그 포맷 정의
- 날짜, 어플리케이션 이름, 로그 레벨, 메시지 형태로 로그를 남긴다. 이 포맷 덕분에 로그가 보기 편해지고, 중요한 정보를 쉽게 찾을 수 있다.
- 로그 파일로 저장
info
레벨과error
레벨의 로그를 날짜별로 파일에 나누어 저장한다. 이를 통해 일반적인 로그와 오류 로그를 쉽게 구분할 수 있다. 매일 새로운 파일이 생성되고, 최대 30일간 유지되므로 오래된 로그 파일이 자동으로 정리된다.
- 예외 처리 로그
- 애플리케이션이 예상치 못한 에러로 종료될 때의 로그(
uncaughtException
)도 별도로 저장하여 문제를 빠르게 찾을 수 있도록 한다.
- 애플리케이션이 예상치 못한 에러로 종료될 때의 로그(
- 개발 환경에서 콘솔 로그 출력
- 개발 중에는 콘솔에 로그를 찍어주는 게 편리하다. 그래서
process.env.NODE_ENV
를 확인해 개발 환경에서는 콘솔에 로그를 출력하게 설정했다.
- 개발 중에는 콘솔에 로그를 찍어주는 게 편리하다. 그래서
3. app.js
에서 로깅 사용하기
그럼 app.js
파일에서는 이 로그 기능을 어떻게 사용하는지 살펴보자.
3.1 코드 설명
import express from "express";
import dotenv from "dotenv";
import figlet from "figlet";
import { logger } from "#util/logger.js";
import { config } from "#config/config.js";
import { db } from "#db/dbConn.js";
const app = express();
// 환경 변수 설정
dotenv.config();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 데이터베이스 연결 성공 시 로그 남기기
db.getConnection().then(async (connection) => {
logger.info(`DB Connection Success: ${config.db.host}, ${config.db.database}`);
});
// 서버 시작 시 로그 출력
app.listen(config.host.port, () => {
figlet("WOOBOLAB", (err, data) => {
if (err) {
logger.error(`Something went wrong with figlet.. , ${err}`);
return;
}
logger.info(`
${data}
Server is running on port ${config.host.port}`);
});
});
3.2 주요 로그 설명
- 데이터베이스 연결 로그
- 데이터베이스 연결이 성공하면
logger.info()
를 사용해 연결된 데이터베이스 호스트와 이름을 로그로 남긴다. 이를 통해 서버가 DB와 정상적으로 연결되었는지 쉽게 확인할 수 있다.
- 데이터베이스 연결이 성공하면
- 서버 시작 로그
- 서버가 시작되면
figlet
을 사용해 콘솔에 멋진 아스키 아트로 "WOOBOLAB"을 출력하고, 그와 함께 서버가 어떤 포트에서 실행 중인지logger.info()
로 기록한다. - 만약
figlet
에서 에러가 발생하면,logger.error()
를 통해 에러를 기록해두어 문제가 무엇인지 쉽게 파악할 수 있도록 한다.
- 서버가 시작되면
4. 로그 시스템의 장점
- 로그 레벨 관리:
info
와error
레벨로 로그를 나누어 관리하므로, 정상적인 흐름과 오류 상황을 명확하게 구분할 수 있다. - 자동 파일 관리:
winston-daily-rotate-file
을 이용해 매일 새로운 파일에 로그를 저장하고, 오래된 로그 파일은 자동으로 정리할 수 있다. 덕분에 파일 관리를 신경 쓸 일이 줄어든다. - 환경에 따른 로깅 설정: 개발 환경과 운영 환경에서 로그를 다르게 출력할 수 있다. 개발 중에는 콘솔에서 로그를 바로바로 확인할 수 있어 디버깅에 편리하고, 운영 환경에서는 파일로 로그를 남겨 나중에 분석할 수 있게 한다.
5. 마무리
이번 포스트에서는 Node.js에서 Winston과 winston-daily-rotate-file을 사용해 로그 시스템을 구축하는 방법을 알아보았다. 이렇게 구축한 로그 시스템은 애플리케이션 상태를 쉽게 파악할 수 있게 해주고, 문제가 발생했을 때 빠르게 원인을 찾아 해결하는 데 도움을 준다.
이 포스팅의 사용된 코드는 inpa-dev 님의 글을 참조하였다.
출처: https://inpa.tistory.com/entry/NODE-📚-Winston-모듈-사용법-서버-로그-관리
댓글