| name | nunchi-map |
| description | Resume/continue development of 눈치맵 (nunchi-map) — a real-time local crowd/wait/on-site-photo app (대국민 눈치게임): enter a destination, see how crowded it is now, expected wait, and live '지금 뜨는 곳' ranking. Routes to the repos, explains architecture + how to run/verify, and lists the exact next gaps. Use when the user says "눈치맵", "누치맵", "nunchi-map", "대국민 눈치게임", "혼잡도 앱", "지금 뜨는 곳", or asks to continue/extend/deploy that app or its landing page. Do NOT use for ThakiCloud product repos (see [[thaki-platform-repos]]) or generic Go/React scaffolding unrelated to this app. |
눈치맵 (nunchi-map) — Continuation & Router
목적지 입력 → 지금 그곳의 실시간 혼잡도 + 대기 추정 + 현장 UGC 사진 + '지금 뜨는 곳' 랭킹을 한 화면에.
개인 사이드 프로젝트(ThakiCloud 제품 아님). 이 스킬은 다음 세션이 이어서 작업하도록 위치·구조·실행·잔여 갭을 고정한다.
1. 위치 (Repos)
| 무엇 | 경로 / URL | 비고 |
|---|
| 앱 (백엔드+모바일+문서) | ~/thaki/nunchi-map · github.com/sylvanus4/nunchi-map (private) | 정본. main 추적 |
| 동일 앱, 서브모듈 | ~/thaki/ai-platform-strategy/nunchi-map | 부모가 gitlink로 핀. 작업은 standalone에서, 후 부모 범프 |
| 랜딩(수요검증) | ~/thaki/nunchi-map-landing · github.com/sylvanus4/nunchi-map-landing (public) | GitHub Pages |
| 라이브 랜딩 | https://sylvanus4.github.io/nunchi-map-landing/ | 링크드인 공유용, 클릭('관심있어요')로 수요 측정 |
작업 시작: cd ~/thaki/nunchi-map && git checkout main && git pull ([[git-workflow-main-only]]). 코드 변경 후 push하고, 부모 서브모듈 범프(cd ~/thaki/ai-platform-strategy && (cd nunchi-map && git pull) && git add nunchi-map && git commit && git push).
2. 스택 / 구조
- 백엔드: Go 1.24 + Fiber, PostgreSQL 16 + PostGIS(위치·시계열), Redis(hotness ZSET), NATS.
backend/ (module github.com/sylvanus4/nunchi-map/backend).
cmd/api(REST), cmd/ingest-worker(서울 실시간 도시데이터 폴링→upsert→reading→hotness.Recompute).
internal/: congestion(seoul_client·areas 좌표표·레벨정규화), hotness(ComputeSlope + Redis ZSET), places, reports(지오펜스+포인트 단일 tx), auth(Kakao/Apple JWKS RS256 + 앱 JWT), users, geo, httpapi, store, config.
- 모바일: Expo React Native (
mobile/). 네이티브 지도=react-native-maps(MapScreen.tsx), 웹은 MapScreen.web.tsx(지도 플레이스홀더 + 리스트). src/api/client.ts가 snake_case wire→camel viewmodel 매퍼 소유.
- 핵심 알고리즘:
hotness = w1·level_score + w2·slope + w3·report_count_1h + w4·photo_count_1h. 차별화=slope(혼잡도 상승 기울기) → '지금 뜨는 곳'. 혼잡 4단계 여유(1)/보통(2)/약간붐빔(3)/붐빔(4).
- 데이터: 서울 실시간 도시데이터 오픈API(무료). sample 키는 광화문·덕수궁만 고정 반환(E2E 검증용) — 지역별 실데이터는 실
SEOUL_RTD_API_KEY 필요. 실시간 사진은 인스타 위치API 폐쇄로 UGC(현장 제보)로만.
문서: docs/PRD.md, ARCHITECTURE.md(mermaid), DATA-MODEL.md, adr/000{1,2,3}, openapi.yaml, ROADMAP.md(Phase 0~3).
3. 실행 / 검증 (⚠️ 이 환경은 Docker Hub 차단)
4. 남은 갭 (다음 작업 후보 — 우선순위)
GET /v1/places/:id 상세 보강: recent_reports/congestion_trend/wait_estimate 미구현(모바일이 별도 호출로 임시 보완). 백엔드에서 채우기.
- 좌표 테이블 27/약120:
internal/congestion/areas.go. 공식 120개 지역 좌표 완성(추정 금지 — 공식 목록 필요).
- 실 API 키 연동: 서울 RTD 실키(지역별 데이터), 카카오/애플 앱키.
- 네이티브 지도 실기동: react-native-maps는 dev build/시뮬레이터 필요(웹은 미리보기 전용).
- NATS 구독자 부재: 워커가
congestion.updated 발행하나 소비자 없음(현재 Recompute 직접 호출). API가 구독해 실시간 hotness 갱신하도록 정리 or 죽은 발행 제거.
- hotness geohash 버킷팅: TopHot이
hot:global 스캔 — 밀도 커지면 hot:{geohash5} 버킷.
- Phase 2+: 테마파크(에버랜드/롯데월드) 대기시간·웨이팅앱(캐치테이블/테이블링) 제휴, 전국 확대(ROADMAP.md).
5. gotchas (실패에서)
- Docker Hub 차단 →
docker compose up 대신 smoke_local.sh(brew). compose 파일은 정본 문서로 유지.
- 서울 sample 키는 요청 지역 무시하고 광화문 고정 반환 — 다지역 테스트는 실키.
- 모바일 API 계약: 백엔드 snake_case +
/v1/hot·/v1/places/search는 bare 배열(과거 {places:[]} 래핑 + hotness 필드 누락으로 앱 목록이 비었던 사고). 새 엔드포인트 추가 시 openapi.yaml·mobile/src/api/client.ts 매퍼·smoke_local.sh 어서션 3곳을 함께 맞춘다.
- 되돌릴 수 없는 배치/삭제는 [[destructive-batch-guard]], 커밋/푸시는 [[git-workflow-main-only]] 정합.
6. 랜딩(수요검증) 유지보수
~/thaki/nunchi-map-landing/index.html(단일 파일). '관심있어요' 클릭 카운트=counterapi.dev(COUNTER_BASE), 실패해도 UX 정상. OG 카드=assets/og-banner.png(1200x630, og-banner.html에서 Chrome로 재생성). 수정 후 push하면 Pages 자동 반영.