# 2026-07-09 카메라 JSON 저장/적용 + 세그먼트 라벨 캐시 + 팝업 정렬 + 박스 높이

**소요 시간**: 20분
**Context 사용량**: input 640k / output 10k tokens

## 요청 4건 처리

### 1. 카메라 화각 정보를 영상 이름의 JSON 으로 서버 저장 → 폴더에 함께 있으면 자동 적용

- **서버**: `routes/camera.ts` 신규 — `PUT /api/camera/:videoId` 가 영상 폴더(VIDEOS_DIR)에
  `<영상 base>.camera.json` 저장(`{ camera: {...}, model, savedAt }`), `GET` 조회. Path traversal 방어
- **클라이언트**:
  - `parseCameraJson`(geoData): 폴더에서 `<영상 base>.camera.json`(또는 `<base>.json`) 인식 —
    폴더 내 어떤 분할본 base 와도 매칭, 숫자 필드만 통과
  - geoStore `cameraJson` 적재 → StationOverlay 에서 **최우선 적용**(localStorage 보정·djmd 감지값보다 위,
    effect 선언 순서로 보장)
  - 카메라 파라미터 패널 📷 줄에 **[서버에 저장]** 버튼 — 현재 파라미터 전체(focalLen/yaw/pitch/…)를
    현재 재생 중인 영상 이름으로 저장. 저장중…/저장됨 ✓/실패 상태 표시
- E2E 검증: PUT → D: 폴더에 파일 생성 → GET 일치 → 정리 완료

### 2. 두 번째 영상에서 시설물 미표출

- 원인: 라벨 사전계산(startLabelPrecompute) effect deps 에 `storeFrames` 누락 —
  세그먼트 전환(loadSegment)으로 frames 가 교체돼도 이전 세그먼트의 라벨 캐시를 계속 사용 →
  새 위치에서 전부 화면 밖 투영
- 수정: 두 precompute effect deps 에 `storeFrames` 추가 → 세그먼트 전환 시 재계산

### 3. 시설물 라벨 아래 검은 팝업 정렬

- 원인: 팝업 x 앵커가 구 라벨 레이아웃(지점 오른쪽 텍스트) 기준 `sx − 10` 고정 —
  라벨이 중앙정렬 박스로 바뀌면서 어긋남
- 수정: POI 팝업은 `sx − 팝업폭/2`(박스 중앙 아래 정렬), 측점 팝업은 기존 유지

### 4. 라벨 배경 박스 여유

- BOX_H 22 → **24**(글자 20px × 1.2), PAD_X 6→7, 동일좌표 다중 라벨 행 간격 ROW_H 24→28

## 검증

- 클라이언트(tsc+vite)·서버(tsc) 빌드 통과, pm2 재시작, 새 번들(index-BxAoyQvu.js) 서빙
- 카메라 API 왕복 테스트 통과

## 다음 단계 참고

- camera.json 저장은 서버 VIDEOS_DIR 기준 — 폴더 선택으로 여는 로컬 폴더가 VIDEOS_DIR 과
  다른 경로면 저장 파일이 그 폴더에 없음(현 구성은 동일 폴더라 문제없음)
- camera.json 은 폴더 공용(분할본 전체 적용). 세그먼트별 별도 카메라가 필요하면 확장 필요
