어디살지 지도뷰 재설계

전수분석 · 2026 최적안 교차검증 · 구현 로드맵
기준일 2026-06-05 · Kakao Maps JS SDK v2 + PostGIS · 둘러보기(/feed) · 수만 건 규모 전제
결론: Kakao 유지 + 서버 집계가 2026 최적
TL;DR 1. 전수분석 2. 최적성 판정 3. 2026 교차검증 4. 확정 설계 5. 로드맵 6. 검증

TL;DR

1. 현재 구조 전수분석

스택: Kakao Maps JS SDK v2(services+clusterer) + PostGIS(GIST/ST_MakeEnvelope/ST_Contains). 백엔드 Python(FastAPI+SQLAlchemy+alembic), 프론트 React+Vite.

파일역할
FeedMapView.tsx (1112줄)지도 본체 — 클러스터·폴리곤·역지오코딩·GPS
useMapPins.tsviewport 2배 padding 캐시 fetch
utils/boundaries.tspoint-in-polygon(ray-casting)
Feed.tsx (996줄)페이지 / 정렬·필터 UI
public_properties.py:430-680GET /map 엔드포인트
property_repository.py:1518-1637search_within_bbox
boundary_lookup.pyEMD_CD→폴리곤 메모리캐시

2. 최적성 판정

영역판정근거
GIST 인덱스 적중최적&&+ST_MakeEnvelope, partial index와 WHERE 1:1 (:1567,1590)
대량매물 limit 초과문제list_stmtORDER BY 없음 → 비결정 truncate (:1618)
서버 클러스터링문제ST_SnapToGrid/DBSCAN/AsMVT 전무, raw row 통째 전송
클릭→해당영역 재조회최적adm_cd2→PostGIS ST_Contains 실제 서버 재조회
정렬 (지도)문제지도 ORDER BY 부재가 truncate 비결정성 유발
거리순 / N+1최적거리 SQL acos, window ROW_NUMBER() 배치 1쿼리
필터최적type/거래/가격/면적/tags/반경 전부 SQL pushdown, 바인딩 안전
fetch 최적화개선2배 padding+debounce 300ms+bbox dedup 우수, AbortController 부재
클러스터 재생성개선visibleGeoItems 변경마다 clear()+전량 재생성 (:600-607)
마커→미니카드문제FeedMapMiniCard 렌더 통째 주석처리, ~100L 死코드
로딩/빈/에러 UX · a11y최적모든 dead-end 복구경로+aria-live, 라임 위 차콜텍스트 AA
디자인 토큰문제raw hex 만연 + hover:bg-status-failed(실패 토큰 중립 hover 오용)
바텀시트개선grabber 있으나 drag-to-dismiss 없음

3. 2026 최적방법 교차검증

결론: "Kakao 베이스맵 유지 + 서버 집계 + 줌별 렌더"가 세 출처(커뮤니티·한국 부동산·기법비교) 모두에서 정답으로 수렴.

커뮤니티 컨센서스

한국 부동산 사례

서비스패턴
직방서버 Direct Clustering(그룹+카운트 내려줌)
다방계열Level-Based lazy fetch(넓은 줌엔 raw 미전송)
네이버부동산cortarNo(행정구역)+zoom+bbox, 시도→시군구→읍면동→단지 4계층
호갱노노줌30km=시도 버블, 확대시 구→동 전환

Kakao 공식: "클라 위임은 매우 비효율적", 서버 사전집계 권장. 클라 클러스터러는 1만개에서 7~8초로 붕괴. Kakao 유지 합리적 — 무료 30만/일(국내최대), 직방이 카카오 공식 상업 레퍼런스.

PostGIS 18 기법 비교

기법성능/GiST줌별 grid격자 아티팩트캐싱복잡도Kakao DOM
ST_SnapToGrid+GROUP BY✅ ms급✅ /2^zoom⚠️ 사각✅ 결정적✅ 최저✅ 최적
ST_ClusterDBSCAN⚠️ 저줌 CPU🔴✅ 없음🔴 비결정⚠️🔴 부적합
ST_ClusterKMeans⚠️ k 고정🔴✅ 없음🔴⚠️🔴 부적합
H3 육각격자⚠️ res매핑✅ 최우수✅ roll-up⚠️ 확장✅ 조건부
Geohash prefix⚠️ 32배🔴 경계버그⚠️ 열화판
ST_AsMVT종속종속🔴🔴 WebGL전제
geohash 비채택(경계 prefix 단절 버그+거친 단계로 SnapToGrid 순수 열화). H3는 수십만+ 확장·격자균일성 필요시 승격. 출처: postgis.net, Crunchy/Paul Ramsey, CARTO tile aggregation, h3geo, ky-gis.

4. 확정 설계

4-1. 집계 단위 — 하이브리드(행정구역 + 격자)

이 앱은 이미 행정구역 폴리곤(sido/sigungu/emd)+adm_cd2 인프라 보유 → 한국 표준과 일치. 격자만 새로 도입하면 폴리곤과 따로 논다.

[클라] Kakao Map (베이스맵 유지) └ 줌(z) + bbox 전송 [서버] GET /v1/public/properties/map/clusters?z=&bbox=&{filters} ├ 저줌(시도/구/동) → 행정구역 집계 버블 (materialized view 캐싱) ├ 고줌(동 이하) → ST_SnapToGrid(geom, grid(z)) GROUP BY → count + 대표좌표 └ 최고줌 → 개별 매물 핀 [응답] { clusters:[{lng,lat,count,repr_price}], points:[{id,price,...}] } → 수만~수십만 건도 화면당 수십~수백 셀만 전송

4-2. 백엔드

4-3. 프론트

4-4. UI/UX

5. 구현 로드맵 (WSJF)

#작업비용
N0*결정적 ORDER BY 추가(비결정 truncate 즉시 해소)S
N1*백엔드 클러스터 엔드포인트+스키마+repository 집계L
N2*저줌 집계 materialized view 마이그레이션M
N3*프론트 클러스터 렌더 전환 + AbortControllerL
N4UI/UX(死코드·토큰·바텀시트·a11y)M

6. 검증