---
title: "핸드오프 — VWorld 벌크→로컬 온톨로지 전환"
from: claude-code
to: ["jadong"]
project: "clean-veteran"
date: 2026-07-02T23:22:17.058694+09:00
status: sent
type: report
---

# 핸드오프 — VWorld 벌크 → 로컬 온톨로지(kontology) 전환 트랙

> **이 문서 하나로 병렬 세션이 바로 개발 시작 가능.** 프론트(web-console) 트랙과 분리된 **데이터/온톨로지 트랙** 전용.
> 작성: 2026-07-02 · 머신: kontology(vhagar) · 리포: `/home/tlswk/projects/clean-veteran` · 브랜치: `feat/onboard-landing`

## 0. 이 트랙의 미션 (한 줄)
지금 도구들이 **라이브 API**(VWorld API·HIRA API·Kakao)로 데이터를 만드는데, 이걸 **kontology에 다 받아둔 자체 데이터(VWorld 벌크 미러 + 건물 SHP)에서** 만들도록 전환한다. = "우리 온톨로지에서 받게."

## 1. 지금 뭐가 API 기반인가 (전환 대상)
데이터 **생성 파이프라인**(`data/hospitals/*.py`)이 API 의존:
- `build_area_vworld.py` — 병원 좌표→**VWorld API**(LT_C_SPBD)로 건물 footprint×층수 = 면적 추정(쿼터 병목·근사). **← 이게 1순위 대체 대상**
- `geocode_suppliers.py` — 숨고 주소→**Kakao API** 좌표.
- `load_hira.py` — **data.go.kr HIRA API** 병원 105k.
- (건물 실면적을 원래 받으려던 **건축HUB API**는 활용신청됐지만 게이트웨이 반영 지연으로 빈응답 → 그래서 **VWorld 벌크 SHP 다운로드로 우회**한 상태)

프론트(`web-console/`)는 이미 로컬 `map_data.js`만 읽음(API 무관). **문제는 그 map_data.js를 만드는 데이터 단계.**

## 2. 이미 받아둔 자산 (kontology 로컬)
- **건물 SHP (GIS건물통합정보 전체데이터)**: `data/hospitals/raw/vworld_buildings/` (~14GB, 시도별 zip). 서울 1개 압축해제됨(`_seoul/AL_D010_11_*.shp`, **695,773 건물**). **각 건물에 폴리곤 + 건축물대장 실속성(연면적·층수·용도·PNU·주소)**.
  - ⚠️ **컬럼명이 A0~A28로 마스킹됨.** 매핑표 필요 = **`buildboss` 문서**(아래 §5) 또는 VWorld "컬럼 정의서". 샘플 추정: A2=PNU, A3=법정동, A4=주소, A9=주용도, A12=건축면적, **A14/A18=연면적류**, A26=지상층수. **정확 매핑은 컬럼정의서로 확정할 것.**
- **VWorld 카탈로그 미러 (진행 중)**: `data/hospitals/raw/vworld_mirror/` (현재 ~61GB, 27 데이터셋). 백그라운드 다운로드 중.
  - ⚠️ **미러 필터 불완전**: `vworld_mirror_all.py`가 매니페스트 기반 kb≥1MB로 받는데 **변동데이터(일별 델타)까지 섞여 용량 뻥튀김**(GIS건물통합 187파일 24GB인데 실 전체데이터는 17시도 2.8GB). 전체데이터만 깔끔히 받으려면 필터 개선 필요(§4-B).
- **카탈로그 매니페스트**: `data/hospitals/raw/vworld_catalog/manifest.json` (737 데이터셋 × 파일목록·크기).
- **DB**: `data/hospitals/clean-veteran.sqlite` — `cleanveteran_facilities`(105,439 병원, 현재 estimated_pyeong=VWorld API 추정+캡), `cleanveteran_suppliers`(9,073), `cleanveteran_data_sources`, tam 테이블. 스키마 `db/clean-veteran-data-foundation.sql` + `data/hospitals/schema.sql`.

## 3. 스크립트 인벤토리 (`data/hospitals/`)
`init_db.py`(스키마+시드) · `load_hira.py`(HIRA 적재) · `load_suppliers.py`(숨고 적재) · `geocode_suppliers.py`(Kakao 지오코딩) · `score_demand.py`(tenure/score) · `estimate_area.py`(종별평균 면적 v0) · `build_area.py`(건축HUB API 면적, 미작동) · `build_area_vworld.py`(VWorld API 면적, 현행) · `export_map.py`(→`web-console/map_data.js` 생성).
스크래치패드: `vworld_dl.py`(건물 시도 다운로드) · `vworld_catalog.py`(카탈로그 열거) · `vworld_mirror_all.py`(전체 미러).

## 4. 할 일 (우선순위)

