오늘의 명언
“ 당신은 소프트웨어 품질을 추구할 수도 있고, 포인터 연산을 할 수도 있다. 그러나 두 개를 동시에 할 수는 없다. ”
-
베르트랑 마이어 (Bertrand Meyer)
300x250
환경변수 config 설정
애플리케이션이 실행될 때 특정 값을 넘길수 있는 변수 설정을 하기 위해
※env 폴더안에 개발, 배포 파일을 만들어줍니다.
PORT = 5000 //서버 포트
LOG_LEVEL = silly //winston(로그기록) 레벨 단위
MYSQL_HOST = localhost // mysql DB HOST
MYSQL_USER = root // mysql USER
MYSQL_PASSWORD = admin // mysql password
MYSQL_DATABASE = testDB // mysql dataBase
위 내용은 각자 설정에 따라 다릅니다 본인의 설정에 맞게 적어줍니다.
env 환경변수 설정이 완료되었다면, config 폴더에 index.js 파일을 만들어줍니다.
- ES6 기준으로 dirname과 filename은 아래처럼 import를 이용하면 됩니다.
import dotenv from 'dotenv'
import path from 'path'
import {fileURLToPath} from 'url'
import logger from '../loaders/logger.js'
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
if(process.env.NODE_ENV ==='production')
{
logger.info('production mode')
dotenv.config({ path: path.join(__dirname, '../env/.env.production') })
}
else if(process.env.NODE_ENV === 'development')
{
logger.info('development mode')
dotenv.config({ path: path.join(__dirname, '../env/.env.development') })
}
else{
throw new Error("Couldn't find .env file")
}
export default {
server_port: process.env.PORT, //서버 포트
api: {
prefix: '/', //라우터 접두사 ( localhost:5000/api로 기본설정 원할 시-> '/api' 설정하면됨)
},
//DB config
mysql_config:{
HOST:process.env.MYSQL_HOST,
USER:process.env.MYSQL_USER,
PASSWORD:process.env.MYSQL_PASSWORD,
dialect:'mysql',
DB:process.env.MYSQL_DATABASE,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
}
Loader 설정
로더 폴더에서 위에 파일들을 만들어준다. (추후 여러가지 로더모듈이 생긴다. ex) mysql등 )
- express (express 관련 설정)
- loggers (서버 로그를 위해 winston 설정)
- morganMiddleware (http 로그 설정)
// loaders/express.js
import express from 'express'
import path from 'path'
import cookieParser from 'cookie-parser'
import config from '../config/index.js'
import cors from 'cors'
import {fileURLToPath} from 'url'
import morganMiddleware from "./morganMiddleware.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default (app) =>{
const whitelist = ['http://localhost:3000'] //클라이언트 (프론트 URL)
//cors 옵션
const corsOptions = {
origin: function (origin, callback) {
const isWhitelisted = whitelist.indexOf(origin) !== -1
callback(null, isWhitelisted)
},
credentials: true,
}
app.use(cors(corsOptions))
app.use(express.json()) //json 형식
app.use(express.urlencoded({ extended: true })) //x-www-form-urlencoded 형식
app.use(cookieParser()) //쿠키사용
app.use(express.static(path.join(__dirname, '..', 'public')))
app.use(morganMiddleware) //morgan 미들웨어 설정
}
- winston 설정 파일 logger.js를 만들어줍니다.
// loaders/logger.js
import winston from 'winston'
import winstonDaily from 'winston-daily-rotate-file'
import process from 'process'
const {combine,timestamp,label,printf,colorize } = winston.format
//루트경로
const logDir = `${process.cwd()}/logs`;
//레벨
const levels = {
error: 0,
warn: 1,
info: 2,
http: 3,
debug: 4
}
//색상
const colors = {
error: 'red',
warn: 'yellow',
info: 'green',
http: 'magenta',
debug: 'blue'
}
winston.addColors(colors); // 색상 적용
const level = () => {
const env = process.env.NODE_ENV || 'development'
const isDevelopment = env === 'development'
return isDevelopment ? 'debug' : 'http'
}
//로그 포맷
const logFormat = combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
label({label:'Server Logs'}),
printf((info) => {
if (info.stack) {
return `${info.timestamp} ${info.level}: ${info.message} \n Error Stack: ${info.stack}`
}
return `${info.timestamp} ${info.level}: ${info.message}`
})
)
// 콘솔에 찍힐 때는 색깔을 구변해서 로깅해주자.
const consoleOpts = {
handleExceptions: true,
level: process.env.NODE_ENV === 'production' ? 'error' : 'debug',
format: combine(
colorize({ all: true }),
timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' })
)
}
const transports = [
new winston.transports.Console(consoleOpts),
new winstonDaily({
level: 'info', // info 레벨 로그를 저장할 파일 설정
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
filename: `%DATE%.log`, // %DATE% = 위에서 설정한 datePattern 이 들어감
dirname: logDir,
maxFiles: 30, // 30일치 로그 파일 저장
}),
new winstonDaily({
level: 'error', // error 레벨 로그를 저장할 파일 설정
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
filename: `%DATE%.error.log`,
dirname: logDir + '/error', // error.log 파일은 /logs/error 하위에 저장
maxFiles: 30,
}),
]
const logger = winston.createLogger({
level:level(),
levels,
format:logFormat,
transports
})
export default logger
차후 서버 실행후 로그확인을 하기위해선 아래와 같은 경로에서 확인합니다.
관련 로그를 기록을 위한 morganMiddleware.js 파일로 winston과 morgan을 연결합니다.
// loaders/morganMiddleware
import morgan from 'morgan'
import logger from './logger.js'
const format = () => {
return process.env.NODE_ENV === 'production' ? 'combined' : 'dev';
};
// 로그 작성을 위한 Output stream옵션.
const stream = { write: (message) => logger.http(message) }
// 로깅 스킵 여부 (만일 배포환경이면, 코드가 400 미만라면 함수를 리턴해 버려서 로그 기록 안함. 코드가 400 이상이면 로그 기록함)
const skip = (_, res) => {
if (process.env.NODE_ENV === 'production') {
return res.ststusCode < 400;
}
return false;
};
const morganMiddleware = morgan(format(), { stream, skip });
export default morganMiddleware
위와 같이 3개의 파일을 작성완료하였으면 index.js 파일로 묶어줍니다.
// index.js
import logger from './logger.js'
import expressLoader from './express.js'
export default (app)=>{
logger.info('express Loader Success!!')
expressLoader(app)
}
루트 경로 app.js로 이동합니다.
// app.js
import express from 'express'
import config from './config/index.js'
import loaders from "./loaders/index.js";
import logger from "./loaders/logger.js"
const app = express()
loaders(app)
const server = app.listen(config.server_port,()=>{
logger.info(`
🛡️ Server listening on port: ${config.server_port} 🛡️
`)
}) .on('error', (err) => {
logger.error(err)
process.exit(1)
})
export default { server }
위와 같이 설정을 끝냈다면 밑에 명령어로 실행합니다.
"start": "cross-env NODE_ENV=development nodemon app.js",
위와같이 express가 실행이 됩니다.
콘솔로 로그 표시가 잘되는지와 logs 폴더에 로그가 잘 나오는지 확인하시면 끝입니다.
반응형
잘못된 내용이 있으면 댓글 부탁드립니다. 감사합니다.