# All files / middlewares errorHandler.js

0% Statements 0/25
0% Branches 0/20
0% Functions 0/5
0% Lines 0/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102

     /**
     * 에러 핸들러 미들웨어
     *
     * 애플리케이션 전역 에러를 처리하는 Express 미들웨어
     *
     * @author TK-FB-Project
     * @since 2025-12-11
     */

    const { AppError } = require('../utils/errors');
    const logger = require('../utils/logger');

    /**
     * 에러 응답 포맷터
     */
    const formatErrorResponse = (error, req) => {
      const response = {
        success: false,
        error: {
          message: error.message || '알 수 없는 오류가 발생했습니다',
          code: error.code || 'INTERNAL_ERROR'
        },
        timestamp: new Date().toISOString()
      };

      // 검증 에러의 경우 상세 정보 포함
      if (error.details) {
        response.error.details = error.details;
      }

      // 개발 환경에서만 스택 트레이스 포함
      if (process.env.NODE_ENV === 'development') {
        response.error.stack = error.stack;
        response.request = {
          method: req.method,
          url: req.originalUrl,
          ip: req.ip,
          user: req.user?.username || 'anonymous'
        };
      }

      return response;
    };

    /**
     * 에러 핸들러 미들웨어
     */
    const errorHandler = (error, req, res, next) => {
      // AppError가 아닌 경우 변환
      if (!(error instanceof AppError)) {
        error = new AppError(
          error.message || '서버 내부 오류가 발생했습니다',
          500,
          'INTERNAL_ERROR'
        );
      }

      // 로깅
      if (error.statusCode >= 500) {
        logger.error(error.message, {
          code: error.code,
          stack: error.stack,
          url: req.originalUrl,
          method: req.method,
          user: req.user?.username || 'anonymous'
        });
      } else {
        logger.warn(error.message, {
          code: error.code,
          url: req.originalUrl,
          method: req.method,
          user: req.user?.username || 'anonymous'
        });
      }

      // 응답
      const response = formatErrorResponse(error, req);
      res.status(error.statusCode).json(response);
    };

    /**
     * 비동기 함수 래퍼 (에러 자동 처리)
     */
    const asyncHandler = (fn) => {
      return (req, res, next) => {
        Promise.resolve(fn(req, res, next)).catch(next);
      };
    };

    /**
     * 404 Not Found 핸들러
     */
    const notFoundHandler = (req, res, next) => {
      const { NotFoundError } = require('../utils/errors');
      next(new NotFoundError(`경로를 찾을 수 없습니다: ${req.originalUrl}`));
    };

    module.exports = {
      errorHandler,
      asyncHandler,
      notFoundHandler
    };