### T-A (최우선): 건물 SHP → 병원 실연면적 로컬 조인 (API 대체)
목표: `estimated_pyeong`을 VWorld API 추정 → **SHP 실연면적**으로 교체. 결과 → `export_map.py` 재실행 → map_data.js 갱신 → 프론트 자동 반영.
1. **컬럼 매핑 확정**: buildboss 문서(§5) 또는 컬럼정의서로 A0~A28 실명 확인, **연면적 컬럼** 특정.
2. **SHP 전 시도 압축해제** + **공간 인덱스**: `pyshp`(순수파이썬, 설치됨) 또는 `geopandas`(GDAL 필요, PEP668 주의). 시도별로 처리(서울 695k 등, 전국 수백만 폴리곤).
3. **공간조인**: 병원 좌표(DB lat/lng) → 포함 건물 폴리곤 → 그 건물 연면적. 그리드/rtree 인덱스로 점-in-폴리곤. (대안: SHP DBF의 PNU/주소로 매칭 — 병원 PNU는 Kakao b_code로 이미 도출 가능)
4. **DB 갱신**: `estimated_pyeong`=연면적/3.3058, `area_source='building_shp'`. 실패분은 종별평균 유지.
5. `python3 export_map.py` → map_data.js 갱신.
⚠️ **혼합건물 과대추정 주의**: 의원이 상가 입주면 건물 전체 연면적이 나옴. 종별 캡(병원급 §build_area_vworld.py의 CAP 참고) 또는 전유면적 처리 검토.

### T-B: VWorld 미러 완주 + 정리
- 백그라운드 `vworld_mirror_all.py`(태스크 bt9nq8tpv, 이 세션 종료 시 끊김 — **재실행하면 재개**: 이미 받은 파일 skip). 27 데이터셋, 500MB+ 파일은 스킵됨(`선택다운로드` API 별도 필요, `listFnc.multiDownload`).
- **전체데이터-only 필터 개선**(현재 변동 섞임): s002 HTML 행 파싱을 정확히(각 행의 "구분 전체데이터" 라벨로) 하거나, 브라우저 필터(vworld_dl.py 방식) 재활용.
- **선행 의존**: 다운로드는 **로그인 세션 필요** — CDP Chrome `:9222`에 VWorld 로그인됨(config_vault `V_WORLD_ID/PW`). 세션 만료 시 재로그인(`cdp_drive.py` + 로그인 폼, §5 참고).

### T-C: 도구가 로컬 데이터 읽게 (API 완전 이탈)
- `geocode_suppliers.py`(Kakao) → VWorld 지오코딩 SHP나 주소 벌크로 로컬 대체 검토.
- `load_hira.py`(HIRA API) → HIRA "전국 병의원 약국 현황" 파일(data.go.kr 15051059) 로컬 적재로 대체 가능.
- 원칙: 데이터 생성 단계에서 **라이브 호출 0**, 로컬 미러만 읽기.

### T-D (선택): kontology 온톨로지 적재
- 미러 벡터(건물·지적·도로·경계·용도지역)를 kontology Neo4j/Postgres(Docker, `~/projects/kontology`)에 적재 → "대한민국 공간 온톨로지" 로컬본. (별도 대작업, 프론트 무관)

## 5. 키·도구·참고
- **config_vault** (Supabase `metqzpwektpcacyqzljn`, 값은 런타임 조회·출력금지): `V_WORLD_API_KEY`·`V_WORLD_ID`·`V_WORLD_PW`(VWorld) · `DATA_GO_API`(data.go.kr, HIRA 승인됨) · `BUILDING_API_KEY`(건축) · `KAKAO_REST_API_KEY`·`JUSO_API_KEY`. 조회: `set -a; source ~/projects/maester-agent/.env; set +a` → Supabase REST `config_vault?key_name=eq.<NAME>`.
- **CDP 드라이버**: `~/.claude/cdp_drive.py` (goto/eval/fill/tap). VWorld 다운로드는 `:9222` 로그인 Chrome 세션 쿠키 재활용(`Network.getCookies`) → `downloadResourceFile.do?ds_id=&fileNo=`.
- **컬럼정의서/가이드**: VWorld 상세페이지의 "컬럼 정의서 다운로드" 링크, 또는 이전에 받은 `buildboss` 건축HUB 가이드(Supabase Storage `documents/openapi-buildboss.zip`).
- **pyshp** 설치됨. pandas 3.0.3·openpyxl 있음. duckdb·geopandas는 PEP668로 `pip install --user --break-system-packages` 필요.

## 6. ⚠️ 트랙 충돌 방지 (중요)
- **프론트 트랙(다른 세션)**이 `web-console/` (index.html·js/·css/)를 P1/P2로 작업 중. **이 파일들 건드리지 말 것.**
- **이 트랙 소유**: `data/hospitals/` (스크립트·DB·raw/), `data/hospitals/raw/vworld_*`.
- **인터페이스 = `export_map.py` → `web-console/map_data.js`**. 데이터 갱신 후 `export_map.py`만 재실행하면 프론트가 자동 반영(map_data.js는 gitignore, 재생성물). 두 트랙은 이 파일 하나로만 만난다.
- 커밋 시 `web-console/js|css|index.html`은 프론트 트랙 소관이니 **data/·db/·docs/만** 스테이징.

## 7. 시작하는 법 (병렬 세션)
1. 이 문서 읽기.
2. `docs/superpowers/specs/2026-07-02-cv-market-console-design.md`(§11 팔란티어 맥락)·`docs/superpowers/plans/2026-07-02-cv-market-console.md`(전체 그림) 참고.
3. `.superpowers/sdd/progress.md`에서 프론트 P0 완료 상태 확인(중복 금지).
4. T-A(건물 SHP 실연면적)부터: buildboss 문서로 컬럼 확정 → 서울 SHP로 공간조인 스모크 → 전국 확장.
5. 라이브 결과 확인: `export

[full: /home/tlswk/projects/clean-veteran/docs/HANDOFF-vworld-local-data-20260702.md]
