종합부동산웹앱 4단계 원천식별자·실데이터 갱신 구현
질의 원문
다음 단계 차례로 진행해줘.
수집 경로와 시점
- 수집시점: 2026-08-11 19:33 KST
- 기준 설계:
docs/plans/2026-08-11-watchlist-source-refs-live-refresh-design.mddocs/plans/2026-08-11-watchlist-source-refs-live-refresh.mddocs/analysis/2026-08-11-종합부동산웹앱-4단계-원천식별자-실데이터갱신설계.md- 확인 코드:
src/realestate/webapp/watchlist.pysrc/realestate/webapp/app.pysrc/realestate/webapp/metric_collector.pysrc/realestate/search/live.pysrc/realestate/analysis/complex_report.py
데이터 등급
| 항목 | 등급 | 설명 |
|---|---|---|
| 구현 판단 | 로컬 코드·테스트 기반 | 저장소 파일과 테스트 결과 기준 |
| 네이버 시세 갱신값 | 2차/플랫폼 | 네이버부동산 시세 제공값. 직접 원본 확정 아님 |
| 네이버 경유 실거래 중위값 | 1차/공공원본 경유 | 국토부 신고 실거래를 네이버 경유로 받은 값. RTMS 직접 확인 아님 |
| 경매·재개발 원천 식별자 | 예약/미연결 | 저장 키만 보존하고 실제 원본 갱신은 다음 단계 |
구현 내용
WatchlistItem에source_refs를 추가했다.- 허용 원천 식별자 키를
naver_complex_no,naver_area_label,court_case_no,court_code,court_goods_no,data_go_lawd_cd로 제한했다. /api/watchlist생성·수정 API가source_refs를 저장하고 알 수 없는 키는 버린다.- 워치리스트 후보 추가 폼에 네이버 단지번호와 면적 기준 입력을 추가했다.
- 후보 카드에 원천 식별자 뱃지와
data-watch-source-ref-*속성을 렌더링했다. WatchlistMetricCollector를 추가해 기존complex_report(complex_no)결과를 워치리스트 지표로 변환한다.- 앱 생성 시 기본
metric_collector를 연결했다. naver_complex_no가 없거나 복수 평형에서naver_area_label이 없으면 503으로 실패하고 기존 값은 유지한다.- 시세 값이 있으면 네이버 시세를 우선 사용하고, 없으면 충분 표본의 실거래 중위값만 사용한다.
- 지표 갱신 버튼을 후보 카드에 추가하고 실패·진행 상태를
aria-live영역에 표시한다. - 코드 리뷰에서 발견된 실제 사용 위험을 보강했다.
59/84같은 정수 면적 라벨은59.93㎡/84.98㎡처럼 네이버가 주는 소수 면적과 매칭되도록 했고, refresh 수집기가None값을 반환하면 기존 값을 지우지 않고 실패하게 했다. - 기본 네이버 수집기는 FastAPI async route 안에서 직접 실행하지 않고 worker thread로 오프로딩한다.
- malformed
source_refspayload는 500이 아니라 400으로 실패한다.
가정
- 원천 식별자는 사용자가 직접 입력하거나 향후 검색 UI에서 선택해 저장한다.
- 이번 단계에서는 후보명 기반 자동 검색을 하지 않는다.
- 단지 내 평형이 여러 개일 때 면적 기준이 없으면 잘못된 갱신보다 실패가 낫다.
- 수집 실패는 정상적인 상태로 보고, 추정값을 저장하지 않는다.
한계
- 네이버 수집은 네트워크, TLS 지문, API 구조 변경에 따라 실패할 수 있다.
- 네이버 경유 실거래는 직접 RTMS 원본 확인이 아니므로
original_verified=false로 남긴다. - 경매·재개발 식별자는 이번 단계에서 표시·보존만 하며, 실제 법원경매·정비사업 원본 연결은 별도 구현이 필요하다.
- 예상 분담금은 아직 자동 수집하지 않는다.
검증
- RED: 새
tests/test_webapp_metric_collector.py가metric_collector모듈 부재로 실패하는 것을 확인했다. - REVIEW RED: 코드 리뷰 지적에 따라 면적 소수 매칭,
Nonemetric refresh, 동기 수집기 worker thread 오프로딩, malformedsource_refs테스트 4건이 실패하는 것을 확인했다. - REVIEW GREEN:
python -m pytest tests/test_webapp_metric_collector.py::test_metric_collector_matches_integer_area_label_to_decimal_exclusive_area tests/test_webapp_watchlist.py::test_watchlist_api_rejects_malformed_source_refs tests/test_webapp_watchlist.py::test_watchlist_metric_refresh_rejects_none_metric_values tests/test_webapp_watchlist.py::test_watchlist_metric_refresh_runs_sync_collector_in_worker_thread -q-> 4 passed - GREEN:
python -m pytest tests/test_webapp_metric_collector.py tests/test_webapp_watchlist.py::test_watchlist_api_preserves_source_refs tests/test_webapp_watchlist.py::test_watchlist_metric_refresh_requires_source_refs tests/test_webapp_watchlist.py::test_watchlist_metric_refresh_uses_default_naver_collector tests/test_webapp_watchlist.py::test_watchlist_page_renders_source_ref_inputs_and_attrs tests/test_webapp_watchlist.py::test_watchlist_page_renders_metric_refresh_controls -q-> 10 passed - focused:
python -m pytest tests/test_webapp_metric_collector.py tests/test_webapp_watchlist.py tests/test_webapp_static_js.py -q-> 50 passed - focused+E2E+현황판:
python -m pytest tests/test_webapp_metric_collector.py tests/test_webapp_watchlist.py tests/test_webapp_pipeline.py tests/test_webapp_static_js.py tests/test_webapp_watchlist_e2e.py tests/test_investment_board.py -q-> 82 passed, 2 warnings - Node:
node --test tests/webapp_watchlist_logic.test.js-> 6 passed - JS 문법:
node --check src/realestate/webapp/static/app.js-> 통과 - JS 문법:
node --check src/realestate/webapp/static/watchlist_logic.js-> 통과 - 전체 테스트:
python -m pytest -q-> 257 passed, 2 warnings - whitespace:
git diff --check-> whitespace error 없음(CRLF 경고만 출력) - 투자 현황판:
python -m realestate.cli invest-board->reports/investment_board.html재생성
다음 단계
- 목표가 도달 후보와 급매 후보 자동 플래그를 추가한다.
- 플래그에는 수집시점과 데이터등급을 함께 표시해 오래된 값과 원본 미확인 값을 구분한다.
- 경매 사건번호·재개발 원천 문서 식별자를 실제 수집기와 연결한다.