diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c44e9a..a682b5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ --- +## 2026-06-28 + +### ๐Ÿ› ์ง€์—ญ ํ‘œ์‹œ ๊ณ„์ธตํ™” โ€” "ํ•œ๊ตญ|์„œ์šธ" โ†’ "ํ•œ๊ตญ โ€บ ์„œ์šธ" (#532) +- ๋ฌธ์ œ: ์‹๋‹น ์ƒ์„ธ/๋ฆฌ์ŠคํŠธ๊ฐ€ region ์›๋ณธ(`ํ•œ๊ตญ|์„œ์šธ|๊ฐ•๋‚จ๊ตฌ`, ํŒŒ์ดํ”„ ๋…ธ์ถœ)์„ ๊ทธ๋Œ€๋กœ ํ‘œ์‹œ +- ํ•ด๊ฒฐ: ๊ณต์šฉ ์œ ํ‹ธ `lib/region.ts` `formatRegion()` ์‹ ์„ค โ€” ๋นˆํ† ํฐ/`null`/๋”๋ฏธ(`๋‚˜๋ผ`) ์ œ๊ฑฐ ํ›„ ` โ€บ ` ๊ณ„์ธต ์กฐ์ธ +- ์ ์šฉ: `RestaurantDetail.tsx`(์ง€์—ญ ํ‘œ๊ธฐ), `RestaurantList.tsx`(์นด๋“œ ์ง€์—ญ) +- ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์šฉ `buildSearchQuery`(๊ณต๋ฐฑ ์กฐ์ธ)๋Š” ์œ ์ง€ โ€” ์™ธ๋ถ€ ์ง€๋„ ๊ฒ€์ƒ‰ ํ˜ธํ™˜ +- ์„ค๊ณ„์„œ: `docs/design/532-region-display/README.md` + ## 2026-06-17 ### ๐ŸŽฏ ํด๋Ÿฌ์Šคํ„ฐ expansion ํ›„ ๋งˆ์ปค ํด๋ฆญ ์‹œ ์žฌ๋ฌถ์ž„ ๋ฐฉ์ง€ (v0.1.66) diff --git a/docs/design/532-region-display/README.md b/docs/design/532-region-display/README.md new file mode 100644 index 0000000..3888270 --- /dev/null +++ b/docs/design/532-region-display/README.md @@ -0,0 +1,43 @@ +# #532 โ€” ์ง€์—ญ ํ‘œ์‹œ ๊ณ„์ธตํ™” (formatRegion) + +## ๋ฐฐ๊ฒฝ / ๋ฌธ์ œ +์ง€์—ญ(`region`)์€ `๋‚˜๋ผ|์‹œ๋„|๊ตฌ๊ตฐ` ํŒŒ์ดํ”„ ๊ตฌ๋ถ„ ๋ฌธ์ž์—ด(์˜ˆ: `ํ•œ๊ตญ|์„œ์šธ|๊ฐ•๋‚จ๊ตฌ`). +์‚ฌ์šฉ์ž ํ™”๋ฉด์— **์›๋ณธ์ด ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ**๋˜์–ด `ํ•œ๊ตญ|์„œ์šธ|๊ฐ•๋‚จ๊ตฌ`(ํŒŒ์ดํ”„) ๋˜๋Š” ํ‰๋ฌธ `ํ•œ๊ตญ ์„œ์šธ`๋กœ ๋ณด์ž„. +๊ธฐ๋Œ€: **`ํ•œ๊ตญ โ€บ ์„œ์šธ โ€บ ๊ตฌ๊ตฐ`** ๊ณ„์ธต(breadcrumb) ํ‘œ์‹œ. + +## ๋ฒ”์œ„ +- ์‹๋‹น ์ƒ์„ธ ์‹œํŠธ์˜ "์ง€์—ญ" ํ‘œ๊ธฐ (`RestaurantDetail.tsx`) +- ์‹๋‹น ๋ฆฌ์ŠคํŠธ ์นด๋“œ์˜ ์ง€์—ญ ํ‘œ๊ธฐ (`RestaurantList.tsx`) +- ๊ณต์šฉ ์œ ํ‹ธ `formatRegion()` ์‹ ์„ค (`lib/region.ts`) + +๋น„๋ฒ”์œ„: ์ง€์—ญ *ํ•„ํ„ฐ* ๋™์ž‘/์ •๋ ฌ(์ •์ƒ), ์™ธ๋ถ€ ์ง€๋„ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ(`buildSearchQuery` โ€” ๊ณต๋ฐฑ ์กฐ์ธ ์œ ์ง€), ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ(๋ณ„๋„ ์ด์Šˆ). + +## ํ•จ์ˆ˜ ์„ค๊ณ„ + +### `formatRegion(region: string | null | undefined): string` +- **์ž…๋ ฅ**: ํŒŒ์ดํ”„ ๊ตฌ๋ถ„ ์ง€์—ญ ๋ฌธ์ž์—ด (์˜ˆ: `"ํ•œ๊ตญ|์„œ์šธ|๊ฐ•๋‚จ๊ตฌ"`, `"์ผ๋ณธ|null"`, `"ํ•œ๊ตญ||๊ด€์•…๊ตฌ"`, `""`) +- **์ฒ˜๋ฆฌ**: + 1. falsy โ†’ `""` ๋ฐ˜ํ™˜ + 2. `split("|")` โ†’ ๊ฐ ํ† ํฐ `trim()` + 3. ๋นˆ ํ† ํฐ, `"null"`(๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ), ๋”๋ฏธ `"๋‚˜๋ผ"` ์ œ๊ฑฐ + 4. ๋‚จ์€ ํ† ํฐ์„ `" โ€บ "`(U+203A)๋กœ ์กฐ์ธ +- **์ถœ๋ ฅ ์˜ˆ**: + | ์ž…๋ ฅ | ์ถœ๋ ฅ | + |---|---| + | `ํ•œ๊ตญ\|์„œ์šธ\|๊ฐ•๋‚จ๊ตฌ` | `ํ•œ๊ตญ โ€บ ์„œ์šธ โ€บ ๊ฐ•๋‚จ๊ตฌ` | + | `์ผ๋ณธ\|null` | `์ผ๋ณธ` | + | `ํ•œ๊ตญ\|\|๊ด€์•…๊ตฌ` | `ํ•œ๊ตญ โ€บ ๊ด€์•…๊ตฌ` | + | `""` / `null` | `""` (ํ˜ธ์ถœ๋ถ€์—์„œ ๋ฏธํ‘œ์‹œ) | +- **์ˆœ์ˆ˜ ํ•จ์ˆ˜**(I/O ์—†์Œ) โ†’ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์šฉ์ด. + +### ์ ์šฉ +- `RestaurantDetail.tsx:132`: `{restaurant.region}` โ†’ `{formatRegion(restaurant.region)}` +- `RestaurantList.tsx:54`: `{r.region}` โ†’ `{formatRegion(r.region)}` + +## ์—ฃ์ง€์ผ€์ด์Šค +- ๋ชจ๋“  ํ† ํฐ์ด ๋”๋ฏธ/๋นˆ ๊ฐ’(`"ํ•œ๊ตญ|"`, `"|"`) โ†’ ์œ ํšจ ํ† ํฐ๋งŒ ๋‚จ๊น€(`ํ•œ๊ตญ`) ๋˜๋Š” `""`. ํ˜ธ์ถœ๋ถ€๋Š” `region &&` ๊ฐ€๋“œ๊ฐ€ ์žˆ์–ด `""`์ด๋ฉด ๋ฏธํ‘œ์‹œ. +- ๋‹จ์ผ ํ† ํฐ(`"ํ•œ๊ตญ"`) โ†’ `ํ•œ๊ตญ` ๊ทธ๋Œ€๋กœ. + +## ๊ฒ€์ฆ +- ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(๊ฐ€๋Šฅ ์‹œ) ๋˜๋Š” dev ํ™”๋ฉด์—์„œ ์ƒ์„ธ/๋ฆฌ์ŠคํŠธ ์ง€์—ญ ํ‘œ๊ธฐ๊ฐ€ `โ€บ` ๊ณ„์ธต์œผ๋กœ ๋ณด์ด๋Š”์ง€. +- `npm run build`(๋˜๋Š” tsc/lint) ํ†ต๊ณผ. diff --git a/frontend/src/components/RestaurantDetail.tsx b/frontend/src/components/RestaurantDetail.tsx index 790df49..22f1d92 100644 --- a/frontend/src/components/RestaurantDetail.tsx +++ b/frontend/src/components/RestaurantDetail.tsx @@ -7,6 +7,7 @@ import ReviewSection from "@/components/ReviewSection"; import MemoSection from "@/components/MemoSection"; import { RestaurantDetailSkeleton } from "@/components/Skeleton"; import Icon from "@/components/Icon"; +import { formatRegion } from "@/lib/region"; interface RestaurantDetailProps { restaurant: Restaurant; @@ -129,7 +130,7 @@ export default function RestaurantDetail({ )} {restaurant.region && (

