---
name: node-debug-logging-middleware
description: Node.js Express/Koa 앱에 상세 디버깅 로그를 출력하는 미들웨어를 추가합니다. 미들웨어 로깅, 요청 추적, Node.js 디버깅 요청 시 활성화됩니다.
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
---

# Node Debug Logging Middleware

Node.js 웹 애플리케이션에 상세한 디버깅 로그 미들웨어를 추가하는 스킬입니다.

## 기능

### 로깅 대상
- HTTP 요청/응답 상세 정보
- 요청 바디 및 쿼리 파라미터
- 응답 시간 및 상태 코드
- 에러 스택 트레이스
- 메모리 사용량

### 지원 프레임워크
- Express.js
- Koa.js
- Fastify
- NestJS

### 출력 옵션
- 콘솔 (개발환경)
- 파일 (프로덕션)
- 외부 서비스 (Sentry, Datadog 등)

## Express.js 미들웨어

```javascript
const fs = require('fs');
const path = require('path');

/**
 * 디버그 로깅 미들웨어 생성
 * @param {Object} options - 설정 옵션
 * @param {string} options.logDir - 로그 파일 디렉토리
 * @param {boolean} options.logBody - 요청/응답 바디 로깅 여부
 * @param {boolean} options.logHeaders - 헤더 로깅 여부
 * @param {number} options.bodyLimit - 바디 로깅 최대 크기 (bytes)
 */
function createDebugLogger(options = {}) {
  const {
    logDir = './logs',
    logBody = true,
    logHeaders = false,
    bodyLimit = 10000
  } = options;

  // 로그 디렉토리 생성
  if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir, { recursive: true });
  }

  const getLogStream = () => {
    const date = new Date().toISOString().split('T')[0];
    const logFile = path.join(logDir, `debug-${date}.log`);
    return fs.createWriteStream(logFile, { flags: 'a' });
  };

  return (req, res, next) => {
    const startTime = Date.now();
    const requestId = Math.random().toString(36).substring(7);

    // 요청 정보 수집
    const requestLog = {
      id: requestId,
      timestamp: new Date().toISOString(),
      method: req.method,
      url: req.originalUrl,
      ip: req.ip || req.connection.remoteAddress,
      userAgent: req.get('User-Agent')
    };

    if (logHeaders) {
      requestLog.headers = req.headers;
    }

    if (logBody && req.body && Object.keys(req.body).length > 0) {
      const bodyStr = JSON.stringify(req.body);
      requestLog.body = bodyStr.length > bodyLimit
        ? bodyStr.substring(0, bodyLimit) + '...[truncated]'
        : req.body;
    }

    // 응답 가로채기
    const originalSend = res.send;
    let responseBody;

    res.send = function(body) {
      responseBody = body;
      return originalSend.call(this, body);
    };

    // 응답 완료 시 로깅
    res.on('finish', () => {
      const duration = Date.now() - startTime;

      const logEntry = {
        ...requestLog,
        response: {
          statusCode: res.statusCode,
          duration: `${duration}ms`,
          contentLength: res.get('Content-Length')
        }
      };

      if (logBody && responseBody && res.statusCode >= 400) {
        try {
          const bodyStr = typeof responseBody === 'string'
            ? responseBody
            : JSON.stringify(responseBody);
          logEntry.response.body = bodyStr.length > bodyLimit
            ? bodyStr.substring(0, bodyLimit) + '...[truncated]'
            : responseBody;
        } catch (e) {
          // 바디 파싱 실패 무시
        }
      }

      // 콘솔 출력
      const color = res.statusCode >= 500 ? '\x1b[31m'
        : res.statusCode >= 400 ? '\x1b[33m'
        : '\x1b[32m';
      console.log(
        `${color}[${requestLog.timestamp}] ${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms\x1b[0m`
      );

      // 파일 출력
      const stream = getLogStream();
      stream.write(JSON.stringify(logEntry) + '\n');
      stream.end();
    });

    next();
  };
}

module.exports = createDebugLogger;
```

## 사용법

```javascript
const express = require('express');
const createDebugLogger = require('./middleware/debugLogger');

const app = express();

// JSON 파싱 (로깅 전에 설정)
app.use(express.json());

// 디버그 로거 적용
app.use(createDebugLogger({
  logDir: './logs',
  logBody: true,
  logHeaders: process.env.NODE_ENV === 'development',
  bodyLimit: 5000
}));

// 라우트 정의
app.get('/api/users', (req, res) => {
  res.json({ users: [] });
});

app.listen(3000);
```

## Koa.js 버전

```javascript
async function koaDebugLogger(ctx, next) {
  const startTime = Date.now();

  console.log(`--> ${ctx.method} ${ctx.url}`);

  try {
    await next();
  } catch (err) {
    console.error(`[ERROR] ${err.message}`);
    throw err;
  }

  const duration = Date.now() - startTime;
  console.log(`<-- ${ctx.method} ${ctx.url} ${ctx.status} ${duration}ms`);
}

// 사용
app.use(koaDebugLogger);
```

## 로그 출력 예시

```json
{
  "id": "a1b2c3",
  "timestamp": "2024-01-15T10:30:45.123Z",
  "method": "POST",
  "url": "/api/users",
  "ip": "192.168.1.100",
  "userAgent": "Mozilla/5.0...",
  "body": { "name": "홍길동", "email": "hong@example.com" },
  "response": {
    "statusCode": 201,
    "duration": "45ms",
    "contentLength": "156"
  }
}
```

## 사용 예시

```
Express 앱에 요청 로깅 미들웨어를 추가해줘
API 호출을 디버깅하기 위한 로그를 설정해줘
Node.js 서버에 상세 로깅을 추가해줘
```

## 출처
Original skill from skills.cokac.com
