로그 처리
winston 깃 허브 문서 : https://github.com/winstonjs/winston
소스 : https://github.com/braverokmc79/login-lecture
1. 설치
$ npm install winston $ npm install winston-daily-rotate-file $ npm install dotenv
2.env 설정
개발시 dev , 운영서버 반영시 production
.env
NODE_ENV ="dev"
app.js 에 추가
const dotenv = require("dotenv");
dotenv.config();
3. winston.log.js 파일과 logger.js 파일을 config 디렉토리에 저장한다.
1) src/config/winston.log.js
const winston = require("winston");
const winstonDaily = require("winston-daily-rotate-file");
const { combine, timestamp, printf, colorize, label } = winston.format;
const logDir = "logs"; // logs 디렉토리 하위에 로그 파일 저장
const logFormat = printf((info) => {
return `${info.timestamp} ${info.level}: ${info.message}`;
});
const productionWinstonDail = [
new winstonDaily({
level: "warn",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/warn",
filename: `%DATE%.warn.log`, // file 이름 날짜로 저장
maxFiles: 30, // 30일치 로그 파일 저장
zippedArchive: true,
}),
// error 레벨 로그를 저장할 파일 설정
new winstonDaily({
level: "error",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/error", // error.log 파일은 /logs/error 하위에 저장
filename: `%DATE%.error.log`,
maxFiles: 30,
zippedArchive: true,
})
]
const devWinstonDail = [...productionWinstonDail];
devWinstonDail.push( // info 레벨 로그를 저장할 파일 설정
new winstonDaily({
level: "info",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/info",
filename: `%DATE%.info.log`, // file 이름 날짜로 저장
maxFiles: 30, // 30일치 로그 파일 저장
zippedArchive: true,
}));
/*
* Log Level
* error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
*/
const winstonLog = winston.createLogger({
format: combine(
timestamp({
format: "YYYY-MM-DD HH:mm:ss",
}),
logFormat
),
transports: process.env.NODE_ENV !== "production" ? devWinstonDail : productionWinstonDail
});
winstonLog.stream = {
// morgan wiston 설정
write: (message) => {
logger.info(message);
},
};
// Production 환경이 아닌 경우(dev 등) 배포 환경에서는
// 최대한 자원을 안잡아 먹는 로그를 출력해야함
if (process.env.NODE_ENV !== "production") {
winstonLog.add(
// new winston.transports.Console({
// format: combine(
// colorize({ all: true }), // console 에 출력할 로그 컬러 설정 적용함
// logFormat // log format 적용
// ),
// });
new winston.transports.Console({
name: 'debug-console',
colorize: true,
level: "debug",
format: combine(
label({ label: '백엔드 맛보기' }),
colorize(),
timestamp({
format: "YYYY-MM-DD HH:mm:ss"
}),
printf(
info => `${info.timestamp} | [${info.label}] | (${info.level}) : ${info.message} `
)
),
showlevel: true,
json: false,
})
);
}
module.exports = winstonLog;
2) src/config/logger.js
const winstonLog = require("./winston.log");
const parseurl = require('parseurl');
//로그 처리 및 결과값 반환처리
const logger = (response, req, res) => {
const url = {
method: req.method,
path: parseurl(req).pathname,
status: (response !== null ? response.err : false) ? 400 : 200,
};
if (response === null) {
winstonLog.info(`${url.method} | ${url.path} 화면 | Request Query : ${JSON.stringify(req.query)} `);
return;
}
let result = false;
if (response.err) {
winstonLog.error(
`${url.method} ${url.path} ${url.status} Response: ${response.success} | Request Body : ${JSON.stringify(req.body)} | msg | ${response.err}`
);
result = true;
} else {
if (url.method === "GET") {
winstonLog.info(`${url.method} | ${url.path} 화면 | Request Query : ${JSON.stringify(req.query)} | msg | ${response.msg || ""} `);
} else {
winstonLog.info(
`${url.method} ${url.path} ${url.status} Response: ${response.success} | Request Body : ${JSON.stringify(req.body)} | msg | ${response.msg || ""}`
);
}
result = false;
}
if (result) return res.status(400).json({ msg: response.err.toString() });
return res.status(200).json(response);
};
module.exports = logger;
3) logs 폴더를 프로젝트 app.js 와 동일한 루트 경로에 생성한다.
4. 사용방법
1) 모델에서 에러반환 처리 또는 try~catch 처리로 에러 또는 메시지 반환 처리를 한다.
src/models/UserStorage.js
static async getUserInfo(id) {
return new Promise((resolove, rejects) => {
const query = "SELECT * FROM users WHERE id= 6 ?";
db.query(query, [id], function (err, data) {
if (err) return rejects(err);
resolove(data.length === 0 ? false : data[0]);
})
});
}
src/models/User.js
async login() {
try {
const client = this.body;
const { id, psword } = await UserStorage.getUserInfo(client.id);
if (id) {
if (id === client.id && psword === client.psword) {
return { success: true };
}
return { success: false, msg: "비밀번호가 틀렸습니다." };
}
return { success: false, msg: "존재하지 않는 아이디 입니다." };
} catch (err) {
return { success: false, err }
}
}
2) 컨트롤에서 get 방식 post 방식에 따라 알맞게 logger 함수를 사용한다.
컨트롤 코드 예
"use strict"
const User = require("../../models/User");
const logger = require("../../config/logger");
const output = {
home: (req, res) => {
logger(null, req, res);
res.render("home/index");
},
login: (req, res) => {
logger(null, req, res);
res.render("home/login");
},
register: (req, res) => {
logger(null, req, res);
res.render("home/register");
}
}
const process = {
login: async (req, res) => {
const user = new User(req.body);
const response = await user.login();
logger(response, req, res);
},
register: async (req, res) => {
const user = new User(req.body);
const response = await user.register();
logger(response, req, res);
}
}
module.exports = {
output,
process
}
3) 반환처리 방법은 프로젝트에 맞게 logger.js 파일을 수정해서 사용할것














댓글 ( 4)
댓글 남기기