Files
GhiVideo/docs/history/2026-06-24_1603_KMZ직접로딩-CSV중복제거.md
b23042andClaude Opus 4.8 78fc090360 초기 커밋: 스테이션(측점) 기반 주행영상 플레이어
- 클라이언트(React/Vite): Video.js 플레이어, 하단 스테이션바, POI/구조물 영상 오버레이, 카메라 파라미터 보정, 미니맵/RoutePanel
- 서버(Express): Range 스트리밍, HLS 변환, 프레임 추출, tus 업로드, 주석 API
- 최근 작업: 스테이션바 종점역 표출/양끝 정렬/미도착(재생불가) 표시, POI 라벨 '구분' 우선·컴팩트 팝업·겹침제외 토글·동일좌표 다중행, 진행방향(상/하) 우선 표출, 커서 배지 크기·픽셀 떨림 개선

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:37:57 +09:00

2.2 KiB

KMZ 직접 로딩 — POI/구조물을 원본 KMZ에서 추출 (CSV 추출 중복 제거)

날짜: 2026-06-24 수정 파일: client/src/utils/geoData.ts, client/package.json(+fflate)

배경/요구

지금까지 KMZ → CSV 추출(중복 작업) → 앱이 CSV 로드. 사용자: "KMZ가 원본이니 앱이 KMZ를 직접 읽으면 끝날 일." → 앱이 KMZ를 직접 파싱하도록 변경.

KMZ 구조 (확인)

<base>.kmz = doc.kml(zip, deflate). 폴더가 building CSV와 1:1: 02)지장물·03)교량·04)터널·05)출입문번호·06)구교. 각 Placemark = 좌표 + description HTML표(속성). 측점(01)은 KMZ에 없음 → 측점은 계속 CSV.

  • 02)지장물 69 · 03)교량 13(신대천교(복) 등) · 04)터널 2 · 05)출입문 8 · 06)구교 9 = 101 Placemark.

구현

  • fflate 추가(브라우저 zip 해제, 8KB).
  • parseKmz(files): 루트 .kmz → unzipSync → doc.kml → DOMParser. 폴더 트리 재귀(walk)로 Placemark 의 최내곽 폴더명을 분류 키로 사용: · 교량/터널/구교 → RouteStructure(연장(m)=lengthM, 시설종별=grade). · 출입문 → GeoPoint{category:'출입문', title=출입문번호}. · 그 외(02)지장물) → GeoPoint{category=category_clean} (철도역/역사는 StationOverlay가 영상 제외). 좌표는 <coordinates> 우선, 속성은 description CDATA(HTML표)를 <b>키</b>…<td>값</td> 정규식 → props(팝업 표시·KML 항목 그대로).
  • loadFolderGeoData: parseKmz 추가. KMZ 있고 내용 있으면 그걸로 pois/structures 사용 (지장물·출입문·교량/터널/구교), 없으면 기존 CSV 폴백. 측점·역사·route.json·드론프레임은 CSV 유지.

결과

  • KMZ 로드 시: POI 77(지장물 69 + 출입문 8) · 구조물 24(교량 13 + 터널 2 + 구교 9).
  • 팝업 속성 = KMZ description표 그대로. 신대천교(복) 등 교량도 영상 표출.
  • 더 이상 02~06 CSV 추출 불필요(측점 CSV/소스, 지장물_역사 CSV만 유지).

검증

  • npm run build -w client (node20) tsc + vite build 통과.
  • Python으로 동일 폴더→분류 로직 검증(101 Placemark, 폴더별 수 일치).

소요 시간: 약 22분 Context 사용량: input ~740k / output ~12k tokens