48 Commits

Author SHA1 Message Date
joungmin
2eb16ce861 fix(map): 클러스터 expansion 후 마커 클릭 시 재묶임 방지
- selected 시 무조건 zoom 16 → 줌 18에서 마커 클릭하면 다시 16으로 줄어 클러스터링
- 현재 zoom ≥ 16이면 유지, 미만이면 16으로 (Naver/Google 둘 다)
- page.tsx의 setRegionFlyTo 호출 제거 — selected useEffect로 일원화

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-17 10:09:22 +09:00
joungmin
14384b0c71 fix(map): NaverMap 클러스터 클릭 시 중앙 이동 — morph로 통일
- 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>
2026-06-17 09:55:51 +09:00
joungmin
250b067d87 fix(map): NaverMapView selected 변경 시 자동 panTo + zoom
- 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>
2026-06-17 09:42:37 +09:00
joungmin
6a885c5203 docs(changelog): v0.1.63 미커밋 잡변경 정리 5건
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 19:35:24 +09:00
joungmin
1164139312 feat(map): 식당 선택 시 지도 자동 줌인/이동
- 리스트/검색결과에서 식당 클릭 → 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>
2026-06-16 17:29:28 +09:00
joungmin
78f7e83a0e feat(map): NaverMapView 마커에 식당명 박스 (GoogleMap 동일)
- 단순 동그라미 → 박스+화살표+식당명+cuisine 아이콘 핀
- 채널별 bg/text/border/arrow 색상
- 폐업(CLOSED_*) 회색 + 취소선, selected 강조 (1.15× + 파란박스)
- InfoWindow 제거 (식당명이 박스로 보임)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 17:13:37 +09:00
joungmin
247547c516 feat(map): NaverMapView 채널별 마커 색상
- GoogleMapView와 동일 팔레트 (8 색)
- 식당 첫 채널 기준 색상, activeChannel 있으면 우선
- getChannelColorMap 재사용 패턴 동일

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 17:09:02 +09:00
joungmin
8de8696424 perf(map): NaverMapView SDK 네이티브 마커 + InfoWindow
- React absolute div overlay → naver.maps.Marker 네이티브 교체
- 줌/팬 시 SDK GPU 최적화로 랙 해소
- 식당명 InfoWindow (마커 클릭 시 표시)
- bounds_changed → idle 이벤트로 sync 빈도 감소
- 클러스터도 네이티브 마커 (HTML 콘텐츠 숫자)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 16:58:03 +09:00
joungmin
ce3e34938c fix(map): NaverMapView 안정화 — divRef 항상 마운트 + ResizeObserver
- 이전: 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>
2026-06-16 10:38:57 +09:00
joungmin
5199475d67 revert(map): NaverMap 임시 비활성, 한국도 GoogleMap fallback
- 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>
2026-06-16 10:32:54 +09:00
joungmin
bd8d82dd5d fix(stats): /api/stats/visits 500 — Mapper resultType int→long
- 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>
2026-06-16 10:26:15 +09:00
joungmin
bc83923261 fix(map): NaverMap 인증 파라미터 ncpClientId → ncpKeyId
- 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>
2026-06-16 10:03:09 +09:00
joungmin
f17ba9e37a feat(map): #363 메인 지도 SDK 국내(네이버)/해외(구글) 분기
- MapView dispatcher: NAVER 키 + KR bbox 좌표 → NaverMapView
- NaverMapView 신규 (네이버 v3 직접 wrapper, Supercluster 재사용)
- GoogleMapView 신규 (기존 MapView 내용 rename)
- MapView.types.ts 공용 타입 + isKoreaCoord 헬퍼
- Dockerfile/deploy.sh: NEXT_PUBLIC_NAVER_MAP_CLIENT_ID build-arg
- 키 미설정 시 GoogleMap fallback (회귀 0)

