Skip to content

Conversation

@leeleeleeleejun
Copy link
Member

@leeleeleeleejun leeleeleeleejun commented Aug 18, 2025

#️⃣연관된 이슈

📝작업 내용

카테고리 상세페이지 화면 UI 구현 및 API 관련 query 로직 등 구현

  • HeaderBackButton 컴포넌트 추가 659a5e7

    • Header에서 자주 쓰이는 뒤로가기 버튼을 공통 컴포넌트로 분리했습니다.
  • 카테고리 페이지 전환 애니메이션 적용 757c324

    • categories/Template 컴포넌트를 추가하여 하위 페이지 이동 시 slide animation이 동작하도록 구현했습니다.
  • 페이지에서 선택 카테고리를 변경할 수 있는 RowCategories 컴포넌트 입니다. cfd5bcd

    • ScrollHintGradient를 적용해 오른쪽 끝에 흰색 그라데이션을 두어 스크롤 가능 여부를 시각적으로 표시했습니다.
  • API_PATH 수정

    • RANKING → BY_RANKING으로 이름 변경 (일관성 확보)
    • PLACES 필드를 추가해 Places 관련 API Path를 별도로 관리하도록 개선

스크린샷 (선택)

2025-08-18.6.07.46.mov

💬리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

Summary by CodeRabbit

  • 신기능

    • 카테고리 상세 페이지 추가: 가로 스크롤 카테고리 선택 및 선택 카테고리별 맛집 목록 표시.
    • 뒤로가기 버튼 추가 및 공통 애니메이션 컨테이너 도입으로 페이지 전환 시 슬라이드 효과 제공.
  • 스타일

    • 레이아웃 너비를 반응형(최대 450px)으로 변경.
    • 헤더에 className 지원 추가로 스타일 커스터마이즈 가능.
  • 리팩터

    • 랭킹/카테고리 기반 데이터 조회 체계 정비 및 관련 컴포넌트명·출력 형식 정리.

@leeleeleeleejun leeleeleeleejun self-assigned this Aug 18, 2025
@leeleeleeleejun leeleeleeleejun linked an issue Aug 18, 2025 that may be closed by this pull request
1 task
@coderabbitai
Copy link

coderabbitai bot commented Aug 18, 2025

Walkthrough

랭킹 기반 장소 API를 PLACES 네임스페이스로 재구성하고 byRanking·byCategory 쿼리를 도입했습니다. 카테고리 상세 페이지(동적 라우트)와 관련 컴포넌트(RowCategories/Places/CategoryItem)를 추가하고, HeaderBackButton과 페이지 전환 Template을 도입했습니다.

Changes

