[Fix/#83] 검색화면 렌더링 오류 해결 및 클릭 시 용어 상세 연결#89
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough추천 용어 카드 컴포넌트에 클라이언트 라우팅 기능을 추가하고, 스켈레톤 로딩 UI를 도입하며, 로딩 상태를 관리하도록 수정했습니다. 추천 용어 데이터 모델에 slug 필드를 추가하여 라우팅에 활용합니다. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
src/lib/recommendations.ts (1)
41-47: slug 필드에 대한 데이터 보장/방어 로직을 한 번 점검하는 게 좋습니다.
RecommendedTerm에slug: string을 필수로 추가하고, 두 분기에서 모두t.slug를 그대로 노출하는 방향 자체는 PR 목적(카드 클릭 → 상세 페이지 이동)에 잘 맞습니다. 다만getTermsByCategory가 반환하는 항목에slug가 항상 채워져 있지 않다면/terms/${slug}가undefined나 빈 문자열로 끝나는 경로가 생길 수 있습니다.
terms의 타입 정의에서slug가 필수 string으로 이미 보장되는지 한 번 확인해 보시고, 혹시 선택 필드라면t.slug가 falsy인 항목은 필터링하거나 폴백을 두는 식의 방어 로직을 추가하는 것을 권장합니다.Also applies to: 61-69, 78-84
src/components/RecommendedTermCardSkeleton.tsx (1)
1-21: 스켈레톤 구조는 좋고, 접근성 측면에서 선택적 개선 여지가 있습니다.실제 카드 레이아웃과 잘 맞춰진 스켈레톤이라 UI 측면에서는 무난해 보입니다. 다만 이 컴포넌트 자체에는 어떤 역할/aria 정보도 없어서, 상위 섹션에서 별도 로딩 상태 안내를 하지 않는 경우 스크린리더 사용자는 “무언가가 로딩 중”이라는 의미를 파악하기 어렵습니다.
- 이 스켈레톤들을 단순 장식으로 취급한다면
aria-hidden="true"를 주고,- 대신 상위
RecommendedTermsSection쪽에서"추천 용어 로딩 중..."같이 텍스트로 상태를 한 번만 읽어 주는 패턴을 고려해 볼 만합니다.큰 이슈는 아니지만, 나중에 접근성 손볼 때 같이 정리해 두면 좋겠습니다.
src/components/RecommendedTermCard.tsx (1)
1-60: 카드 클릭 네비게이션은 목적에 부합하지만, 시맨틱/접근성 측면에서는 Link/버튼 사용을 권장합니다.
slug를 받아서router.push(/terms/${slug})로 상세 페이지로 보내는 흐름은 이 PR의 요구사항을 잘 만족합니다. 다만 현재는 바깥 컨테이너가 단순<div>+onClick이라 키보드 포커스를 받을 수 없고, 화면 읽기 프로그램에서도 “클릭 가능한 요소”로 인식되기 어렵습니다.가능한 개선 방향은 예를 들어 다음과 같습니다.
-import { useRouter } from "next/navigation"; +import Link from "next/link"; -export default function RecommendedTermCard({ - term, - category, - description, - iconColor, - slug, -}: TermCardProps) { - const router = useRouter(); - const handleClick = () => { - router.push(`/terms/${slug}`); - }; - - return ( - <div - onClick={handleClick} - className="flex w-64 cursor-pointer flex-col items-start justify-start gap-2.5 overflow-hidden rounded-xl bg-black/50 p-5 outline outline-[0.25px] outline-white/25 transition-colors hover:bg-black/70" - > +export default function RecommendedTermCard({ + term, + category, + description, + iconColor, + slug, +}: TermCardProps) { + return ( + <Link + href={`/terms/${slug}`} + className="flex w-64 cursor-pointer flex-col items-start justify-start gap-2.5 overflow-hidden rounded-xl bg-black/50 p-5 outline outline-[0.25px] outline-white/25 transition-colors hover:bg-black/70" + > {/* ...나머지 내용 동일... */} - </div> + </Link> ); }이렇게 하면:
- 기본적으로 키보드 포커스/엔터 키로도 동작하고,
- Next.js의
<Link>프리페치 이점도 같이 얻을 수 있습니다.현재 구현도 동작은 하지만, 이후 접근성/SEO를 고려하면 위와 같이 정리해 두는 것을 추천드립니다.
src/components/search/RecommendedTermsSection.tsx (3)
19-37: userData가 끝까지 null일 수 있는 경우 스켈레톤이 영구 로딩 상태로 남을 수 있습니다.
useEffect안에서!userData이면 그냥return하고 있어서, 로그인 실패/게스트 모드 등으로userData가 최종적으로도null인 시나리오가 있다면isLoading이 계속true로 남고 스켈레톤 3개가 무한히 떠 있게 됩니다.앱 구조상
userData가 항상 곧 초기화되는 것이 보장된다면 그대로 둬도 되지만, 혹시 그렇지 않다면:
userData가 없을 때는 추천 섹션 자체를 렌더링하지 않거나 (if (!userData) return null;),- 혹은
userData없이도category = "all"로getRecommendedTerms를 호출해 게스트용 추천을 보여주는등의 분기 처리를 넣는 쪽이 UX 측면에서 더 안전해 보입니다. 실제
useAuth동작을 한 번 점검해 보시는 걸 추천드립니다.
57-66: 리스트 key로 index 대신term.slug를 사용하는 편이 더 안전합니다.추천 용어 배열은 크게 변동이 없겠지만, 현재
key={index}를 쓰고 있어서 순서 변경/부분 업데이트가 생기면 리렌더링 측면에서 React가 의도치 않게 DOM을 재사용할 수 있습니다. 이 카드에는 고유 식별자인slug가 있으니, 가능하면 이를 key로 쓰는 게 좋습니다.- displayedRecommendedTerms.map((term, index) => ( - <RecommendedTermCard - key={index} + displayedRecommendedTerms.map((term) => ( + <RecommendedTermCard + key={term.slug} term={term.term} category={term.category} description={term.description} iconColor={term.iconColor} slug={term.slug} /> ))지금 당장 큰 문제는 아니지만, 이후 추천 목록이 동적으로 바뀌는 요구사항이 생길 때를 대비해 미리 정리해 두면 좋을 것 같습니다.
48-55: 추천 용어 개수에 따라 ‘더보기/접기’ 버튼 노출 조건을 조정하면 UX가 더 자연스러울 것 같습니다.현재 구현에서는
!isLoading이기만 하면 추천 용어가 0개이거나 최대 3개뿐이어도 더보기/접기 버튼이 항상 노출될 수 있습니다. 이 경우 버튼을 눌러도 UI 변화가 없어서 사용자 입장에서는 헷갈릴 수 있습니다.추천 용어가 3개를 초과할 때만 버튼을 노출하도록 조건을 조금 더 좁혀보는 것을 제안드립니다.
- {!isLoading && ( + {!isLoading && recommendedTerms.length > 3 && ( <div className="flex flex-col items-center justify-center gap-2.5 self-stretch overflow-hidden pt-5"> <button onClick={() => setShowMoreRecommended(!showMoreRecommended)} className="inline-flex items-center justify-center gap-1 text-sm font-bold text-neutral-300 transition-colors hover:text-white" > <ChevronsDownIcon className={`h-4 w-4 transition-transform ${showMoreRecommended ? "rotate-180" : ""}`} width={16} height={16} /> {showMoreRecommended ? "접기" : "더보기"} </button> </div> )}이렇게 하면 실제로 “더 보기”가 가능한 상황에서만 버튼이 나타나 더 직관적인 동작이 됩니다.
Also applies to: 69-83
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/RecommendedTermCard.tsx(3 hunks)src/components/RecommendedTermCardSkeleton.tsx(1 hunks)src/components/search/RecommendedTermsSection.tsx(3 hunks)src/lib/recommendations.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/RecommendedTermCard.tsx (1)
src/components/icons/ic_category_all.tsx (1)
CategoryAllIcon(3-25)
src/components/search/RecommendedTermsSection.tsx (3)
src/lib/recommendations.ts (1)
getRecommendedTerms(52-89)src/components/RecommendedTermCardSkeleton.tsx (1)
RecommendedTermCardSkeleton(1-22)src/components/RecommendedTermCard.tsx (1)
RecommendedTermCard(40-93)
✨ 작업 개요
검색화면 렌더링 오류 해결 및 클릭 시 용어 상세 연결
📌 관련 이슈
✅ 작업 내용
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.