[Node.js] Morgan과 에러 처리 미들웨어 구현하기

NYAONG·2024년 11월 25일

nodejs

목록 보기
10/11
post-thumbnail

Node.js 애플리케이션에서 Morgan과 에러 처리 미들웨어 구현하기

로그와 에러 처리는 애플리케이션 운영에 있어 핵심적인 역할을 한다. 이 포스트에서는 Node.jsExpress 기반 애플리케이션에서 Morgan을 사용한 요청 로그와 에러 처리 미들웨어를 어떻게 구현하는지, 그리고 그 각각의 역할을 알아보겠다.


1. Morgan: 요청 로그 미들웨어

Morgan은 HTTP 요청에 대한 로그를 남기는 미들웨어로, 애플리케이션에 어떤 요청이 들어오는지, 어떤 상태로 응답하는지 등을 쉽게 확인할 수 있다. 이를 통해 애플리케이션의 성능을 모니터링하고, 문제 발생 시 신속하게 대응할 수 있다.

1.1. Morgan 설정 코드 (morganMiddleware.js)

morganMiddleware.js 에서는 다음과 같이 Morgan을 설정하고 있다.


import morgan from "morgan";
import dotenv from "dotenv";
import momentTimeZone from "moment-timezone";
import {logger} from "#util/logger.js";

dotenv.config();
const timeZone = "Asia/Seoul";

// 날짜 형식 정의
morgan.token("date", (req, res, tz) => {
    return momentTimeZone().tz(tz).format("YYYY-MM-DD HH:mm:ss");
});

// 로그 포맷 설정 함수
function format() {
    const productionFormat = ':remote-addr - :remote-user [:date[' + timeZone + ']] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';
    const developmentFormat = ':remote-addr - :remote-user [:date[' + timeZone + ']] ":method :url HTTP/:http-version" :status :res[content-length] - :response-time ms';
    return process.env.NODE_ENV === "production" ? productionFormat : developmentFormat;
}

// 로그 출력 스트림 설정 (Winston을 통해 기록)
const stream = {
    write: (message) => {
        logger.info(`SERVER LOG: ${message.trim()}`);
    }
}

// 스킵 조건 설정 (production에서는 400 이하 상태 코드만 스킵)
const skip = (_, res) => {
    if (process.env.NODE_ENV === "production") {
        return res.statusCode < 400;
    }
    return false;
}

// Morgan 미들웨어 생성 및 내보내기
export const morganMiddleware = morgan(format(), {stream, skip});

1.2. 코드 설명

  1. 로그 포맷 설정
    • format() 함수는 현재 환경에 따라 로그 포맷을 결정한다. 개발 환경에서는 요청과 응답 시간까지 포함된 포맷을 사용하고, 프로덕션 환경에서는 기본적인 요청 정보만 기록한다.
    • 날짜moment-timezone을 이용해 "Asia/Seoul" 타임존으로 설정하고, 로그에 포함한다.
    • 나 같은 경우에는 timezone 설정을 하지 않을 시 로그 시간이 이상하게 설정되어서 별도로 timezone 설정을 하였다.
  2. 로그 출력 스트림 설정
    • 로그 메시지는 Winston을 사용해 기록된다. Winston은 강력한 로깅 도구로, 로그를 파일이나 콘솔에 기록할 수 있게 해준다. 여기서는 logger.info()를 사용해 Morgan 로그를 기록한다.
  3. 스킵 조건 설정
    • 프로덕션 환경에서는 응답 코드가 400 미만인 경우 로그를 스킵하도록 설정했다. 이로 인해 정상적인 요청에 대한 로그는 생략되고, 에러 요청만 기록되어 로그 파일을 더 깔끔하게 관리할 수 있다.
  4. Morgan 미들웨어 적용
    • 최종적으로 생성한 Morgan 미들웨어 (morganMiddleware)를 Express 애플리케이션에서 사용할 수 있도록 내보낸다.

2. 에러 처리 미들웨어

애플리케이션이 정상적으로 동작하지 않는 상황에서, 에러 처리는 사용자 경험을 보호하고 문제를 추적하는 데 필수적이다. 에러 처리 미들웨어는 모든 요청이 처리된 이후에 실행되며, 발생한 에러를 포착하고 적절하게 응답한다.

2.1. 에러 처리 미들웨어 (app.js)

app.js 에서는 아래와 같이 에러 처리 미들웨어를 구현하고 있다.


