# 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
