import type { RenderResponse } from 'nitropack' import type { H3Event } from 'h3' import { defineNitroPlugin } from 'nitropack/runtime' import { getTrueClientIp } from '#layers/utils/apiUtil' function generateRequestId(): string { return Date.now().toString(36) + Math.random().toString(36).substring(2) } function getIpAddress(event: H3Event): string { return getTrueClientIp(event.node.req as any) || 'unknown' } export default defineNitroPlugin(nitroApp => { // 정적 파일 체크 함수 추가 const isStaticFile = (path: string): boolean => { return /\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$/i.test(path) } // 헬스체크 경로 체크 함수 추가 const isHealthCheck = (path: string): boolean => { return path === '/health' || path === '/api/healthz' } nitroApp.hooks.hook('request', event => { // 정적 파일 요청은 로깅 제외 if (isStaticFile(event.path) || isHealthCheck(event.path)) { return } // 상세 로깅을 위한 정보 수집 const startTime = Date.now() const userAgent = event.node.req.headers['user-agent'] || '' const method = event.method || '' const headers = JSON.stringify(event.node.req.headers, null, 2) const requestId = generateRequestId() const domain = event.node.req.headers.host || 'unknown' // if (process.env.NODE_ENV !== 'development') { console.log( `Request Info {"requestId":"${requestId}", "type":"request","method":"${method}","domain":"${domain}","url":"${event.path}","userIp":"${getIpAddress(event)}","userAgent":"${userAgent}", "headers" : "${headers}" }` ) // 요청 완료 후 응답 상태 코드 로깅 event.node.res.on('finish', () => { console.log( `Response Info {"requestId":"${requestId}","type":"response","method":"${method}","domain":"${domain}","url":"${event.path}","statusCode":${event.node.res.statusCode},"responseTime":"${Date.now() - startTime}ms","userIp":"${getIpAddress(event)}","userAgent":"${userAgent}","statusMessage":"${event.node.res.statusMessage}","responseHeader": ${JSON.stringify(event.node.res.getHeaders(), null, 2)}}` ) console.log( '===========================================================================================================================================================================================================================================================' ) }) // } }) nitroApp.hooks.hook('error', error => { console.error('[Nitro Error]', { message: error.message, stack: error.stack, timestamp: new Date().toISOString(), }) }) // 응답 헤더에서 'x-powered-by' 제거 nitroApp.hooks.hook( 'render:response', (response: Partial) => { if (response?.headers) { delete response.headers['x-powered-by'] } } ) })