- page.tsx: 모바일 "내위치" 토글 2곳 onClick 초기화 목록에 setMinMentions(0) 추가
(데스크톱 토글만 반영돼 있던 설계 §7 상호배타/리셋 일관성 누락 보강)
- 설계서 §7: 데스크톱/모바일 토글 전부(3곳) 동일 적용 명시
- tsc/jest(6 suites, 32 tests) 통과. 통상 모바일 흐름에선 no-op(minMentions는 데스크톱 전용 select)
Refs #533
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- formatRegion 순수함수/엣지케이스/렌더 가드/설계서 일치 검토 완료
- 단위 테스트 8/8 재확인, #545 접근성 회귀 복원 확인
- 06-Reviewer 승인 → 07-Release 대기
Refs #532
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
동시 진행 중이던 [Designer] #545 커밋(e0e9ab6)의 title 속성/aria-hidden
표시를 #532 작업 중 작업 트리 정리 과정에서 착오로 되돌렸다(commit c13b976).
formatRegion 렌더 가드 변경(#532)과는 무관한 부분이므로 원상 복구.
Refs #532, #545
- 설계서(docs/design/533-min-mentions-filter/README.md) 대비 구현 일치 확인
(backend RestaurantMapper video_count/min_mentions, frontend 필터 UI)
- dev API 실측: min_mentions 0/1/2/3/5/100 전 구간 경계 위반 0건
(=2→116개, =3→36개, DISTINCT+서브쿼리 중복 없음, 기존 필터 조합 회귀 없음)
- passesMinMentions()를 lib/filters.ts로 추출(동작 변경 없음)하고
frontend/__tests__/filters.test.ts 6케이스 추가(경계값/null 처리 등)
- 백엔드 빌드, tsc, 프론트 전체 jest(6 suites, 32 tests) 통과
Refs #533
RestaurantList.tsx/RestaurantDetail.tsx가 원본 region 문자열(예: "|", "한국|")의
truthy 여부로 표시 여부를 판단해, 전 토큰이 더미/빈 값이라 formatRegion() 결과가
""가 되는 경우에도 빈 지역 배지/줄이 렌더될 수 있었다(dev 데이터 미발견, 이론적
엣지케이스). 가드를 formatRegion(region) 결과 기준으로 변경. formatRegion() 자체
로직/시그니처는 변경 없음 — 표현(호출부 조건)만 다듬음.
설계서(docs/design/532-region-display/README.md) 갱신: 가드 방식 및 근거 명시.
Refs #532
기능(isKoreaRestaurant 게이트)은 QA 통과 상태 그대로 유지, 표현/접점만 보완.
- 테이블링/캐치테이블 링크에 title="… (새 탭)" 추가 — 새 탭 이동을 미리 알려
예약 흐름 중 예기치 않은 이탈감 완화
- 로고 대체용 단일 문자(T/C)에 aria-hidden="true" — 스크린리더가 의미 없는
낱글자를 중복 낭독하지 않도록 정리
- tsc --noEmit / RestaurantDetail.test.tsx 5/5 통과 (회귀 없음)
Refs #545
RestaurantDetail.tsx의 isKoreaRestaurant() 게이트가 설계서 인수조건과
일치함을 확인. 국내/해외/URL-NONE/좌표없음 fallback 등 5개 경계 케이스를
자동화 RTL 테스트로 검증(수동 육안 QA를 대체). tsc 및 전체 jest 스위트
통과.
Refs #545
- frontend/__tests__/region.test.ts: 설계서(docs/design/532-region-display)
엣지케이스 8종(falsy/계층조인/null토큰/빈토큰/더미제거/단일토큰/전량더미/trim) 검증
- tsc --noEmit, jest 전체 스위트 통과 확인
- 실제 dev DB region 데이터로 엣지케이스 재확인
Refs #532
- RestaurantDetail.tsx 예약 버튼 2종을 isKoreaRestaurant() 게이트로 감쌈
- 테이블링/캐치테이블은 국내 전용 — 지도 링크와 동일 판정 기준 적용
Refs #545
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- panTo(애니메이션) + setZoom(z, true)(애니메이션) 동시 호출이 서로 cancel
- 단일 식당은 줌 변화 없어서 가려졌고 클러스터는 줌 크게 변경 → 가시화
- SDK의 morph(latlng, zoom)으로 center+zoom 동시 변경 일관 처리
- flyTo / selected / cluster 클릭 모두 동일 패턴
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- GoogleMapView에는 있던 useEffect [selected] 패턴이 NaverMapView에 누락
- 마커/클러스터/리스트 어디서 선택해도 그 식당이 중앙 + zoom 16
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- tasteby-web: PORT=3001 명시 (env 누락 → 기본 3000으로 충돌 위험)
- reviews/, screenshots/ 로컬 작업 산출물 무시
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Icon.tsx: 크기 고정 + flex center로 정렬 일관성
- cuisine-icons.ts: Tabler → Phosphor 매핑(BowlFood/FishSimple/Pizza 등)
- FoodIcon.tsx 신규: 한식 specific 자체 SVG (찌개/전골/탕)
- frontend/docs/brand-guide.md 신규: 브랜드 아이덴티티 + 디자인 시스템 정책
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- evaluation 컬럼이 IS JSON 제약이라 평문은 {"text":"..."}로 정규화
- parseMap이 잘못된 JSON 받았을 때 빈 Map 대신 {"text":원문}으로 보존
- PipelineService/RestaurantService에서 이미 호출 중인 유틸 — 미커밋 상태였음
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 리스트/검색결과에서 식당 클릭 → setRegionFlyTo로 그 좌표 + zoom 16
- NaverMap/GoogleMap dispatcher 둘 다 panTo + setZoom
- 마커 selected 강조(1.15× 파란 박스)와 함께 동작
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- GoogleMapView와 동일 팔레트 (8 색)
- 식당 첫 채널 기준 색상, activeChannel 있으면 우선
- getChannelColorMap 재사용 패턴 동일
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 배포 흐름 v0.1.51~v0.1.57 정리
- 운영 진단 확인사항 (NCLOUD 도메인 형식, Search/Maps 별개 시스템)
- NaverMapView 안정화 핵심 결정사항 (divRef 항상 마운트, ResizeObserver, try/catch)
- 후속 분리 항목 명시
Refs: #363🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 이전: ready 가드로 첫 렌더 시 ref 누락 가능 → SDK가 div 못 잡음
- 명시적 width/height + 회색 배경(시각적 로딩 표시)
- ResizeObserver + rAF로 컨테이너 0×0 → 정상 크기 시 m.refresh
- try/catch + initError로 init 실패 가시화
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- NaverMapView 골격이 실 운영에서 지도/마커 렌더 실패
- 환경변수 비워 dispatcher가 GoogleMap fallback (회귀 0)
- NaverMapView 코드는 유지 — 후속 안정화 작업 후 재활성
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- StatsMapper interface는 long 반환인데 XML resultType이 int
- Integer를 primitive long으로 cast 못 함 → ClassCastException → 500
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- NCLOUD 신 정책: ncpKeyId 사용 (navermaps/maps.js.ncp 공식)
- 인증 200/Failed 진짜 원인 — 도메인 등록 정확했으나 파라미터 차이
- Refs: navermaps/maps.js.ncp
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 좌표 기반 한국 판정 (KR bbox 33~38.7°N, 124~132°E)
- 국내: 네이버 지도(/p/search/) primary + Google Maps 보조
- 해외: Google Maps 단독
- 좌표 없으면 region 첫 토큰 fallback
2단계(메인 지도 탭 SDK 분기)는 별도 후속.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 실제 캐치테이블은 app.catchtable.co.kr/ct/shop/... 형식
- 옛 /shop/, /dining/ 패턴은 contains 매칭 실패 → 첫 회차 1044건 전부 미발견
- 패턴 교정 후 NONE 해제 + 재실행 필요
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 특정 검색에서 무한 hang → backend virtual thread 점유로 후속 벌크 작업 중단
- Naver/DDG 둘 다 timeout 적용
- 타임아웃 시 HttpTimeoutException → 호출자(bulk)에서 notfound 안전 처리
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 대량 백필(700+건 ≈ 100분) 시 10분 SSE timeout으로 중간 끊김
- emit() 실패 시 마지막 cache.flush + complete 누락 → 3시간으로 확장
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Naver/DDG 결과가 www.tabling.co.kr 형태인데 PUT validation에서 거부됨
- bulk-tabling SSE는 validation 없이 통과 — 불일치 해소
- catchtable은 이미 app/www 둘 다 허용 (기존)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- GET /api/admin/restaurants/duplicates/place-id (어드민 전용)
- 그룹별 식당 목록 + video/review/memo 카운트 동봉
- Mapper: findDuplicatePlaceIdRows + Service 그룹핑
- 정리/병합 + UNIQUE 제약은 데이터 위험 분리 위해 후속 PR로
Refs: #359 (조회 단계 완료)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- dto/RestaurantUpdateDTO record 신규 (15 필드, 모두 nullable)
- @Size/@Pattern(URL or NONE)/@DecimalMin·Max/@Min·Max
- RestaurantController.update 시그니처 Map → @Valid DTO 교체
- toFieldMap()으로 null 제외 후 기존 Service.update 호출 (회귀 0)
- #332 ALLOWED_UPDATE_FIELDS Set 제거 (DTO 필드 자체가 화이트리스트)
Refs: #358 (close)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- WebSearchService 신규 (Naver webkr.json 우선, 키 미설정/실패 시 DDG)
- RestaurantController.searchTabling/searchCatchtable 내부 호출 교체
- 인라인 DDG 80줄 제거, 미사용 import 정리
- app.naver.client-id/secret 추가 (env: NAVER_CLIENT_ID/SECRET)
- k8s secrets template에 NAVER 키 항목
Refs: #357 (close)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- DB V20260615b: video_restaurants.{relevance, relevance_reason, relevance_evaluated_at} + idx_vr_relevance
- VideoRelevanceService (#322 패턴): @Async verifyAsync + verify + verifyAll(batchSize)
- PipelineService.processExtract → linkVideoRestaurant 후 verifyAsync(linkId) 자동 트리거
- GET /api/restaurants/{id}/videos: 기본 strong/unknown만, ?include_weak=true 시 모두 + relevance/reason
- AdminVideoRelevanceController: GET pending / POST all / POST {id}/evaluate / PATCH {id}
- 캐시 키 strong|all 분리, LLM 실패 시 unknown 안전 기본값(표시 유지)
Refs: #356 (close)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>