app.use((err, req, res, next) => {
    logger.error(`Middleware Error Process : ${err}`);

    res.status(500).json({
        success: false,
        timestamp: wbLib.getToday(),
        path: req.originalUrl,
        method: req.method,
        message: '서버에 문제가 발생하였습니다. ',
        errorCode: '500_INTERNAL_SERVER_ERROR!!',
    });
});

2.2. 코드 설명

  1. 에러 처리 흐름

    • 이 미들웨어는 네 가지 인자 (err, req, res, next)를 받는 에러 처리용 미들웨어이다.
    • 라우트 처리 중 에러가 발생하면 이 미들웨어가 호출된다.
  2. 에러 로그 기록

    • logger.error()를 통해 발생한 에러 내용을 기록한다. 이를 통해 운영 중 어떤 문제가 발생했는지 추적할 수 있다.
  3. 에러 응답

    • HTTP 상태 코드 500을 클라이언트에게 반환하며, JSON 형식으로 에러 정보를 제공한다.
    • timestamp: 에러 발생 시간을 기록하며, 이는 wbLib.getToday() 함수를 통해 가져온다.
    • wbLib.getToday()는 현재 시간을 지정한 스트링 형식으로 리턴하는 함수이며 별도로 관리하고있는 라이브러리의 함수이다.
    • wbLib.getToday()
    // wbLib.js
    
    export function getToday() {
        const now = new Date();
    
        const year = now.getFullYear();
        const month = String(now.getMonth() + 1).padStart(2, '0');
        const day = String(now.getDate()).padStart(2, '0');
        const hours = String(now.getHours()).padStart(2, '0');
        const minutes = String(now.getMinutes()).padStart(2, '0');
        const seconds = String(now.getSeconds()).padStart(2, '0');
    
        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    }
    • path, method: 요청 경로와 HTTP 메서드를 포함해 어떤 요청에서 에러가 발생했는지 쉽게 추적할 수 있다.
    • message와 *errorCode를 통해 사용자에게 친절한 에러 메시지를 제공한다.

3. Morgan과 에러 처리 미들웨어의 통합

이제 두 미들웨어가 어떻게 함께 동작하는지 알아보자.

3.1 애플리케이션의 흐름

  • 요청이 들어오면:
    1. Morgan 미들웨어가 먼저 실행되어 해당 요청의 정보를 기록한다.
    2. 요청이 정상적으로 처리될 경우, 요청 정보가 로그로 남는다.
    3. 만약 요청 처리 중 에러가 발생한다면, 해당 에러가 에러 처리 미들웨어로 전달된다.
    4. 에러 처리 미들웨어는 에러 내용을 로그로 기록하고, 사용자에게 HTTP 500 상태 코드에러 메시지를 반환한다.

3.2 운영 환경과 개발 환경에 따른 차별화

  • 개발 환경:
    • 모든 요청과 응답 시간이 기록된다.
    • 에러 로그는 상세히 남기고, 문제를 쉽게 디버깅할 수 있다.
  • 프로덕션 환경:
    • 400 이하 상태 코드는 로그로 남기지 않음으로써, 시스템 로그가 과도하게 쌓이는 것을 방지하고 에러 로그에 집중할 수 있다.
    • 에러 발생 시 사용자에게는 간단한 메시지를, 로그에는 상세한 에러 정보를 기록해 운영자가 문제를 빠르게 해결할 수 있도록 돕는다.

4. 마무리

이번 포스트에서는 Node.js 애플리케이션에서 Morgan에러 처리 미들웨어가 어떻게 동작하고 설정되어 있는지 살펴보았다. 이 두 미들웨어는 각각 요청 로그 관리에러 처리에 중요한 역할을 하며, 함께 사용함으로써 애플리케이션의 안정성을 높이고 문제 발생 시 신속하게 대응할 수 있게 돕는다.

  • Morgan은 애플리케이션의 요청 흐름을 기록해, 요청의 상세한 내역을 알 수 있게 해준다.
  • 에러 처리 미들웨어는 발생한 에러를 정확하게 기록하고 사용자에게 적절한 응답을 제공함으로써, 애플리케이션의 신뢰성을 높인다.

자료참조 : inpa dev
https://inpa.tistory.com/entry/EXPRESS-%F0%9F%93%9A-morgan-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4

profile
야옹

0개의 댓글