Compare commits

..

2 Commits

Author SHA1 Message Date
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
3 changed files with 48 additions and 13 deletions

View File

@@ -4,8 +4,22 @@
---
## 2026-06-16
### 🗺️ 식당 상세 지도 링크 국내/해외 분기 (v0.1.51)
- 좌표 기반 한국 판정 (WGS84 KR bbox 33~38.7°N, 124~132°E)
- 국내: 네이버 지도 primary + Google Maps 보조 (네이버 URL은 신 도메인 /p/search/)
- 해외: Google Maps 단독
- 좌표 없으면 region 첫 토큰 fallback (구 데이터 호환)
- frontend-only 배포
## 2026-06-15
### 🐛 캐치테이블 URL 패턴 수정 (v0.1.50)
- 실제 catchtable URL은 `app.catchtable.co.kr/ct/shop/...` 형식 (옛 `/shop/`, `/dining/`은 매칭 실패)
- 첫 회차(v0.1.49) 캐치테이블 벌크 결과 1044건 전부 미발견(매핑 0%)의 원인
- 패턴을 `catchtable.co.kr/ct/shop/`, `catchtable.co.kr/ct/dining/`로 교정 후 NONE 해제 + 재실행
### 🐛 WebSearchService HTTP timeout 추가 (v0.1.49)
- 벌크 백필 중 특정 검색에서 무한 hang → backend executor virtual thread 점유로 후속 작업 중단 (90건 처리 후 멈춤)
- connectTimeout=5s + request timeout=15s (Naver/DDG 둘 다)

View File

@@ -423,9 +423,10 @@ public class RestaurantController {
}
private List<Map<String, Object>> searchCatchtable(String restaurantName) {
// 실제 캐치테이블 URL은 /ct/shop/ 형식. 옛 /dining/ /shop/ 패턴은 매칭 실패.
return webSearch.search(
"site:app.catchtable.co.kr " + restaurantName,
"catchtable.co.kr/dining/", "catchtable.co.kr/shop/"
"catchtable.co.kr/ct/shop/", "catchtable.co.kr/ct/dining/"
);
}

View File

@@ -24,6 +24,15 @@ function buildSearchQuery(r: Restaurant): string {
return r.name;
}
// 좌표 기반 한국 판정 (WGS84). KR bbox 대략 33~38.7°N, 124~132°E.
// 좌표 없으면 region 첫 토큰으로 fallback (구 데이터 호환).
function isKoreaRestaurant(r: Restaurant): boolean {
if (r.latitude != null && r.longitude != null) {
return r.latitude >= 33 && r.latitude <= 38.7 && r.longitude >= 124 && r.longitude <= 132;
}
return !r.region || r.region.split("|")[0] === "한국";
}
export default function RestaurantDetail({
restaurant,
onClose,
@@ -138,6 +147,26 @@ export default function RestaurantDetail({
)}
{restaurant.google_place_id && (
<p className="flex gap-3">
{isKoreaRestaurant(restaurant) ? (
<>
<a
href={`https://map.naver.com/p/search/${encodeURIComponent(buildSearchQuery(restaurant))}`}
target="_blank"
rel="noopener noreferrer"
className="text-green-600 dark:text-green-400 hover:underline text-xs"
>
</a>
<a
href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(buildSearchQuery(restaurant))}`}
target="_blank"
rel="noopener noreferrer"
className="text-gray-500 dark:text-gray-400 hover:underline text-xs"
>
Google Maps
</a>
</>
) : (
<a
href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(buildSearchQuery(restaurant))}`}
target="_blank"
@@ -146,15 +175,6 @@ export default function RestaurantDetail({
>
Google Maps에서
</a>
{(!restaurant.region || restaurant.region.split("|")[0] === "한국") && (
<a
href={`https://map.naver.com/v5/search/${encodeURIComponent(restaurant.name)}`}
target="_blank"
rel="noopener noreferrer"
className="text-green-600 dark:text-green-400 hover:underline text-xs"
>
</a>
)}
</p>
)}