// utils/responseFormatter.js - 통합 응답 포맷터 /** * 성공 응답 포맷터 */ const successResponse = (data = null, message = '요청이 성공적으로 처리되었습니다.', meta = null) => { const response = { success: true, message, timestamp: new Date().toISOString() }; if (data !== null) { response.data = data; } if (meta) { response.meta = meta; } return response; }; /** * 페이지네이션 응답 포맷터 */ const paginatedResponse = (data, totalCount, page = 1, limit = 10, message = '데이터 조회 성공') => { const totalPages = Math.ceil(totalCount / limit); return successResponse(data, message, { pagination: { currentPage: parseInt(page), totalPages, totalCount: parseInt(totalCount), limit: parseInt(limit), hasNextPage: page < totalPages, hasPrevPage: page > 1 } }); }; /** * 리스트 응답 포맷터 */ const listResponse = (items, message = '목록 조회 성공') => { return successResponse(items, message, { count: items.length }); }; /** * 생성 응답 포맷터 */ const createdResponse = (data, message = '데이터가 성공적으로 생성되었습니다.') => { return successResponse(data, message); }; /** * 업데이트 응답 포맷터 */ const updatedResponse = (data = null, message = '데이터가 성공적으로 업데이트되었습니다.') => { return successResponse(data, message); }; /** * 삭제 응답 포맷터 */ const deletedResponse = (message = '데이터가 성공적으로 삭제되었습니다.') => { return successResponse(null, message); }; /** * 통계 응답 포맷터 */ const statsResponse = (stats, period = null, message = '통계 조회 성공') => { const meta = {}; if (period) { meta.period = period; } meta.generatedAt = new Date().toISOString(); return successResponse(stats, message, meta); }; /** * 인증 응답 포맷터 */ const authResponse = (user, token, redirectUrl = null, message = '로그인 성공') => { const data = { user, token }; if (redirectUrl) { data.redirectUrl = redirectUrl; } return successResponse(data, message); }; /** * 파일 업로드 응답 포맷터 */ const uploadResponse = (fileInfo, message = '파일 업로드 성공') => { return successResponse({ filename: fileInfo.filename, originalName: fileInfo.originalname, size: fileInfo.size, mimetype: fileInfo.mimetype, path: fileInfo.path, uploadedAt: new Date().toISOString() }, message); }; /** * 헬스체크 응답 포맷터 */ const healthResponse = (status = 'healthy', services = {}) => { return successResponse({ status, services, uptime: process.uptime(), memory: process.memoryUsage(), version: process.version }, `서버 상태: ${status}`); }; /** * Express 응답 확장 미들웨어 */ const responseMiddleware = (req, res, next) => { // 성공 응답 헬퍼들을 res 객체에 추가 res.success = (data, message, meta) => { return res.json(successResponse(data, message, meta)); }; res.paginated = (data, totalCount, page, limit, message) => { return res.json(paginatedResponse(data, totalCount, page, limit, message)); }; res.list = (items, message) => { return res.json(listResponse(items, message)); }; res.created = (data, message) => { return res.status(201).json(createdResponse(data, message)); }; res.updated = (data, message) => { return res.json(updatedResponse(data, message)); }; res.deleted = (message) => { return res.json(deletedResponse(message)); }; res.stats = (stats, period, message) => { return res.json(statsResponse(stats, period, message)); }; res.auth = (user, token, redirectUrl, message) => { return res.json(authResponse(user, token, redirectUrl, message)); }; res.upload = (fileInfo, message) => { return res.json(uploadResponse(fileInfo, message)); }; res.health = (status, services) => { return res.json(healthResponse(status, services)); }; next(); }; module.exports = { successResponse, paginatedResponse, listResponse, createdResponse, updatedResponse, deletedResponse, statsResponse, authResponse, uploadResponse, healthResponse, responseMiddleware };