이번엔 서버에서 발생하는 모든 요청,에러 등에 대한 log를 기록하는 logger를 만들어 보았다.
winton - npm 
log를 기록하는데에 여러가지 라이브러리를 사용할 수 있지만, 다운로드 조회수도 많고 용량도 적은 winston을 사용하기로 하였다.
class WinstonLogger {
	private static instance: WinstonLogger;
	private readonly logger: Logger;
	static getInstance(): WinstonLogger {
		if (!WinstonLogger.instance) {
			WinstonLogger.instance = new WinstonLogger();
		}
		return WinstonLogger.instance;
	}
}
logger는 모든 api에서 쓰이고 사용처도 다양하기 때문에 각 파일에서 인스턴스를 한번만 생성하도록 싱글턴 방식으로 제작하였다.
private constructor() {
  const infoLog = new WinstonDaily({
    level: 'info',
    datePattern: 'YYYY-MM-DD', // 파일 날짜 형식
    dirname: `/tmp/logs/info`, // 파일 경로
    filename: `%DATE%.info.log`, // 파일 이름 형식 2020-05-28.info.log
  });
  const httpLog = new WinstonDaily({
    level: 'http', // http 보다 낮은애들은 모두 파일에 저장
    datePattern: 'YYYY-MM-DD',
    dirname: `/tmp/logs/http`,
    filename: `%DATE%.info.log`,
  });
  const errorLog = new WinstonDaily({
    level: 'error',
    datePattern: 'YYYY-MM-DD',
    dirname: `/tmp/logs/error`,
    filename: `%DATE%.error.log`,
  });
  const exceptionLog = new WinstonDaily({
    level: 'error',
    datePattern: 'YYYY-MM-DD',
    dirname: `/tmp/logs/exception`,
    filename: `%DATE%.exception.log`,
  });
  const terminalLog = new transports.Console({
    level: 'debug',
    format: format.combine(format.colorize(), format.timestamp(), logFormat),
  });
  let transport;
  let exceptionHandler;
  if (process.env.NODE_ENV === 'production') {
    transport = [infoLog, errorLog, httpLog];
    exceptionHandler = exceptionLog;
  } else if (process.env.NODE_ENV === 'development') {
    transport = [infoLog, errorLog, httpLog];
    exceptionHandler = exceptionLog;
  } else {
    transport = terminalLog;
    exceptionHandler = terminalLog;
  }
  this.logger = createLogger({
    format: format.combine(format.timestamp(), logFormat),
    transports: transport,
    exceptionHandlers: exceptionHandler,
  });
}
또한 환경변수에 따라 나누어 local개발 환경에선 로그가 터미널에만 찍히도록하고, production과 development시에는 파일에 저장되도록 수정하였다.
app.use((req, res, next) => {
	logger.http(`[${req.method}] ${req.url}`);
	next();
});
app.use를 app.ts 상단에 두어 들어오는 요청에 대해 모두 log가 남도록 하였다.
이렇게 하면 요청마다 method와 api경로가 기록되게 된다.
실서버에서는 이렇게 저장된 로그 파일을 다른 곳으로 서빙할 것인데, 그건 다음에 알아보자.