Refs: #363

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-16 06:25:47 +09:00
joungmin
7789671fbc feat(map): 식당 상세 지도 링크 국내/해외 분기 (1단계)
- 좌표 기반 한국 판정 (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>
2026-06-16 05:59:24 +09:00
joungmin
c5b0216a37 fix(catchtable): URL 패턴을 /ct/shop/, /ct/dining/으로 교정
- 실제 캐치테이블은 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>
2026-06-16 01:35:18 +09:00
joungmin
40e448fe95 fix(search): WebSearchService HTTP timeout 추가 (connect 5s, request 15s)
- 특정 검색에서 무한 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>
2026-06-15 21:52:31 +09:00
joungmin
8a21646031 fix(admin): bulk-tabling/catchtable SSE timeout 10분 → 3시간
- 대량 백필(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>
2026-06-15 21:08:55 +09:00
joungmin
52090057de fix(restaurant): #357 후속 — tabling-url validation에 www. 호스트 허용
- 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>
2026-06-15 21:02:32 +09:00
joungmin
d73947444f feat(backend): #359 1단계 — google_place_id 중복 조회 API
- 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>
2026-06-15 20:32:40 +09:00
joungmin
c1050f3abd feat(backend): #358 RestaurantUpdateDTO + @Valid 표준화
- 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>
2026-06-15 20:20:51 +09:00
joungmin
a504bf8ee5 feat(backend): #357 DDG → Naver Search 정식 API + DDG 폴백
- 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>
2026-06-15 20:16:14 +09:00
joungmin
47020fd649 feat(backend): #356 영상-식당 관련도 LLM 평가
- 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>
2026-06-15 19:38:07 +09:00
joungmin
8152b71119 docs(changelog): v0.1.42 #351 SSE 통일 기록 2026-06-15 17:17:14 +09:00
joungmin
cf1055bdf9 docs(changelog): v0.1.40 #343 테스트 인프라 기록 2026-06-15 16:29:22 +09:00
joungmin
8c4b0c3e9a docs(changelog): v0.1.38 #348 isNameSimilar 한국어 기록 2026-06-15 16:12:46 +09:00
joungmin
cc4bc0b7e4 docs(changelog): #352 i18n 뼈대 + v0.1.37 기록 2026-06-15 16:02:40 +09:00
joungmin
fda2d76514 docs(changelog): #329 어드민 분리 기록 2026-06-15 15:53:34 +09:00
joungmin
7411c8956f docs(changelog): v0.1.34 #331 VectorService batchUpdate 기록 2026-06-15 15:42:43 +09:00
joungmin
11e1cf7877 docs(changelog): v0.1.33 #326 parseJson 단일 패스 기록 2026-06-15 15:37:48 +09:00
joungmin
ed61d29632 docs(changelog): v0.1.32 #332 화이트리스트 기록 2026-06-15 15:33:52 +09:00
joungmin
109ad106ac docs(changelog): v0.1.31 #337 봇/레이트리밋 기록 2026-06-15 15:28:52 +09:00
joungmin
9743f96af7 docs(changelog): v0.1.30 #335 ShedLock 분산 락 기록 2026-06-15 15:21:20 +09:00
joungmin
079384b645 docs(changelog): v0.1.29 #336 SCAN/UNLINK/복구/메트릭 기록 2026-06-15 15:09:57 +09:00
joungmin
f126664117 docs(changelog): P5-2 작은 후속 기록 2026-06-15 14:51:22 +09:00
joungmin
3304b9c54f docs(changelog): v0.1.24 P5-1 작은 후속 기록 2026-06-15 14:44:08 +09:00
joungmin
dcebb9f06f docs(changelog): v0.1.23 P4-4 별점/로그인 결함 기록 2026-06-15 14:34:27 +09:00
joungmin
ea8db4bef3 docs(changelog): v0.1.22 P4-3 인증/지도 결함 기록 2026-06-15 14:29:10 +09:00
joungmin
865cd86aff docs(changelog): v0.1.21 데몬/캐시/통계 결함 기록 2026-06-15 14:22:13 +09:00
joungmin
5579c5b00f docs(changelog): v0.1.20 백엔드 CRUD 결함 기록 (#290+#294+#295) 2026-06-15 14:16:41 +09:00
joungmin
eb1eaa91a6 docs(changelog): v0.1.19 #293 검색/벡터 결함 기록 2026-06-15 14:04:09 +09:00
joungmin
7779d5ddfd docs(changelog): v0.1.18 어드민 검증 UI 기록 (#304+#323) 2026-06-15 13:58:56 +09:00
joungmin
04c54d1b1a docs(changelog): v0.1.17 백엔드 결함 일괄 수정 기록 (#291+#292) 2026-06-15 13:23:51 +09:00
joungmin
7fa623d22d docs: CHANGELOG v0.1.15+v0.1.16 기록 + #322 설계서 Approved 2026-06-15 13:07:08 +09:00
joungmin
dc8a8e9b4c docs(changelog): #301+#302 모달 접근성 + race condition + 필터 동기화 (v0.1.14) 2026-06-15 12:25:12 +09:00
joungmin
2d41f22b83 fix(infra): #316 backend resource request 재산정 + RollingUpdate 25%/25% 복귀
노드 다운사이징(2×1OCPU/6GB) 이후 backend CPU request 500m이 노드 한도
의 절반을 차지해 rollingUpdate 데드락 발생. 임시 패치(maxSurge=0/
maxUnavailable=1) 상태를 합리화하여 25%/25% 기본 정책으로 복귀.

변경:
- cpu 500m/1 → 300m/800m
- mem 768Mi/1536Mi → 512Mi/1024Mi
- strategy 25%/25% 명시 (기본값 복귀)

근거: 실측 idle CPU 0.7%, RSS ~305 MB. peak 30-40% 추정 안에서 안전.
검증: 적용 후 노드 잔여 330m → 다음 배포 시 두 Pod 공존 가능 (무중단).
다운타임: 이번 1회 ~25초 (구 500m Pod 점유 해제), 다음 배포부터 0초.

설계서: docs/design/316-backend-resource-rightsize/README.md (Approved).

Refs: #316
2026-06-15 12:07:47 +09:00
joungmin
2a6d307260 docs(changelog): OKE 다운사이징 + Orphan LB 삭제 + v0.1.13 배포 기록 2026-06-15 11:55:16 +09:00
joungmin
4638f605aa fix(security): [Developer] #267 AdminUserController GET 4종에 requireAdmin() 추가
CRITICAL: listUsers, userFavorites, userReviews, userMemos 4개 GET이 인증만 요구하고 admin 검사가 없어, 일반 사용자 토큰으로 전체 사용자 목록 및 타인 활동 조회 가능했음. 각 메서드 첫 줄에 AuthUtil.requireAdmin() 호출 추가 → non-admin은 403.

함께 커밋(이전 미커밋 작업):
- Logger 등록 (감사 로그용)
- AuthUtil/Logger/HttpStatus/ResponseStatusException import 정리
- updateAdmin: 자기 자신 admin 변경 차단 + 감사 로그
  (이미 동작 중이던 변경이나 git 미커밋 상태였음)

문서:
- 설계서 §3 인수조건에 권한 강제 항목 추가, 상태 Draft → Approved
- CHANGELOG.md 2026-06-15 핫픽스 항목 추가

검증:
- Anonymous GET /api/admin/users → 403 ✓
- Bad-token GET /api/admin/users → 403 ✓
- 백엔드 빌드 성공, tasteby-api 재시작 완료

Refs: #267
2026-06-15 11:17:48 +09:00
joungmin
80b553ec19 docs: 현행화 17개 설계서 Approved + 후속 이슈 백로그 등록
Reviewer 결과 17 PASS / 1 REJECT (#267 admin 권한 critical).
- 17개 설계서를 Draft → Approved로 갱신
- #267(backend-user)은 critical 결함으로 06-Reviewer 유지
- 후속 17개 개선 이슈(#289~#305) 자동 등록 — 결함 124건 백로그 반영
  (critical 3 / major 46 / minor 75)
- docs/README.md에 18개 설계서 인덱스 추가
- CHANGELOG.md 2026-06-15 섹션 추가

Refs: #266 #268-#283 (현행화 완료) #267 (대기) #289-#305 (백로그)
2026-06-15 11:08:18 +09:00