import axios from 'axios'; // 환경변수에서 API URL을 읽음 (Vite 기준) const API_BASE_URL = import.meta.env.VITE_API_URL || (import.meta.env.DEV ? 'http://localhost:8000' : 'http://localhost:8000'); console.log('API Base URL:', API_BASE_URL); console.log('Environment:', import.meta.env.MODE); // axios 인스턴스 생성 export const api = axios.create({ baseURL: API_BASE_URL, timeout: 30000, // 30초로 증가 headers: { 'Content-Type': 'application/json', }, }); // 재시도 로직을 위한 설정 const MAX_RETRIES = 3; const RETRY_DELAY = 1000; // 1초 // 재시도 함수 const retryRequest = async (config, retries = MAX_RETRIES) => { try { return await api(config); } catch (error) { if (retries > 0 && (error.code === 'ECONNABORTED' || error.response?.status >= 500)) { console.log(`API 재시도 중... (${MAX_RETRIES - retries + 1}/${MAX_RETRIES})`); await new Promise(resolve => setTimeout(resolve, RETRY_DELAY)); return retryRequest(config, retries - 1); } throw error; } }; // 공통 에러 핸들링 (예시) api.interceptors.response.use( response => response, error => { console.error('API Error:', { url: error.config?.url, method: error.config?.method, status: error.response?.status, data: error.response?.data, message: error.message }); // 필요시 에러 로깅/알림 등 추가 return Promise.reject(error); } ); // 예시: 파일 업로드 (multipart/form-data) export function uploadFile(formData, options = {}) { const config = { method: 'post', url: '/upload', data: formData, headers: { 'Content-Type': 'multipart/form-data' }, ...options, }; return retryRequest(config); } // 예시: 자재 목록 조회 export function fetchMaterials(params) { return api.get('/files/materials', { params }); } // 예시: 자재 요약 통계 export function fetchMaterialsSummary(params) { return api.get('/files/materials/summary', { params }); } // 파일 목록 조회 export function fetchFiles(params) { return api.get('/files', { params }); } // 파일 삭제 export function deleteFile(fileId) { return api.delete(`/files/${fileId}`); } // 예시: Job 목록 조회 export function fetchJobs(params) { return api.get('/jobs', { params }); } // 예시: Job 생성 export function createJob(data) { return api.post('/jobs', data); } // 리비전 비교 export function compareRevisions(jobNo, filename, oldRevision, newRevision) { return api.get('/files/materials/compare-revisions', { params: { job_no: jobNo, filename: filename, old_revision: oldRevision, new_revision: newRevision } }); } // 프로젝트 수정 export function updateProject(projectId, data) { return api.put(`/projects/${projectId}`, data); } // 프로젝트 삭제 export function deleteProject(projectId) { return api.delete(`/projects/${projectId}`); } // 스풀 관련 API export function fetchProjectSpools(projectId) { return api.get(`/spools/project/${projectId}/spools`); } export function validateSpoolIdentifier(identifier) { return api.post('/spools/validate-identifier', { spool_identifier: identifier }); } export function generateSpoolIdentifier(dwgName, areaNumber, spoolNumber) { return api.post('/spools/generate-identifier', { dwg_name: dwgName, area_number: areaNumber, spool_number: spoolNumber }); }