--- document_type: backend priority: HIGH --- # 백엔드 제어 및 저장소/워크플로우 명세 ## 1. 물리 파일 및 저장소 구조 (Workflow Mapping) 프로젝트 저장소 내부는 워크플로우 단계와 1:1로 매핑됩니다. 백엔드에서 파일을 다룰 때는 DB에 직접 Blob을 저장하지 않고 이 구조를 따라 저장 후 DB에 상대 경로만 기록합니다. ```text storage/{company_slug}/{user_slug}/{project_id}/ ├── B03_FileInput/ │ └── input/ (원본 업로드 파일들: .las, .tif) ├── B04_wf1_Surface/ │ ├── processed/ (변환된 데이터: cloud_filtered.las 등) │ └── models/ (DEM, TIN 결과물: dem_2m.tif, layer.geojson) ├── B05_wf2_Route/ │ └── route/ (최적 경로: route_main.geojson) ├── B06_wf3_ProfileCross/ │ ├── longitudinal/ (종단면: longitudinal.json) │ └── cross_sections/ (횡단면 배열: cross_0020m.json 등) ├── B07_wf4_DesignDetail/ │ └── structures/ (구조물 객체: struct_0020m_001.json) ├── B08_wf5_Quantity/ │ └── quantities/ (수량 집계: items.json) └── B09_wf6_Estimation/ └── v1/, v2/ (버전별 최종 엑셀, PDF, DXF) ``` **규칙:** 페이지별 백엔드 모듈은 자기 단계의 폴더만 제어합니다. 하위 단계의 파일을 강제로 지우거나 덮어쓰지 않고 `stale_from` 상태를 통해 제어합니다. ## 2. 워크플로우 상태 동기화 (workflow.json) 다중 브라우저 동시 작업을 지원하기 위해 서버 측 상태 파일(`workflow.json`)을 원자적(Atomic)으로 관리합니다. * **Stale (상태 무효화) 발생:** 상위 단계(예: 지표면 분석 B04)가 재계산되면, 그에 의존하는 하위 단계(경로 B05, 횡단 B06 등) 결과는 신뢰할 수 없으므로 `workflow.json`에 `stale_from: "route"` 형태로 마킹됩니다. * **상태 업데이트 함수 (예시):** ```python def _patch_workflow_stale(project_id: str, stale_from: str | None) -> None: # workflow.json의 stale_from 필드만 원자적 업데이트 ``` ## 3. 클라이언트 폴링 (Polling) - 프론트는 3초 주기로 `GET /api/projects/{project_id}/workflow` 를 폴링합니다. - 서버가 반환하는 `stale_from` 값을 확인하여, 만약 현재 단계와 다르다면 UI에서 사용자에게 "결과가 변경되었습니다. 재계산하시겠습니까?"를 경고합니다.