Cohort / File(s) Summary
Queries & Services API 재구성
apps/web/app/_apis/queries/place.ts, apps/web/app/_apis/services/place.ts, apps/web/app/_constants/path.ts
rankingListbyRanking로 키·호출명 변경, getRankingPlacesgetPlacesByRanking로 변경, byCategory/getPlacesByCategory 추가. API_PATH.RANKING 제거·API_PATH.PLACES.{BY_RANKING,BY_CATEGORY} 추가.
Schemas 정리
apps/web/app/_apis/schemas/place.ts
RankingPlaceSchema/RankingPlace 제거. 파싱을 BasePlaceSchema로 통일.
랭킹 컴포넌트 정리
apps/web/app/_components/RankingPlaceList/*
MostLikedPlacesMostLikesPlaces로 컴포넌트명·배럴 변경. 내부 쿼리 호출 rankingListbyRanking으로 교체.
카테고리 상세 기능 추가
apps/web/app/categories/[id]/page.tsx, .../CategoryDetailPage.tsx, .../_components/Places/Places.tsx, .../_components/RowCategories/*, .../_components/index.tsx, apps/web/app/categories/template.tsx
동적 라우트 페이지 추가. 카테고리 목록 프리패치 및 카테고리별 장소 프리패치. RowCategories, CategoryItem, Places 컴포넌트 도입 및 배럴 재수출.
템플릿 & 레이아웃
apps/web/app/_template/template.tsx, apps/web/app/layout.tsx
페이지 전환 애니메이션 Template 추가(슬라이드 인/아웃). 레이아웃 폭을 w-[450px]w-full max-w-[450px]로 변경.
헤더 컴포넌트
apps/web/app/_components/HeaderBackButton/*, packages/ui/src/components/Header/Header.tsx
HeaderBackButton 컴포넌트 및 배럴 추가. UI Header에 선택적 className prop 추가(클래스 병합).
메인 페이지 반영
apps/web/app/page.tsx
MostLikedPlacesMostLikesPlaces로 교체, 프리패치/쿼리 호출을 `byRanking('likes'
Mocks 업데이트
apps/web/app/_mocks/data/place.ts, apps/web/app/_mocks/handlers/placeHandlers.ts
Mock 데이터 RankingPlacesPlaces로 명칭 변경, isLiked/likeCount 제거. 핸들러 경로를 API_PATH.PLACES.*로 변경 및 BY_CATEGORY 핸들러 추가.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant NextPage as /categories/{id} Page
  participant RQ as React Query
  participant API as API_PATH.PLACES
  participant UI as CategoryDetailPage

  User->>NextPage: 요청 /categories/{id}
  NextPage->>RQ: prefetch useCategoryQueries.list()
  RQ->>API: GET /categories
  API-->>RQ: categories[]
  NextPage->>RQ: prefetch usePlaceQueries.byCategory(id)
  RQ->>API: GET /places?categoryId={id}
  API-->>RQ: places[]
  NextPage-->>User: HydrationBoundary + CategoryDetailPage(initId)

  User->>UI: 카테고리 선택 클릭
  UI->>RQ: usePlaceQueries.byCategory(newId)
  RQ->>API: GET /places?categoryId={newId}
  API-->>RQ: places[]
  RQ-->>UI: places 렌더 업데이트
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

✨ Feature

Poem

토끼가 전하는 소식:
PLACES로 옮겼다, 깡충 깡충! 🐇
랭킹도 카테고리도 깔끔히 정리했네.
뒤로 가기 버튼은 화살표 한 번 탁—
페이지는 슬라이드로 춤추며 나타나네.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#15

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (1)
apps/web/app/_mocks/data/place.ts (1)

1-32: 모크 데이터 카테고리 ID 충돌 확인 – 즉시 수정 필요

스크립트 실행 결과, apps/web/app/_mocks/data/place.ts 파일의 모크 데이터에서 ID 4가 ‘분식’과 ‘중식’에 중복으로 사용되고 있음을 확인했습니다. 실제 카테고리 마스터 데이터와 일치하도록 아래를 검토·수정해 주세요.

  • 파일: apps/web/app/_mocks/data/place.ts
  • 문제 항목: ID 4 → ['분식', '중식']

수정 방안 예시:

  • ‘중식’ 카테고리에 실제 마스터에서 사용하는 올바른 ID로 변경
  • ‘분식’ 카테고리 ID가 변경된 경우, 마찬가지로 마스터 데이터와 일치하도록 조정

추가 권장 (선택):

  • export const Places: BasePlace[] = […] 형태로 타입 주석을 달아 빌드 타임에 스키마 불일치를 잡아낼 수 있습니다.
🧹 Nitpick comments (15)
apps/web/app/_template/template.tsx (1)

12-19: exit 애니메이션은 현재 구성만으론 실행되지 않을 가능성 높음

Next App Router에서 페이지 전환 시 unmount 애니메이션(exit)을 사용하려면 보통 AnimatePresence(Framer Motion 기준)로 경계에서 관리하고, key를 경로 등으로 변경해 주어야 합니다. 현 구성은 mount 애니메이션(initial/animate)은 동작하되, exit은 트리거되지 않을 수 있습니다. 필요 시 아래와 같이 개선을 고려해 주세요.

예시 (Framer Motion 기준, 참고용):

'use client'
import { motion, AnimatePresence } from 'framer-motion'
import { usePathname } from 'next/navigation'

export default function Template({ children }: { children: React.ReactNode }) {
  const pathname = usePathname()
  return (
    <AnimatePresence mode="wait" initial={false}>
      <motion.div
        key={pathname}
        initial={{ x: 10, opacity: 0 }}
        animate={{ x: 0, opacity: 1 }}
        exit={{ x: -10, opacity: 0 }}
        transition={{ type: 'tween', ease: 'easeOut', duration: 0.3 }}
      >
        {children}
      </motion.div>
    </AnimatePresence>
  )
}
apps/web/app/_components/HeaderBackButton/HeaderBackButton.tsx (2)

10-12: button 기본 type 및 접근성(ARIA) 보완 제안

폼 내부에서 사용될 가능성을 고려하면 type='button' 명시가 안전하며, 스크린 리더를 위해 aria-label을 추가하는 것을 권장합니다.

다음과 같이 보완하면 좋겠습니다.

   return (
-    <button onClick={back}>
+    <button type='button' aria-label='뒤로 가기' onClick={back}>
       <Icon type={'arrowLeft'} size={24} />
     </button>
   )

6-12: 히스토리 부재 시 대체 이동 경로 지원(Optional)

히스토리가 없는 진입(딥링크 등)에서 back이 무의미할 수 있습니다. fallbackHref를 옵션으로 받아 push로 대체하는 패턴을 고려해 볼 수 있습니다.

아래처럼 최소 변경으로 확장 가능합니다.

-export const HeaderBackButton = () => {
-  const { back } = useRouter()
+export const HeaderBackButton = ({ fallbackHref }: { fallbackHref?: string }) => {
+  const router = useRouter()

   return (
-    <button type='button' aria-label='뒤로 가기' onClick={back}>
+    <button
+      type='button'
+      aria-label='뒤로 가기'
+      onClick={() => {
+        if (typeof window !== 'undefined' && window.history.length > 1) {
+          router.back()
+        } else if (fallbackHref) {
+          router.push(fallbackHref)
+        }
+      }}
+    >
       <Icon type={'arrowLeft'} size={24} />
     </button>
   )
apps/web/app/_components/RankingPlaceList/index.tsx (1)

3-3: 리네이밍 반영 좋습니다. 호환성 alias 유지(Optional)

외부 사용처가 많다면 점진적 마이그레이션을 위해 이전 명칭 alias를 잠시 유지하는 것도 방법입니다.

예: 기존 이름으로도 임시 재노출

 export { RankingPlaceList } from './RankingPlaceList'
 export { MostViewsPlaces } from './MostViewsPlaces'
 export { MostLikesPlaces } from './MostLikesPlaces'
+// TODO: 제거 예정 - 점진적 마이그레이션용 호환 alias
+export { MostLikesPlaces as MostLikedPlaces } from './MostLikesPlaces'
apps/web/app/categories/[id]/page.tsx (1)

6-8: Next.js App Router의 params 타입/사용 방식 수정 제안

params는 Promise가 아니라 동기 객체입니다. 타입을 간결히 하고 불필요한 await를 제거해 주세요.

-const Page = async ({ params }: { params: Promise<{ id: string }> }) => {
-  const { id } = await params
+type PageProps = { params: { id: string } }
+const Page = async ({ params }: PageProps) => {
+  const { id } = params
apps/web/app/categories/[id]/_components/RowCategories/RowCategories.tsx (2)

6-10: Props의 id 타입을 Category['id']로 정교화해주세요

런타임/타입 불일치를 방지하려면 idsetIdFunc의 파라미터를 Category['id']로 맞추는 편이 안전합니다. 서버 스키마 변경(예: number→string transform)에도 견고해집니다.

 type Props = {
-  categories: Category[]
-  id: string
-  setIdFunc: (id: string) => void
+  categories: Category[]
+  id: Category['id']
+  setIdFunc: (id: Category['id']) => void
 }

32-43: 스크린 리더 노이즈 방지: ScrollHintGradient를 접근성에서 제외

해당 그라데이션은 장식용이므로 스크린 리더로 읽히지 않도록 aria-hidden을 추가하는 것이 좋습니다. 또한 다크 모드/비화이트 배경에서 from-white 하드코딩이 부자연스러울 수 있으니 테마 토큰 기반으로 전환을 고려해주세요.

다크 모드(또는 비화이트 배경)에서 그라데이션이 떠 보이지 않는지 UI를 한 번 확인 부탁드립니다.

 const ScrollHintGradient = () => (
-  <div
+  <div
+    aria-hidden
     className={cn(
       'absolute',
       'right-[-1px] top-0',
       'h-full w-10',
       'z-10',
       'pointer-events-none',
       'bg-gradient-to-l from-white to-transparent',
     )}
   />
 )
apps/web/app/_apis/services/place.ts (1)

16-19: 카테고리 id를 URL 인코딩하세요

id가 문자열인 이상 쿼리스트링에 안전하게 포함되도록 인코딩을 권장합니다. 현재 API_PATH.PLACES.BY_CATEGORY가 내부 인코딩을 보장하지 않는다면 호출단에서 encodeURIComponent를 적용해 주세요.

API_PATH.PLACES.BY_CATEGORY 내부에서 이미 인코딩하고 있다면 본 제안은 불필요합니다. 확인 부탁드립니다.

 export const getPlacesByCategory = async (id: string): Promise<BasePlace[]> => {
-  const { data } = await axiosInstance.get(API_PATH.PLACES.BY_CATEGORY(id))
+  const { data } = await axiosInstance.get(
+    API_PATH.PLACES.BY_CATEGORY(encodeURIComponent(id)),
+  )
   return BasePlaceSchema.array().parse(data)
 }
apps/web/app/categories/[id]/_components/Places/Places.tsx (1)

5-19: 빈 목록에 대한 UX 보완 제안

카테고리에 해당하는 장소가 0개일 때, 비어 있는 리스트만 노출됩니다. 간단한 Empty State를 추가하면 사용자 경험이 좋아집니다.

예시:

import { Text } from '@repo/ui/components/Text'

export const Places = ({ id }: { id: string }) => {
  const { data: places } = useSuspenseQuery(usePlaceQueries.byCategory(id))

  if (!places.length) {
    return <Text className='px-5 py-4 text-gray-300'>등록된 가게가 없어요</Text>
  }

  return (
    <ul className='px-3'>
      {places.map((place, index) => (
        <PlaceListItem
          key={place.placeId}
          {...place}
          showBorder={index !== places.length - 1}
        />
      ))}
    </ul>
  )
}
apps/web/app/categories/[id]/_components/RowCategories/CategoryItem.tsx (2)

16-21: button 기본 type 명시 및 접근성 속성 보강

폼 내부 사용 시 의도치 않은 submit을 방지하기 위해 type='button'을 명시하고, 선택 상태 전달을 위해 aria-pressed를 추가하는 것을 권장합니다. 키보드 포커스 가시성도 함께 강화하면 좋습니다.

   return (
     <Column
-      as={'button'}
-      onClick={onClick}
-      className={'w-10 items-center gap-1'}
+      as={'button'}
+      type='button'
+      aria-pressed={isActive}
+      onClick={onClick}
+      className={cn(
+        'w-10 items-center gap-1',
+        'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main rounded-md',
+      )}
     >

23-29: 텍스트 오버플로우 가능성 확인

w-10(2.5rem) 폭에 text-nowrap 조합은 한글 긴 카테고리명에서 수평 오버플로우가 발생할 수 있습니다. 시각적 문제 없는지 확인 부탁드립니다. 필요 시 max-w-* + truncate 또는 폭을 소폭 늘리는 방안을 고려해주세요.

packages/ui/src/components/Header/Header.tsx (1)

22-22: 오른쪽 플레이스홀더에 aria-hidden 추가 권장

right 미지정 시 left를 복제해 보정하는 패턴은 레이아웃 유지에 효과적이지만, 스크린 리더에는 중복 콘텐츠가 될 수 있습니다. ui:invisible은 보통 접근성 트리에서 제외되지만, 명시적으로 aria-hidden을 추가하는 것이 안전합니다.

-      {right ?? <div className='ui:invisible'>{left}</div>}
+      {right ?? (
+        <div aria-hidden className='ui:invisible'>
+          {left}
+        </div>
+      )}
apps/web/app/categories/[id]/CategoryDetailPage.tsx (2)

41-44: RowCategories id prop 타입 정합성 확인 필요

RowCategories에서 선택 상태 비교를 category.id(number) 기준으로 한다면, 현재 id(string)를 넘기는 것은 일치 비교에서 문제가 될 수 있습니다. 위에서 제안한 numericId를 넘기는 것으로 통일하는 것을 권장합니다.

가능한 변경안:

-        <RowCategories id={id} categories={categories} setIdFunc={setIdFunc} />
+        <RowCategories id={numericId} categories={categories} setIdFunc={setIdFunc} />

RowCategories prop 타입이 id: number인지 확인 후 적용해 주세요.


27-40: 유효하지 않은 카테고리 id에 대한 UX 개선 제안

라우트로 전달된 initId가 유효하지 않거나 카테고리 목록에 없는 경우, 헤더가 빈 상태로 렌더링될 수 있습니다. 첫 번째 카테고리를 기본 선택으로 설정하거나 에러/로딩 상태를 명시적으로 처리하는 것이 좋습니다.

원하시면 간단한 fallback useEffect 스니펫을 제공하겠습니다.

apps/web/app/_mocks/handlers/placeHandlers.ts (1)

12-17: 중복된 랭킹 핸들러를 하나로 합치는 개선 제안

likes/views 두 핸들러가 동일 응답을 반환합니다. 쿼리 파라미터 sort를 파싱하는 단일 핸들러로 단순화할 수 있습니다.

예시:

-  http.get(addBaseUrl(API_PATH.PLACES.BY_RANKING('likes')), () => {
-    return HttpResponse.json(Places)
-  }),
-  http.get(addBaseUrl(API_PATH.PLACES.BY_RANKING('views')), () => {
-    return HttpResponse.json(Places)
-  }),
+  http.get(addBaseUrl('/places/ranking'), ({ request }) => {
+    const url = new URL(request.url)
+    const sort = url.searchParams.get('sort') // 'likes' | 'views'
+    // 필요 시 sort 값에 따라 다른 목데이터 선택 가능
+    return HttpResponse.json(Places)
+  }),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9904682 and d1467df.

📒 Files selected for processing (25)
  • apps/web/app/_apis/queries/place.ts (1 hunks)
  • apps/web/app/_apis/schemas/place.ts (0 hunks)
  • apps/web/app/_apis/services/place.ts (1 hunks)
  • apps/web/app/_components/HeaderBackButton/HeaderBackButton.tsx (1 hunks)
  • apps/web/app/_components/HeaderBackButton/index.tsx (1 hunks)
  • apps/web/app/_components/RankingPlaceList/MostLikedPlaces/index.tsx (0 hunks)
  • apps/web/app/_components/RankingPlaceList/MostLikesPlaces/MostLikesPlaces.tsx (1 hunks)
  • apps/web/app/_components/RankingPlaceList/MostLikesPlaces/index.tsx (1 hunks)
  • apps/web/app/_components/RankingPlaceList/MostViewsPlaces/MostViewsPlaces.tsx (1 hunks)
  • apps/web/app/_components/RankingPlaceList/index.tsx (1 hunks)
  • apps/web/app/_constants/path.ts (1 hunks)
  • apps/web/app/_mocks/data/place.ts (1 hunks)
  • apps/web/app/_mocks/handlers/placeHandlers.ts (2 hunks)
  • apps/web/app/_template/template.tsx (1 hunks)
  • apps/web/app/categories/[id]/CategoryDetailPage.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/Places/Places.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/RowCategories/CategoryItem.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/RowCategories/RowCategories.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/RowCategories/index.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/index.tsx (1 hunks)
  • apps/web/app/categories/[id]/page.tsx (1 hunks)
  • apps/web/app/categories/template.tsx (1 hunks)
  • apps/web/app/layout.tsx (1 hunks)
  • apps/web/app/page.tsx (2 hunks)
  • packages/ui/src/components/Header/Header.tsx (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/app/_apis/schemas/place.ts
  • apps/web/app/_components/RankingPlaceList/MostLikedPlaces/index.tsx
🧰 Additional context used
🧬 Code Graph Analysis (19)
apps/web/app/_components/HeaderBackButton/HeaderBackButton.tsx (6)
apps/web/app/_components/HeaderBackButton/index.tsx (1)
  • HeaderBackButton (1-1)
apps/web/app/_components/BottomNavigation/TabItem.tsx (1)
  • TabItemProps (20-42)
packages/ui/src/components/Icon/assets/icons/arrowRight.tsx (1)
  • props (3-24)
apps/web/app/_components/SubTitle/SubTitle.tsx (1)
  • Props (10-17)
packages/ui/src/components/Icon/assets/icons/arrowLeft.tsx (1)
  • props (3-24)
packages/ui/src/components/Icon/assets/icons/header/logo.tsx (1)
  • props (3-49)
apps/web/app/categories/template.tsx (1)
apps/web/app/_template/template.tsx (1)
  • Template (9-24)
apps/web/app/layout.tsx (3)
packages/ui/src/components/Layout/Column/Column.tsx (1)
  • restProps (4-16)
packages/ui/src/components/Layout/Layout.stories.tsx (1)
  • args (58-67)
packages/ui/src/components/Icon/Icon.stories.tsx (1)
  • Column (28-40)
apps/web/app/_components/RankingPlaceList/MostLikesPlaces/index.tsx (3)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (1)
  • Props (12-45)
apps/web/app/categories/[id]/_components/Places/Places.tsx (2)
apps/web/app/_apis/queries/place.ts (1)
  • usePlaceQueries (13-25)
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (1)
  • Props (12-45)
apps/web/app/categories/[id]/page.tsx (5)
apps/web/app/page.tsx (1)
  • Page (17-38)
apps/web/app/HydrationBoundaryPage.tsx (1)
  • HydrationBoundaryPage (29-44)
apps/web/app/_apis/queries/category.ts (2)
  • useCategoryQueries (11-17)
  • CategoryQueryKeys (6-6)
apps/web/app/_apis/queries/place.ts (1)
  • usePlaceQueries (13-25)
apps/web/app/categories/[id]/CategoryDetailPage.tsx (1)
  • CategoryDetailPage (17-47)
apps/web/app/_components/RankingPlaceList/index.tsx (3)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (1)
  • Props (12-45)
apps/web/app/_components/RankingPlaceList/MostViewsPlaces/MostViewsPlaces.tsx (3)
apps/web/app/_apis/queries/place.ts (1)
  • usePlaceQueries (13-25)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/categories/[id]/_components/RowCategories/RowCategories.tsx (3)
apps/web/app/_apis/schemas/category.ts (1)
  • Category (10-10)
apps/web/app/categories/[id]/_components/RowCategories/CategoryItem.tsx (1)
  • CategoryItem (13-37)
packages/ui/src/utils/cn.ts (1)
  • cn (19-21)
apps/web/app/categories/[id]/CategoryDetailPage.tsx (4)
apps/web/app/_apis/queries/category.ts (1)
  • useCategoryQueries (11-17)
apps/web/app/_mocks/data/category.ts (1)
  • category (1-17)
apps/web/app/_components/Categories/CategoryItem.tsx (1)
  • Category (7-23)
apps/web/app/_components/Categories/Categories.tsx (2)
  • category (15-17)
  • data (8-20)
apps/web/app/categories/[id]/_components/RowCategories/CategoryItem.tsx (4)
apps/web/app/_apis/schemas/category.ts (1)
  • Category (10-10)
apps/web/app/_mocks/data/category.ts (1)
  • category (1-17)
packages/ui/src/utils/cn.ts (1)
  • cn (19-21)
apps/web/app/_components/Categories/CategoryItem.tsx (1)
  • Category (7-23)
apps/web/app/_constants/path.ts (2)
apps/web/app/_apis/schemas/place.ts (1)
  • RankingPlaceSort (12-12)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/RankingPlaceList/MostLikesPlaces/MostLikesPlaces.tsx (3)
apps/web/app/_apis/queries/place.ts (1)
  • usePlaceQueries (13-25)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (1)
  • Props (12-45)
apps/web/app/_apis/services/place.ts (4)
apps/web/app/_apis/schemas/place.ts (3)
  • RankingPlaceSort (12-12)
  • BasePlace (14-14)
  • BasePlaceSchema (4-10)
apps/web/app/_constants/path.ts (1)
  • API_PATH (3-9)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/page.tsx (4)
apps/web/app/_apis/queries/place.ts (1)
  • usePlaceQueries (13-25)
apps/web/app/_components/RankingPlaceList/MostLikesPlaces/MostLikesPlaces.tsx (1)
  • MostLikesPlaces (7-13)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_apis/queries/place.ts (4)
apps/web/app/_apis/schemas/place.ts (1)
  • RankingPlaceSort (12-12)
apps/web/app/_apis/services/place.ts (2)
  • getPlacesByRanking (9-14)
  • getPlacesByCategory (16-19)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_apis/queries/category.ts (1)
  • CategoryQueryKeys (6-6)
apps/web/app/_mocks/handlers/placeHandlers.ts (5)
apps/web/app/_constants/path.ts (1)
  • API_PATH (3-9)
apps/web/app/categories/[id]/_components/Places/Places.tsx (1)
  • Places (5-19)
apps/web/app/_mocks/data/place.ts (1)
  • Places (1-32)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (1)
  • Props (13-28)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
apps/web/app/_mocks/data/place.ts (2)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/_components/RankingPlaceList/MostLikedPlaces/MostLikedPlaces.tsx (1)
  • useSuspenseQuery (7-13)
packages/ui/src/components/Header/Header.tsx (3)
packages/ui/src/utils/cn.ts (1)
  • cn (19-21)
packages/ui/src/components/Divider/Divider.tsx (1)
  • className (3-5)
packages/ui/src/components/Layout/JustifyBetween/JustifyBetween.tsx (1)
  • restProps (4-21)
🔇 Additional comments (15)
apps/web/app/layout.tsx (1)

35-36: w-[450px] → w-full 전환 좋습니다. 모바일/협소 뷰포트 대응성 향상

max-w를 유지하면서 가용 폭을 채우는 방향으로의 변경이 적절합니다. 상위 컨테이너가 justify-center이므로 큰 화면에서도 450px로 안정적으로 중앙 정렬됩니다.

apps/web/app/_template/template.tsx (1)

2-3: 모션 라이브러리 선택 확인

  • apps/web/app/_template/template.tsx (2행): import { motion } from 'motion/react'
  • apps/web/package.json: "motion": "^12.23.12" 설치, "framer-motion" 미설치

프로젝트에 Motion One(motion/react)이 설치되어 있으므로 현재 import가 의도된 것으로 보입니다.
Motion One의 exit, transition.type='tween' 등 API는 framer-motion과 차이가 있을 수 있으니 애니메이션이 예상대로 작동하는지 검증해 주세요.
만약 framer-motion 사용이 목적이라면 패키지를 설치하고 import를 아래처럼 변경해 주시기 바랍니다.

-import { motion } from 'motion/react'
+import { motion } from 'framer-motion'
apps/web/app/_components/RankingPlaceList/MostViewsPlaces/MostViewsPlaces.tsx (1)

8-8: byRanking 전환 LGTM

쿼리 키/서비스 레이어 리팩터와 정합성이 맞습니다. Suspense 기반 데이터 흐름도 그대로 유지됩니다.

apps/web/app/categories/[id]/_components/RowCategories/index.tsx (1)

1-1: RowCategories 명명된 내보내기 일관성 확인 완료

  • 코드베이스에서 import RowCategories from '…/RowCategories' 형태의 default import 사용이 없습니다.
  • 구현 파일에도 export default RowCategories가 존재하지 않습니다.

배럴 파일의 named export 구성은 적절하므로 추가 조치가 필요 없습니다.

apps/web/app/_components/RankingPlaceList/MostLikesPlaces/index.tsx (1)

1-1: 배럴(export) 정리 및 잔존 참조 없음 확인 완료

MostLikedPlaces에 대한 코드 참조나 파일/폴더가 전혀 발견되지 않아 리네이밍 후 잔존 참조가 없습니다. 배럴 구조가 올바르게 반영되었음을 확인했습니다. LGTM!

apps/web/app/_components/HeaderBackButton/index.tsx (1)

1-1: 배럴(export) 추가 적절

컴포넌트 공개 표면적을 디렉터리 단위로 통일한 점 좋습니다.

apps/web/app/categories/[id]/page.tsx (2)

12-14: SSR 프리패치 구성 적절

카테고리 목록과 선택된 카테고리의 장소 목록을 서버에서 prefetch하여 HydrationBoundary로 전달하는 흐름이 깔끔합니다. 캐싱 키(PlaceQueryKeys.byCategory(id))와 일치하는 사용이 보장되므로 서스펜스 경계에서도 안정적으로 동작할 것입니다.


10-17: CategoryDetailPage에 'use client' 지시자가 이미 존재합니다
apps/web/app/categories/[id]/CategoryDetailPage.tsx 파일 최상단에 이미 'use client' 디렉티브가 선언되어 있어 클라이언트 훅 사용 시 런타임 에러 발생 우려가 없습니다. 별도 조치가 필요 없습니다.

apps/web/app/_components/RankingPlaceList/MostLikesPlaces/MostLikesPlaces.tsx (1)

7-8: 이름 변경 및 쿼리 마이그레이션 적절

MostLikesPlaces로의 이름 정리와 usePlaceQueries.byRanking('likes') 전환이 전체 리팩터 방향(PLACES 네임스페이스, byRanking 키)과 일관적입니다. 컴포넌트 내부 로직도 간결합니다.

apps/web/app/page.tsx (3)

12-14: 컴포넌트 이름 변경 반영 OK

MostLikedPlacesMostLikesPlaces로의 변경이 배럴 익스포트와 일치합니다. 임포트 경로 및 사용처 모두 정합적입니다.


22-23: 랭킹 프리패치 쿼리 키 전환 적절

rankingListbyRanking 전환이 쿼리 키/서비스 리팩터와 맞물려 있습니다. 초기 렌더에서 서스펜스 미발생을 기대할 수 있습니다.


31-31: 사용처 변경도 일관적

<MostLikesPlaces />로의 교체가 상단 임포트 및 프리패치와 일관되며 UI·데이터 흐름에 문제 없어 보입니다.

apps/web/app/_apis/services/place.ts (1)

9-14: 랭킹 조회 서비스 함수 구성 적절합니다

Zod로 응답을 즉시 파싱해 타입 안정성을 확보한 점 좋습니다. React Query와의 궁합도 문제 없어 보입니다.

packages/ui/src/components/Header/Header.tsx (1)

14-19: className 확장 지원 좋습니다

기본 클래스와 병합해 오버라이드 가능한 형태로 설계한 점 좋습니다. cn('defaults', className) 순서도 적절합니다.

apps/web/app/_apis/queries/place.ts (1)

7-11: Query Key 재구성 LGTM

byRanking / byCategory 키 구조 명확하고, all → ['place'] 네임스페이스도 일관적입니다.

Comment on lines 1 to 19
import axiosInstance from '@/_lib/axiosInstance'
import { API_PATH } from '@/_constants/path'
import {
type RankingPlace,
type BasePlace,
type RankingPlaceSort,
RankingPlaceSchema,
BasePlaceSchema,
} from '../schemas/place'

export const getRankingPlaces = async (
export const getPlacesByRanking = async (
sort: RankingPlaceSort,
): Promise<RankingPlace[]> => {
const { data } = await axiosInstance.get(API_PATH.RANKING(sort))
return RankingPlaceSchema.array().parse(data)
): Promise<BasePlace[]> => {
const { data } = await axiosInstance.get(API_PATH.PLACES.BY_RANKING(sort))
return BasePlaceSchema.array().parse(data)
}

export const getPlacesByCategory = async (id: string): Promise<BasePlace[]> => {
const { data } = await axiosInstance.get(API_PATH.PLACES.BY_CATEGORY(id))
return BasePlaceSchema.array().parse(data)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

레거시 심볼 사용 여부 점검 제안: getRankingPlaces/rankingList 잔존 참조 확인

리네이밍이 광범위합니다. 빌드 타임에 놓친 잔존 참조가 없는지 확인 부탁드립니다.


🏁 Script executed:

#!/bin/bash
# 리네이밍 전 심볼/키 사용 흔적 탐색 스크립트
set -euo pipefail

echo "Searching for old service function name: getRankingPlaces"
rg -nP --glob '!**/node_modules/**' '\bgetRankingPlaces\b' -C2 || true

echo
echo "Searching for old query accessor: rankingList("
rg -nP --glob '!**/node_modules/**' '\brankingList\s*\(' -C3 || true

echo
echo "Searching for old API path namespace: API_PATH.RANKING"
rg -nP --glob '!**/node_modules/**' '\bAPI_PATH\.RANKING\b' -C2 || true

Length of output: 1126


HydrationBoundaryPage.tsx에서 legacy 심볼(rankingList) 잔존 사용 확인

  • apps/web/app/HydrationBoundaryPage.tsx:22
    usePlaceQueries.rankingList('likes') → 신규 쿼리 메서드명으로 변경 필요
  • getRankingPlacesAPI_PATH.RANKING 참조는 검색되지 않음

Comment on lines +18 to 20
http.get(addBaseUrl(API_PATH.PLACES.BY_CATEGORY('1')), () => {
return HttpResponse.json(Places)
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

BY_CATEGORY 핸들러가 categoryId=1에만 반응함 → 다른 카테고리 요청 실패

현재 핸들러가 ?categoryId=1에만 매칭되어, 1 이외의 카테고리 선택 시 404/미응답이 발생합니다. 쿼리 파라미터를 동적으로 파싱하도록 수정해야 개발/스토리북/테스트 환경에서 정상 동작합니다.

아래처럼 /places 경로로 매칭하고 categoryId를 파싱하여 응답을 생성하는 것을 제안합니다(간단히 필터링도 포함).

-  http.get(addBaseUrl(API_PATH.PLACES.BY_CATEGORY('1')), () => {
-    return HttpResponse.json(Places)
-  }),
+  http.get(addBaseUrl('/places'), ({ request }) => {
+    const url = new URL(request.url)
+    const categoryId = url.searchParams.get('categoryId')
+    // 간단한 필터링: 해당 카테고리를 포함하는 place만 반환
+    const filtered =
+      categoryId == null
+        ? Places
+        : Places.filter((p) =>
+            p.categories?.some((c) => String(c.id) === String(categoryId)),
+          )
+    return HttpResponse.json(filtered)
+  }),

참고: MSW의 경로 매칭은 쿼리 문자열 플레이스홀더를 지원하지 않아, 위와 같이 경로만 고정하고 쿼리를 직접 파싱하는 방식이 가장 견고합니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
http.get(addBaseUrl(API_PATH.PLACES.BY_CATEGORY('1')), () => {
return HttpResponse.json(Places)
}),
http.get(addBaseUrl('/places'), ({ request }) => {
const url = new URL(request.url)
const categoryId = url.searchParams.get('categoryId')
// 간단한 필터링: 해당 카테고리를 포함하는 place만 반환
const filtered =
categoryId == null
? Places
: Places.filter((p) =>
p.categories?.some((c) => String(c.id) === String(categoryId)),
)
return HttpResponse.json(filtered)
}),
🤖 Prompt for AI Agents
In apps/web/app/_mocks/handlers/placeHandlers.ts around lines 18-20, the current
handler matches only requests with categoryId=1; change it to match the /places
path (no query placeholder), read req.url.searchParams.get('categoryId'), parse
it (e.g., to number), filter the Places array by categoryId when present and
return HttpResponse.json(filteredPlaces); if categoryId is absent return the
full list (or empty per spec), and ensure the handler still supports other query
combinations and returns a proper 200 JSON response.

Comment on lines +23 to +25
const setIdFunc = (id: string) => {
setId(id)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

RowCategories가 number를 콜백으로 전달하는 경우 대비: setIdFunc 시그니처 완화

RowCategories 내부에서 category.id(number)를 바로 넘길 가능성이 높습니다. 현재 시그니처가 string으로 고정되어 있어 타입/런타임 불일치 위험이 있습니다. union으로 받아 안전하게 문자열로 변환하세요.

-  const setIdFunc = (id: string) => {
-    setId(id)
-  }
+  const setIdFunc = (nextId: string | number) => {
+    setId(String(nextId))
+  }

RowCategories의 setIdFunc 타입 정의가 (id: string | number) => void로 허용되는지 확인 부탁드립니다. 필요 시 해당 컴포넌트에도 동일한 시그니처 반영이 필요합니다.


추가 검증을 위해 아래 스크립트를 실행하여 CategoryDetailPage.tsx에서 RowCategories 사용 위치와 RowCategories 컴포넌트 정의(Props 시그니처)를 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 1. CategoryDetailPage.tsx에서 RowCategories 사용 위치 및 전달된 setIdFunc 확인
rg -nC3 "RowCategories" --glob "*.tsx" "apps/web/app/categories/[id]/CategoryDetailPage.tsx"

# 2. RowCategories 컴포넌트 정의 및 Props 시그니처 검색
rg -nC3 "RowCategories" --glob "*.tsx"

Length of output: 2981


setIdFunc 시그니처 완화 및 안전한 문자열 변환 적용

RowCategories가 number 타입의 id를 넘길 수 있으므로, CategoryDetailPage와 RowCategories 컴포넌트 양쪽에서 setIdFunc 시그니처를 string | number로 완화하고 내부에서 String()으로 변환해 주세요.

• apps/web/app/categories/[id]/CategoryDetailPage.tsx (기존 23–25번 라인)

-  const setIdFunc = (id: string) => {
-    setId(id)
-  }
+  const setIdFunc = (nextId: string | number) => {
+    setId(String(nextId))
+  }

• apps/web/app/categories/[id]/_components/RowCategories/RowCategories.tsx (Props 정의)

-  setIdFunc: (id: string) => void
+  setIdFunc: (id: string | number) => void

위 수정 후 RowCategories 호출부(<CategoryDetailPage /> 안)에는 별도 변경 없이 안전하게 동작합니다.

🤖 Prompt for AI Agents
In apps/web/app/categories/[id]/CategoryDetailPage.tsx around lines 23–25, the
setIdFunc currently only accepts a string; relax its signature to accept string
| number and convert the incoming value to a string with String(id) before
calling setId. Also update the props definition in
apps/web/app/categories/[id]/_components/RowCategories/RowCategories.tsx to
expect setIdFunc: (id: string | number) => void so both components accept
numbers from RowCategories; keep the call site in CategoryDetailPage unchanged
because the internal String() conversion makes it safe.

Comment on lines +1 to +2
import Template from '@/_template/template'
export default Template
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Client 컴포넌트 재수출 파일에 'use client' 누락 — Next App Router에서 컴파일 에러 위험

Client 컴포넌트(@/_template/template)를 Server 파일(categories/template.tsx)에서 그대로 기본 내보내기(re-export)하면, Next가 "use client" 지시자 누락으로 에러를 낼 수 있습니다. 이 파일 자체를 Client 컴포넌트로 표시해 주세요.

아래처럼 상단에 'use client'를 추가하면 해결됩니다.

+'use client'
 import Template from '@/_template/template'
 export default Template

또는 명시적 래퍼를 만드는 방법도 있습니다(참고):

'use client'
import TemplateImpl from '@/_template/template'
export default function Template({ children }: { children: React.ReactNode }) {
  return <TemplateImpl>{children}</TemplateImpl>
}
🤖 Prompt for AI Agents
In apps/web/app/categories/template.tsx lines 1-2, this server-file re-exports a
client component (@/_template/template) without the 'use client' directive which
can cause Next App Router compile errors; fix by marking this file as a client
component: add a single line 'use client' at the very top of
apps/web/app/categories/template.tsx before any imports, then keep the existing
import/export, or alternatively replace the re-export with an explicit client
wrapper component that imports the implementation and returns it (ensuring the
'use client' directive remains at the top).

@leeleeleeleejun leeleeleeleejun merged commit 524e6bb into develop Aug 18, 2025
1 check was pending
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/web/app/_constants/path.ts (1)

6-6: BY_CATEGORY: URL 인코딩 적용 및 number 수용 제안

쿼리 파라미터는 인코딩이 안전합니다. 또한 카테고리 id가 number로 다뤄질 가능성이 있어 string | number 수용이 사용성을 높입니다.

아래처럼 수정을 권장합니다:

-    BY_CATEGORY: (id: string) => `/places?categoryId=${id}`,
+    BY_CATEGORY: (id: string | number) =>
+      `/places?categoryId=${encodeURIComponent(String(id))}`,

대안: URLSearchParams로 일관된 쿼리 문자열 생성

-    BY_CATEGORY: (id: string) => `/places?categoryId=${id}`,
+    BY_CATEGORY: (id: string | number) => {
+      const params = new URLSearchParams({ categoryId: String(id) })
+      return `/places?${params.toString()}`
+    },
🧹 Nitpick comments (1)
apps/web/app/_constants/path.ts (1)

7-7: BY_RANKING: 일관성 차원에서 인코딩 고려 (선택사항)

현재 RankingPlaceSort'likes' | 'views'로 제한되어 있어 기능상 문제는 없지만, 추후 확장성을 고려해 인코딩을 맞춰두면 좋습니다.

-    BY_RANKING: (sort: RankingPlaceSort) => `/places/ranking?sort=${sort}`,
+    BY_RANKING: (sort: RankingPlaceSort) =>
+      `/places/ranking?sort=${encodeURIComponent(sort)}`,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1467df and 4b96f5b.

📒 Files selected for processing (4)
  • apps/web/app/HydrationBoundaryPage.tsx (1 hunks)
  • apps/web/app/_constants/path.ts (1 hunks)
  • apps/web/app/categories/[id]/CategoryDetailPage.tsx (1 hunks)
  • apps/web/app/categories/[id]/_components/Places/index.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/web/app/HydrationBoundaryPage.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/categories/[id]/CategoryDetailPage.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/app/_constants/path.ts (6)
apps/web/app/_apis/schemas/place.ts (1)
  • RankingPlaceSort (12-12)
apps/web/app/_apis/services/place.ts (1)
  • sort (9-14)
apps/web/app/_apis/queries/place.ts (3)
  • getRankingPlaces (15-15)
  • sort (12-16)
  • sort (7-8)
apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
  • Props (13-28)
  • place (18-24)
apps/web/app/page.tsx (1)
  • Page (17-38)
apps/web/app/_components/RankingPlaceList/MostViewsPlaces/MostViewsPlaces.tsx (1)
  • useSuspenseQuery (7-11)
🔇 Additional comments (2)
apps/web/app/categories/[id]/_components/Places/index.tsx (1)

1-1: Places.tsx에서 네임드 export 확인됨: 리익스포트 문제 없음
export const Places가 명시적으로 선언되어 있어 export { Places } from './Places'가 정상 동작합니다. 추가 조치 불필요합니다.

apps/web/app/_constants/path.ts (1)

5-8: 잔여 네임스페이스 사용처 없음 확인됨

스크립트 실행 결과, 레거시 API_PATH.RANKING, /places/?categoryId=(불필요한 슬래시), rankingList 훅 사용 흔적이 모두 없는 것으로 확인되었습니다. 추가 조치 필요 없습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 카테고리 상세페이지 화면 UI 구현

2 participants