[Node.js] Winston 사용하여 로깅하기

로깅(Logging)은 모든 애플리케이션에서 중요한 부분입니다. 로깅은 코드 디버깅, 모니터링 및 유지 관리에 도움이 됩니다. Winston은 유연성과 풍부한 기능으로 인해 Node.js에서 가장 인기 있는 로깅 라이브러리 중 하나입니다. 이 글에서는 Winston을 Node.js 애플리케이션에 통합하고 그 기능을 최대한 활용하는 방법을 살펴봅니다.

개요

이 튜토리얼에서는 다음을 다룹니다:

  • Node.js 프로젝트에서 Winston 설정하기
  • 다양한 로깅 수준 구성하기
  • 사용자 정의 로그 형식 만들기
  • 여러 전송(콘솔, 파일 등)에 로깅하기
  • 사용자 지정 로그 수준 만들기
  • 일일 로그 파일에 로깅하기
  • Express 애플리케이션에서 Winston 사용하기

전제 조건

  • JavaScript 및 Node.js에 대한 기본 지식
  • npm 및 Express에 익숙함(선택 사항이지만 마지막 단계에 권장됨).

설정

Node.js 프로젝트를 초기화합니다.

1
2
3
mkdir winston-logger-example
cd winston-logger-example
npm init -y

Winston를 설치합니다.

1
npm install express winston winston-daily-rotate-file

기본 설정

Winston을 설정하기 위한 logger.js 파일을 생성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// logger.js

const { createLogger, format, transports } = require('winston');

const logger = createLogger({
level: 'info',
format: format.combine(
format.colorize(),
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`)
),
transports: [new transports.Console(), new transports.File({ filename: 'app.log' })],
});

module.exports = logger;
  • createLogger: 새 로거 인스턴스를 초기화합니다.
  • format.combine: 여러 형식을 결합합니다. 여기서는 colorize, timestamp, printf를 사용하고 있습니다.
  • transports: 로그를 전송할 위치를 지정합니다. 이 예에서는 콘솔과 파일(app.log)에 로깅합니다.

로깅 레벨 구성하기

Winston은 error, warn, info, http, verbose, debug, silly 등 여러 로깅 레벨을 지원합니다. 캡처할 로그의 최소 레벨을 구성할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// logger.js

const { createLogger, format, transports } = require('winston');

const logger = createLogger({
levels: {
error: 0,
warn: 1,
info: 2,
http: 3,
verbose: 4,
debug: 5,
silly: 6,
},
level: 'info', // Set the default log level
format: format.combine(
format.colorize(),
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`)
),
transports: [new transports.Console(), new transports.File({ filename: 'app.log' })],
});

module.exports = logger;
  • levels: 사용자 정의 로깅 레벨을 정의합니다.
  • level: 캡처할 로그의 최소 레벨을 설정합니다(여기서는 info로 설정되어 있음).

로그 레벨 이해하기

로그 레벨은 기록되는 메시지의 심각도를 결정합니다. Winston은 가장 심각한 것부터 가장 덜 심각한 것까지 우선순위가 지정된 npm 스타일 로깅 레벨을 사용합니다.

  • error: (0) 즉각적인 주의가 필요할 수 있는 오류를 로깅합니다.
  • warn: (1) 잠재적 문제를 나타내는 경고를 로깅합니다.
  • info: (2) 애플리케이션의 진행 상황을 강조하는 정보 메시지를 로깅합니다.
  • http: (3) HTTP 요청을 로깅합니다.
  • verbose: (4) 디버깅 중 유용한 상세 정보를 로깅합니다.
  • debug: (5) 디버깅 정보를 기록합니다.
  • silly: (6) 가장 자세한 정보, 종종 필요 이상으로 많은 정보를 로깅합니다.

최소 로그 레벨을 설정하여 덜 심각한 메시지를 필터링할 수 있습니다. 예를 들어 로그 레벨을 info로 설정하면 info, warnerror 메시지만 기록됩니다.

사용자 지정 로그 형식 만들기

필요에 따라 사용자 지정 로그 형식을 만들 수 있습니다. 예를 들어 메타데이터를 추가하거나 로그 메시지 구조를 변경할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// logger.js

const { createLogger, format, transports } = require('winston');

