[미들웨어]글로벌 에러 핸들러 - gyunam-bark/nb02-how-do-i-look-team1 GitHub Wiki

글로벌 에러핸들러 미들웨어 설계

설계 개요

  1. DEV(개발), SERVICE(사용자)에 따른 반환 객체 구분

  2. 가능한 많은 statusCode 적용

  3. 비표준 statusCode 가 들어올 경우 500 으로 예외처리

적용 예시

import errorHandler from 'error-middleware.js';

// ...app.use(routes)

app.use(errorHandler);

지원 상태 코드

MDN 참고

상태 코드 메세지
100 Continue
101 Switching Protocols
102 Processing
300 Multiple Chocies
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
307 Temporary Redirect
308 Permanent Redirect
400 Bad Request
401 Unauthorized
403 Forbidden
405 Method Not Allowed
409 Conflict
410 Gone
415 Unsupported Media Type
422 Unprocessable Entity
429 Too Many Requests
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout

치명적인 서버 에러가 발생했을 때 에러 핸들러

(TODO)

  • index.js, server.js, app.js 등의 진입점 파일 최상단에 위치
  • Node.js 프로세스 레벨의 글로벌 에러 핸들러
  • uncaughtException: try-catch로 잡히지 않은 동기 에러
process.on('uncaughtException', err => {
    console.error('--- UNCAUGHT EXCEPTION! 서버가 강제 종료됩니다 ---');
    console.error('에러 종류:', err.name);
    console.error('에러 메시지:', err.message);
    console.error('발생 위치 (스택):', err.stack);
    // 실제 서비스에서는 로깅 시스템 (e.g., Winston, Pino)에 기록 후 알림
    process.exit(1); // 프로세스 즉시 종료
});

치명적인 서버 에러 테스트 코드

(TODO)

// uncaughtException 발생 테스트 코드 (동기 코드 오류)
// 1. 정의되지 않은 변수 참조 (ReferenceError)
function triggerReferenceError() {
    console.log(nonExistentVariable); // 'nonExistentVariable'은 정의되지 않음
}

// 2. null 또는 undefined 값의 속성에 접근 (TypeError)
function triggerTypeError() {
    const obj = null;
    console.log(obj.property); // null의 속성에 접근 시도
}

// 3. 존재하지 않는 함수 호출 (TypeError)
function triggerFunctionError() {
    nonExistentFunction(); // 정의되지 않은 함수 호출
}

// --- 테스트를 위한 호출 ---
// 아래 함수 중 하나만 주석을 해제하고 실행하여 테스트하세요.
// triggerReferenceError();
// triggerTypeError();
// triggerFunctionError();

// 이 라인은 위의 에러가 발생하면 실행되지 않습니다.
console.log('App is running smoothly (if no error occurred).');

// Express 앱과 함께 테스트하는 경우:
// const express = require('express');
// const app = express();
//
// app.get('/trigger-uncaught-error', (req, res) => {
//     console.log(thisVariableDoesNotExist); // 요청 처리 중 동기 에러 발생
//     res.send('You should not see this response.');
// });
//
// const port = 3000;
// app.listen(port, () => {
//     console.log(`Server running on port ${port}`);
// });
//unhandledRejection 발생 테스트 코드 (비동기 Promise 오류)
// 1. .catch() 핸들러가 없는 Promise 거부
function triggerUnhandledPromiseRejection() {
    new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('네트워크 연결 실패!')); // Promise 거부
        }, 100); // 100ms 후 발생
    });
}

// 2. async/await 함수 내에서 try-catch가 없는 Promise 거부
async function triggerAsyncError() {
    await new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('비동기 작업 중 치명적인 오류 발생!'));
        }, 200); // 200ms 후 발생
    });
    console.log('This line will not be reached.'); // 에러 발생 시 이 줄은 실행되지 않음
}


// --- 테스트를 위한 호출 ---
// 아래 함수 중 하나만 주석을 해제하고 실행하여 테스트하세요.
// triggerUnhandledPromiseRejection();
// triggerAsyncError();

console.log('App is running (waiting for promise rejection).');

// Express 앱과 함께 테스트하는 경우:
// const express = require('express');
// const app = express();
//
// app.get('/trigger-unhandled-rejection', async (req, res) => {
//     await Promise.reject(new Error('이 Promise는 처리되지 않습니다.'));
//     res.send('You should not see this response.');
// });
//
// const port = 3000;
// const server = app.listen(port, () => {
//     console.log(`Server running on port ${port}`);
// });
//
// process.on('unhandledRejection', (err, promise) => {
//     console.error('--- 🚨 UNHANDLED REJECTION CAUGHT IN EXPRESS! 🚨 ---');
//     console.error(err);
//     server.close(() => { // 서버를 우아하게 종료
//         process.exit(1);
//     });
// });

치명적인 서버 에러가 발생했을 때 에러 (종료 확인):

(TODO)

테스트 코드

// 테스트용 에러 유도 라우트
app.get('/error', (req, res, next) => {
  const error = new Error();
  // 이 에러 코드 숫자만 바꿔가면서 하면 됩니다.
  error.statusCode = 400;
  next(error);
});

// 글로벌 에러 핸들러
app.use(errorHandler);

미들웨어 코드