Files
Aislo/.agent/backend.md
T

4.2 KiB

백엔드 제어 명세서 (backend.md)

1. 아키텍처 및 라우팅 (Architecture)

  • 수직 통합: 백엔드 로직은 페이지 폴더(A01_, B01_ 등)별로 격리. 거대 단일 모듈 금지.
  • 파일 분할: 파일 수 제한 없음. 코드 집중 방지를 위해 기능별 분할 자율화.
  • 파일명 규칙: [폴더명]_Router.py, [폴더명]_Engine.py, [폴더명]_Schema.py 형태 준수.
  • 루트 main.py: 라우터 등록(include_router)만 수행. 비즈니스 로직 작성 금지.

2. DB 및 PostGIS (Database)

  • 비동기 통신: async/awaitasyncpg 드라이버 사용 강제.
  • 공간 연산: ORM 사용 금지. ST_Volume, ST_Distance 등 PostGIS 기반 Raw SQL 작성 원칙.

3. 설정 및 저장소 (Config & Storage)

  • 하드코딩 금지: 제어 변수/파라미터 하드코딩 금지. config/config_system.py에서 import 필수.
  • 물리 파일 격리: 포인트 클라우드, 분석 중간 파일, 메쉬, 임시 커서는 DB 저장 금지.
  • 저장 경로: storage/[고객사명]/[사용자명]/[프로젝트ID]/에 물리 파일 저장 후 DB에는 경로만 기록.

4. 검증 및 예외 처리 (Error Handling)

  • 데이터 검증: 모든 JSON 요청은 라우터 진입 전 Pydantic 모델로 타입/범위 필수 검증.
  • 예외 포획: 모든 지형/메쉬 연산은 try-except 필수 처리.
  • 반환 포맷: 에러 발생 시 {"status": "error", "message": "원인"} 표준 포맷 반환.

5. 워크플로우 상태 동기화 (Workflow State Sync)

5.1 다중 브라우저 동시 작업 원칙

  • 브라우저 독립성: 같은 계정/프로젝트를 여러 브라우저에서 동시 접근 가능. 각 브라우저는 서버 데이터 기반 독립 작동.
  • 클라이언트 상태 격리: localStorage는 브라우저별 격리(도메인 단위 공유). 공유 데이터는 항상 서버 영구저장소 우선.
  • 영구저장소 설계: 단계별 계산 결과를 storage/[고객사]/[사용자]/[프로젝트ID]/result_[단계].json 형태로 물리 저장.
    • result_scan.json — 포인트 클라우드 필터링 결과
    • result_surface.json — 지표면 모델 선택
    • result_route.json — 경로 설계 결과
    • result_section.json — 종횡단 생성 결과

5.2 Stale 상태 감지 및 전파

  • workflow.json 구조:
    {
      "current_stage": "route",
      "completed": ["scan", "surface"],
      "stale_from": "route",
      "stage1_confirmed": {...}
    }
    
  • Stale 발생 조건:
    • 상위 단계(예: surface) 재계산 → 하위 단계(route, section) 자동으로 stale_from 설정
    • 다른 브라우저에서 변경 감지 → 기존 결과 무효화
  • 상태 업데이트 함수:
    def _patch_workflow_stale(project_id: str, stale_from: str | None) -> None:
        """workflow.json의 stale_from 필드만 원자적 업데이트"""
        wf_path = storage_path / project_id / "workflow.json"
        # 기존 상태 유지하며 stale_from만 변경
    

5.3 클라이언트 폴링 패턴 (Polling)

  • 주기: GET /api/projects/{project_id}/workflow — 3초마다 호출
  • 응답: workflow.json 전체 반환 (현재 단계, 완료 이력, stale 상태 포함)
  • 클라이언트 동작:
    1. stale 감지 → 사용자에게 선택지 제시
    2. "계속하기" → 기존 결과 유지 (위험 경고)
    3. "재계산하기" → 상위 단계 재실행 (모든 하위 결과 초기화)
  • 구현 예시:
    setInterval(async () => {
      const workflow = await fetch(`/api/projects/${projectId}/workflow`);
      if (workflow.stale_from && workflow.stale_from !== currentStage) {
        handleStaleness(workflow.stale_from);  // 사용자에게 알림
      }
    }, 3000);
    

5.4 WebSocket 확장 (미래 선택사항)

  • 실시간 알림: 폴링 대신 WebSocket으로 업그레이드 가능 (응답성 향상)
  • 전송 메시지:
    {
      "type": "workflow_changed",
      "project_id": "...",
      "stale_from": "route",
      "changed_by": "other_browser"
    }
    
  • 마이그레이션 시기: 사용자 수 증가 또는 실시간성 요구 시 적용