# #533 — 언급 적은(관련도 낮은) 식당 제외 필터

## 배경 / 문제
영상에서 잠깐·우연히 언급된(=관련도 낮은) 식당까지 모두 노출되어 신호 대비 잡음이 큼.
사용자가 "언급이 충분한 식당만" 보도록 제외 필터 제공.

## 신호 정의
"의미있는 언급 수(`video_count`)" = 해당 식당의 `video_restaurants` 링크 중
**relevance ∈ ('strong','unknown')** 개수. (weak/incidental = 곁다리 언급 → 제외)
→ 기존 `findVideoLinks` 기본 노출 정책(strong/unknown)과 일관.

## 범위
- **백엔드**: 식당 목록 응답에 `video_count` 포함 + `min_mentions` 서버 필터 파라미터.
- **프론트**: `Restaurant.video_count` 타입 + 클라이언트 필터 UI(전체/2회+/3회+).
- 서버사이드 필터 일원화(현 클라 필터 패턴 통일)는 **#535**로 분리.

## 함수/변경 설계

### 백엔드
1. `domain/Restaurant.java` — `Integer videoCount` 필드 추가(전이 enrichment).
2. `mapper/RestaurantMapper.xml`
   - `restaurantMap` resultMap: `<result property="videoCount" column="video_count"/>`
   - `findAll` SELECT에 스칼라 서브쿼리 추가:
     `(SELECT COUNT(*) FROM video_restaurants vrc WHERE vrc.restaurant_id = r.id AND vrc.relevance IN ('strong','unknown')) AS video_count`
   - `findAll` `<where>`에 optional 필터:
     `<if test="minMentions != null and minMentions > 0"> AND (위 서브쿼리) &gt;= #{minMentions} </if>`
3. `mapper/RestaurantMapper.java` — `@Param("minMentions") Integer minMentions` 추가.
4. `service/RestaurantService.java` — `findAll(..., Integer minMentions, boolean includeHidden)`로 스레드. 5-arg 오버로드는 `null, false` 전달.
5. `controller/RestaurantController.java` — `@RequestParam("min_mentions") Integer minMentions` + 캐시 키에 `mm=` 포함.

### 프론트
6. `lib/api.ts` — `Restaurant.video_count?: number | null`; `getRestaurants` 파라미터 `min_mentions?`(미래/서버필터용).
7. `app/page.tsx` — 필터 상태 `minMentions`(0/2/3) + `filteredRestaurants`에 `(r.video_count ?? 0) >= minMentions` 가드 + UI 컨트롤 + useMemo deps 추가.

## 엣지케이스
- `video_count` 미산정(findById 등) → null. 클라 필터는 `?? 0`로 안전.
- minMentions=0(기본) → 필터 미적용(기존 동작 유지).
- DISTINCT + 스칼라 서브쿼리: r.id 단위라 결과 불변.

## 검증
- 백엔드 빌드 성공 → PM2 재시작.
- `GET /api/restaurants?min_mentions=2` 가 2회 미만 식당 제외하는지.
- 응답에 `video_count` 포함 확인.
- 프론트 토글로 목록/지도가 줄어드는지.
