Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7789671fbc | ||
|
|
c5b0216a37 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -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 둘 다)
|
||||
|
||||
@@ -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/"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,22 +147,33 @@ export default function RestaurantDetail({
|
||||
)}
|
||||
{restaurant.google_place_id && (
|
||||
<p className="flex gap-3">
|
||||
<a
|
||||
href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(buildSearchQuery(restaurant))}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-brand-600 dark:text-brand-400 hover:underline text-xs"
|
||||
>
|
||||
Google Maps에서 보기
|
||||
</a>
|
||||
{(!restaurant.region || restaurant.region.split("|")[0] === "한국") && (
|
||||
{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://map.naver.com/v5/search/${encodeURIComponent(restaurant.name)}`}
|
||||
href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(buildSearchQuery(restaurant))}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-green-600 dark:text-green-400 hover:underline text-xs"
|
||||
className="text-brand-600 dark:text-brand-400 hover:underline text-xs"
|
||||
>
|
||||
네이버 지도에서 보기
|
||||
Google Maps에서 보기
|
||||
</a>
|
||||
)}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user