const customFormat = format.combine(
format.colorize(),
format.timestamp(),
format.printf(({ timestamp, level, message, ...meta }) => {
return `${timestamp} ${level}: ${message} ${Object.keys(meta).length ? JSON.stringify(meta, null, 2) : ''}`;
})
);

const logger = createLogger({
level: 'info',
format: customFormat,
transports: [new transports.Console(), new transports.File({ filename: 'app.log' })],
});

module.exports = logger;
  • customFormat: timestamp, log level, message 및 optional metadata를 구조화된 로그 형식으로 결합합니다.

여러 전송에 로깅

Winston은 다양한 파일, 외부 로깅 서비스 또는 콘솔과 같은 여러 대상에 로깅할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// logger.js

const { createLogger, format, transports } = require('winston');

const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`)
),
transports: [
new transports.Console(),
new transports.File({ filename: 'app.log' }),
new transports.File({ filename: 'error.log', level: 'error' }),
],
});

module.exports = logger;
  • transports.File({ filename: ‘error.log’, level: ‘error’ }): 오류 메시지를 별도의 파일에 기록합니다.

사용자 정의 로그 레벨 생성

Winston에서 사용자 지정 로그 레벨을 직접 정의할 수 있습니다. 이 기능은 기본 레벨에서 다루지 않는 특정 요구 사항이 있는 경우에 유용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// logger.js

const { createLogger, format, transports, config } = require('winston');

const customLevels = {
levels: {
critical: 0,
error: 1,
warn: 2,
info: 3,
debug: 4,
},
colors: {
critical: 'red',
error: 'red',
warn: 'yellow',
info: 'green',
debug: 'blue',
},
};

const logger = createLogger({
levels: customLevels.levels,
level: 'info', // Set the default log level
format: format.combine(
format.colorize({ all: true }),
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`)
),
transports: [new transports.Console(), new transports.File({ filename: 'app.log' })],
});

winston.addColors(customLevels.colors);

module.exports = logger;
  • customLevels: 사용자 지정 로깅 레벨과 해당 색상을 정의합니다.
  • winston.addColors: 로깅 레벨에 사용자 지정 색상을 적용합니다.

일일 로그 파일에 로깅하기

winston-daily-rotate-file 전송을 사용하여 매일 새 로그 파일을 만들 수 있습니다.

winston-daily-rotate-file을 설치합니다:

1
npm install winston-daily-rotate-file

매일 로테이션 파일 전송을 구성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// logger.js

const { createLogger, format, transports } = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file');

const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`)
),
transports: [
new transports.Console(),
new DailyRotateFile({
filename: 'application-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
}),
],
});

module.exports = logger;
  • DailyRotateFile: 지정된 날짜 패턴으로 매일 새 로그 파일을 만듭니다.
  • zippedArchive: 이전 로그 파일을 압축합니다.
  • maxSize: 회전하기 전 로그 파일의 최대 크기입니다.
  • maxFiles: 로그 파일을 보관할 수 있는 최대 일수입니다.

Express 애플리케이션에서 Winston 사용

Winston을 Express 애플리케이션에 통합하여 HTTP 요청 및 오류에 대한 로깅을 처리합니다.

Express를 설치합니다.

1
npm install express

Winston으로 Express 서버를 설정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// server.js

const express = require('express');
const logger = require('./logger');

const app = express();
const PORT = process.env.PORT || 3000;

// HTTP 요청 로깅
app.use((req, res, next) => {
logger.http(`${req.method} ${req.url}`);
next();
});

app.get('/', (req, res) => {
res.send('Hello, World!');
});

// 오류 처리 미들웨어
app.use((err, req, res, next) => {
logger.error(err.message);
res.status(500).send('Internal Server Error');
});

app.listen(PORT, () => {
logger.info(`Server is running on http://localhost:${PORT}`);
});
  • HTTP 요청 로깅: 미들웨어는 logger.http를 사용하여 들어오는 모든 HTTP 요청을 기록합니다.
  • 오류 처리 미들웨어: logger.error를 사용하여 오류를 기록합니다.

결론

Winston을 Node.js 애플리케이션에 통합하면 코드를 보다 효과적으로 디버그, 모니터링 및 유지 관리하는 데 도움이 되는 강력하고 유연한 로깅 시스템을 만들 수 있습니다. 콘솔, 파일 또는 외부 서비스에 로깅해야 하는 경우 Winston의 풍부한 기능 세트는 Node.js 로깅을 위한 탁월한 선택입니다.

Share