기능(isKoreaRestaurant 게이트)은 QA 통과 상태 그대로 유지, 표현/접점만 보완. - 테이블링/캐치테이블 링크에 title="… (새 탭)" 추가 — 새 탭 이동을 미리 알려 예약 흐름 중 예기치 않은 이탈감 완화 - 로고 대체용 단일 문자(T/C)에 aria-hidden="true" — 스크린리더가 의미 없는 낱글자를 중복 낭독하지 않도록 정리 - tsc --noEmit / RestaurantDetail.test.tsx 5/5 통과 (회귀 없음) Refs #545
5.8 KiB
5.8 KiB
설계서: 해외 식당 예약 버튼(테이블링/캐치테이블) 숨김 (#545)
상태: Approved · QA 통과 · Designer 접근성 다듬기 완료 작성: [AI] Architect (소급 작성 — Developer 구현 후 게이트 보완) · 최종수정: 2026-07-27 ([AI] Designer) 추적성 — Redmine: #545 · 관련 ADR: 없음 · 구현 파일:
frontend/src/components/RestaurantDetail.tsx· 테스트:frontend/__tests__/RestaurantDetail.test.tsx(5케이스, 육안 QA를 자동화 회귀 테스트로 대체)
1. 목적 (Why)
해외 식당 상세에 국내 전용 예약 서비스(테이블링/캐치테이블) 버튼이 노출되는 버그를 막는다. 테이블링/캐치테이블은 국내 식당만 지원하므로, 해외 식당에서는 두 버튼을 숨겨야 한다.
2. 범위 (Scope)
- 포함:
RestaurantDetail.tsx의 테이블링/캐치테이블 예약 버튼 2종에 국내 판정 게이트 적용. - 제외 (out of scope): 백엔드 예약 URL 검색/벌크 수집이 해외 식당을 제외하도록 하는 것 (#545 후속, 별도 이슈로 분리 가능).
3. 인수조건 (Acceptance Criteria)
- 해외 식당(좌표가 한국 bbox 밖) 상세에서 테이블링/캐치테이블 버튼이 보이지 않는다.
- 국내 식당 상세에서는 기존과 동일하게 두 버튼이 보인다 (URL 존재 시).
tsc타입체크 통과.- QA 확인 (해외/국내 식당 각 1건 이상, 대표 발견 케이스 포함) — 자동화 회귀 테스트로 대체 검증 완료(
RestaurantDetail.test.tsx).
4. 컨텍스트 & 제약
- 의존성:
Restaurant.latitude/longitude,Restaurant.region(좌표 없는 구 데이터 fallback). - 제약: 기존 지도 링크 분기(151행)에 이미 쓰이던
isKoreaRestaurant()판정 기준과 동일하게 유지해야 함(판정 기준 이원화 방지). - 가정:
tabling_url/catchtable_url이"NONE"이 아니고 값이 있어도, 해외 식당이면 노출하지 않는다.
5. 아키텍처 개요
- 변경 파일:
frontend/src/components/RestaurantDetail.tsx1개. - 데이터 흐름:
restaurantprop →isKoreaRestaurant(restaurant)순수 판정 → JSX 렌더 게이트. - I/O 없음, 순수 함수 기반 조건부 렌더링만 추가.
Restaurant (좌표/region)
│
▼
isKoreaRestaurant(r) ──false──▶ 테이블링/캐치테이블 버튼 미렌더
│
true
│
▼
기존 로직: url 존재 && != "NONE" → 버튼 렌더
6. 데이터 모델
- 입력:
Restaurant { latitude?, longitude?, region?, tabling_url?, catchtable_url? }(기존 타입, 변경 없음). - 출력: 없음 (렌더 분기만).
- 경계 검증:
isKoreaRestaurant()내부에서 이미 null/undefined 가드 처리(좌표 없으면 region 첫 토큰 fallback).
7. 함수 명세 (Function Specs)
| 함수 | 책임(1줄) | 시그니처 | 입력 | 출력 | 에러/실패 | 복잡? |
|---|---|---|---|---|---|---|
isKoreaRestaurant |
좌표/region 기반 국내 식당 판정 (기존 함수, 변경 없음 — 적용 범위만 확대) | (r: Restaurant) => boolean |
Restaurant |
boolean |
없음 (순수 함수) | 단순 |
신규 함수 없음. 기존
isKoreaRestaurant()(30행, 지도 링크 분기용으로 이미 존재)를 예약 버튼 2곳에도 동일 적용.
8. 흐름 / 알고리즘
isKoreaRestaurant(restaurant)평가 (좌표 우선, KR bbox 3338.7°N / 124132°E; 좌표 없으면region첫 토큰이"한국"인지로 fallback).true일 때만 기존 조건(tabling_url/catchtable_url존재 &&!== "NONE")을 이어서 평가.- 최종
true일 때만 버튼 렌더.
9. 엣지케이스 & 에러 처리
- 좌표와 region 모두 없는 구 데이터 →
isKoreaRestaurant는!r.region조건으로true반환(국내로 간주, 기존 동작 유지 — 회귀 아님). - 좌표가 KR bbox 경계값에 걸치는 경우(제주/울릉도 등) → 기존 지도 링크 판정과 동일 로직이므로 별도 리스크 없음(기존에 검증된 임계값 재사용).
10. 테스트 계획
tsc통과 (완료).- 자동화 회귀 테스트(
frontend/__tests__/RestaurantDetail.test.tsx, RTL) — [AI] QA 작성, 5케이스 전부 통과:- 국내 좌표(서울) + URL 존재 → 두 버튼 노출.
- 해외 좌표(방콕, 대표 발견 케이스) + URL 존재 → 두 버튼 숨김.
- 해외 좌표(도쿄) + URL 없음 → 숨김 유지(회귀 없음).
- 좌표 없음 + region null → fallback으로 국내 간주, 버튼 노출(기존 동작 유지).
- URL이
"NONE"문자열 → 국내 식당이어도 버튼 없음(기존 게이트 유지).
11. 리스크 & 대안 검토
- 대안: 백엔드에서 해외 식당의
tabling_url/catchtable_url을 애초에 null로 채우지 않는 방법도 있으나, 프론트 게이트가 더 즉각적이고 기존 판정 로직 재사용 가능 → 채택. - 되돌리기 어려운 결정 없음. ADR 불필요.
12. 미해결 질문 (Open Questions)
- 백엔드 예약 URL 수집/검색 단계에서 해외 식당을 원천 제외할지 여부는 별도 이슈로 분리할 가치가 있음 (설명에 "후속(옵션)"으로 명시됨).
13. Designer 다듬기 (표현/접점, 기능 변경 없음)
- 판정 로직(
isKoreaRestaurant)과 노출 조건은 QA 통과 상태 그대로 — 변경하지 않음. - 테이블링/캐치테이블 앵커에
title속성 추가("… (새 탭)") — 새 탭 이동을 사전에 알려 예약 흐름 중 예기치 않은 이탈감 완화. - 로고 대체용 단일 문자 배지(
T/C)에aria-hidden="true"적용 — 스크린리더가 의미 없는 낱글자를 중복 낭독하지 않고 실제 라벨만 읽도록 정리. - 회귀 확인:
tsc --noEmit통과,frontend/__tests__/RestaurantDetail.test.tsx5/5 통과.