- ์ง€์—ญ {restaurant.region} + ์ง€์—ญ {formatRegion(restaurant.region)}

)} {restaurant.price_range && ( diff --git a/frontend/src/components/RestaurantList.tsx b/frontend/src/components/RestaurantList.tsx index a9aca30..5431891 100644 --- a/frontend/src/components/RestaurantList.tsx +++ b/frontend/src/components/RestaurantList.tsx @@ -3,6 +3,7 @@ import type { Restaurant } from "@/lib/api"; import { getCuisineIcon } from "@/lib/cuisine-icons"; import Icon from "@/components/Icon"; +import { formatRegion } from "@/lib/region"; import { RestaurantListSkeleton } from "@/components/Skeleton"; interface RestaurantListProps { @@ -51,7 +52,7 @@ export default function RestaurantList({ {r.name} {r.region && ( - {r.region} + {formatRegion(r.region)} )} {r.rating && ( โ˜… {r.rating} diff --git a/frontend/src/lib/region.ts b/frontend/src/lib/region.ts new file mode 100644 index 0000000..7924478 --- /dev/null +++ b/frontend/src/lib/region.ts @@ -0,0 +1,22 @@ +// ์ง€์—ญ ํ‘œ์‹œ ์œ ํ‹ธ โ€” #532 +// region ์€ "๋‚˜๋ผ|์‹œ๋„|๊ตฌ๊ตฐ" ํŒŒ์ดํ”„ ๊ตฌ๋ถ„ ๋ฌธ์ž์—ด. ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ๊ณ„์ธต(breadcrumb)์œผ๋กœ ๋ณด์—ฌ์ค€๋‹ค. + +/** ํ‘œ์‹œ์—์„œ ์ œ์™ธํ•  ๋”๋ฏธ/๋ฌด์˜๋ฏธ ํ† ํฐ. */ +const DUMMY_TOKENS = new Set(["", "null", "๋‚˜๋ผ"]); + +/** + * ํŒŒ์ดํ”„ ๊ตฌ๋ถ„ region ์„ "๋‚˜๋ผ โ€บ ์‹œ๋„ โ€บ ๊ตฌ๊ตฐ" ๊ณ„์ธต ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. + * ๋นˆ ํ† ํฐยท"null"ยท๋”๋ฏธ("๋‚˜๋ผ")๋Š” ์ œ๊ฑฐํ•œ๋‹ค. ์œ ํšจ ํ† ํฐ์ด ์—†์œผ๋ฉด "". + * + * ์˜ˆ) "ํ•œ๊ตญ|์„œ์šธ|๊ฐ•๋‚จ๊ตฌ" โ†’ "ํ•œ๊ตญ โ€บ ์„œ์šธ โ€บ ๊ฐ•๋‚จ๊ตฌ" + * "์ผ๋ณธ|null" โ†’ "์ผ๋ณธ" + * "ํ•œ๊ตญ||๊ด€์•…๊ตฌ" โ†’ "ํ•œ๊ตญ โ€บ ๊ด€์•…๊ตฌ" + */ +export function formatRegion(region: string | null | undefined): string { + if (!region) return ""; + return region + .split("|") + .map((t) => t.trim()) + .filter((t) => !DUMMY_TOKENS.has(t.toLowerCase())) + .join(" โ€บ "); +}