Conversation
Walkthrough가이드 페이지(이미지 캐러셀) 컴포넌트 추가 및 ROUTES에 GUIDE 등록, lazy 로드와 보호 라우트에 GUIDE 경로 추가. 홈 상단 배너에 onClick으로 가이드로 네비게이션 연결하고 BannerCard를 버튼으로 변경. 하단 네비게이션 관련 타입 추가 및 표시 경로에 GUIDE 포함. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant HomeTop as Home TopSection
participant Router
participant Guide as Guide Page
Note over HomeTop: useEffect로 Guide 페이지 동적 import(프리로드)
User->>HomeTop: 배너 클릭
HomeTop->>Router: navigate('/guide')
Router-->>Guide: lazy load & mount
Guide-->>User: 가이드 이미지 캐러셀 렌더링
sequenceDiagram
autonumber
participant BottomNav as BottomNavigation
participant Router
Note over BottomNav: NAV_ITEMS.home.path에 HOME/ GUIDE 포함 가능
BottomNav->>BottomNav: isActive(path) 체크 → pathname이 배열에 포함되면 활성
BottomNav->>Router: handleTabClick(Home) → navigate(ROUTES.HOME)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
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 |
|
MATEBALL-STORYBOOK |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/shared/components/card/banner-card/banner-card.tsx (1)
4-14: className 소실 및 onClick 타입 구체화 필요
- 인터페이스에 className이 남아 있으나 컴포넌트에서 사용되지 않아 스타일 오버라이드가 더 이상 적용되지 않습니다. (호환성 이슈)
- onClick은 React.MouseEventHandler로 명시하면 이벤트 접근이 가능합니다.
적용 diff 예시:
interface CardBannerProps { text: string; subText?: string; className?: string; - onClick?: () => void; + onClick?: React.MouseEventHandler<HTMLButtonElement>; } -const BannerCard = ({ text, subText, onClick }: CardBannerProps) => { +const BannerCard = ({ text, subText, className, onClick }: CardBannerProps) => { return ( - <button type="button" className={cn('relative cursor-pointer text-left')} onClick={onClick}> + <button + type="button" + className={cn('relative cursor-pointer text-left', className)} + onClick={onClick} + >
🧹 Nitpick comments (6)
src/pages/guide/guide.tsx (4)
26-29: A11y: roledescription만으로는 보조기기 인식이 제한됩니다.컨테이너에 명시적 role, 슬라이드에 role을 추가해 접근성을 강화하세요.
- <section + <section className="w-full flex flex-col gap-[2.4rem] overflow-hidden " aria-label="가이드 이미지 캐러셀" + role="region" > ... - <li + <li key={image.id} aria-roledescription="slide" + role="group"Also applies to: 41-44
30-38: 키보드 내비게이션 추가 제안 (좌/우 화살표).키보드만 사용하는 사용자 지원을 위해
tabIndex와onKeyDown을 추가하세요.- <ul + <ul className="flex pt-[3.2rem] transition-transform duration-300 ease-in-out" style={getSlideTransformStyle(currentIndex)} onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onMouseDown={handleMouseDown} aria-roledescription="carousel" aria-live="polite" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'ArrowRight' && currentIndex < guideImages.length - 1) setCurrentIndex(currentIndex + 1); + if (e.key === 'ArrowLeft' && currentIndex > 0) setCurrentIndex(currentIndex - 1); + }} >
48-49: 드래그 방지 및 이미지 로딩 최적화.마우스 드래그 시 이미지가 끌려가는 기본 동작을 막고, 지연 로딩으로 초기 페인트를 최적화하세요.
- <img src={image.src} alt={image.alt} className="h-auto w-full " /> + <img + src={image.src} + alt={image.alt} + className="h-auto w-full " + draggable={false} + loading="lazy" + decoding="async" + />
24-61: useSlide 문맥에서 언마운트 시 document 리스너 누수 가능성 점검.현재 훅은
mousedown시 document에 리스너를 등록하고mouseup에서만 제거합니다. 캐러셀이 드래그 도중 언마운트되면 누수가 생길 수 있습니다. 훅 내부에 cleanup을 추가하는 개선을 고려해 주세요.원하시면
useSlide에useEffectcleanup 패치를 제안해 드리겠습니다.src/shared/components/bottom-navigation/constants/bottom-navigation.ts (1)
38-45: NavItem 타입을 NAV_ITEMS에 즉시 적용정적 타입 체크 강화를 위해 NAV_ITEMS에 NavItem[]을 적용하거나 satisfies를 사용하세요. 타입 선언은 상단으로 이동하는 것을 권장합니다.
적용 diff 예시:
import { ROUTES } from '@routes/routes-config'; +export type NavItem = { + label: string; + path: string | string[]; + icon: { + filled: string; + lined: string; + }; +}; + -export const NAV_ITEMS = [ +export const NAV_ITEMS: NavItem[] = [ { label: '홈', path: [ROUTES.HOME, ROUTES.GUIDE], icon: { filled: 'home-filled', lined: 'home-lined', }, }, ... -]; - -export type NavItem = { - label: string; - path: string | string[]; - icon: { - filled: string; - lined: string; - }; -}; +];대안(TS 4.9+):
export const NAV_ITEMS = [ ... ] satisfies readonly NavItem[];src/shared/components/bottom-navigation/bottom-navigation.tsx (1)
30-38: 배열 경로 클릭 시 첫 경로로 일반화현재는 배열이면 무조건 HOME으로 이동합니다. 첫 요소로 일반화하면 상수 의존 줄고 재사용성이 높습니다.
적용 diff 예시:
- if (Array.isArray(path)) { - // 홈 탭 클릭 시 홈으로 이동 - navigate(ROUTES.HOME); - } else { - navigate(path); - } + const to = Array.isArray(path) ? path[0] : path; + navigate(to);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
src/pages/guide/guide.tsx(1 hunks)src/pages/home/components/top-section.tsx(1 hunks)src/shared/components/bottom-navigation/bottom-navigation.tsx(1 hunks)src/shared/components/bottom-navigation/constants/bottom-navigation.ts(2 hunks)src/shared/components/card/banner-card/banner-card.tsx(1 hunks)src/shared/constants/header.ts(1 hunks)src/shared/routes/lazy.ts(1 hunks)src/shared/routes/protected-routes.tsx(2 hunks)src/shared/routes/routes-config.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-29T18:02:42.616Z
Learnt from: heesunee
PR: MATEBALL/MATEBALL-CLIENT#7
File: src/shared/routes/Router.tsx:4-4
Timestamp: 2025-06-29T18:02:42.616Z
Learning: The Home component file in the MATEBALL-CLIENT project was renamed from Home.tsx to home.tsx, so the correct import path is 'pages/home/home'.
Applied to files:
src/shared/routes/lazy.ts
🧬 Code graph analysis (6)
src/shared/constants/header.ts (1)
src/shared/routes/routes-config.ts (1)
ROUTES(1-23)
src/shared/components/card/banner-card/banner-card.tsx (1)
src/shared/libs/cn.ts (1)
cn(4-6)
src/pages/guide/guide.tsx (3)
src/shared/routes/lazy.ts (1)
Guide(11-11)src/pages/match/hooks/useSlide.ts (1)
useSlide(9-64)src/pages/match/styles/get-slide-transformstyle.ts (1)
getSlideTransformStyle(1-3)
src/shared/components/bottom-navigation/bottom-navigation.tsx (1)
src/shared/routes/routes-config.ts (1)
ROUTES(1-23)
src/shared/routes/protected-routes.tsx (2)
src/shared/routes/routes-config.ts (1)
ROUTES(1-23)src/shared/routes/lazy.ts (1)
Guide(11-11)
src/shared/components/bottom-navigation/constants/bottom-navigation.ts (1)
src/shared/routes/routes-config.ts (1)
ROUTES(1-23)
🔇 Additional comments (12)
src/shared/routes/routes-config.ts (1)
22-22: ROUTES.GUIDE 추가 LGTM.라우팅 상수 일관성 유지 잘 됐습니다. 다른 곳(보텀 내비, 보호 라우트)과도 값이 동일한지 최종 확인만 부탁드립니다.
src/pages/guide/guide.tsx (1)
27-27: Tailwind:flex-col단독 사용으로 레이아웃 깨짐 가능.
flex-col은flex와 함께 써야 동작합니다.- className="w-full flex-col gap-[2.4rem] overflow-hidden " + className="w-full flex flex-col gap-[2.4rem] overflow-hidden "⛔ Skipped due to learnings
Learnt from: heesunee PR: MATEBALL/MATEBALL-CLIENT#102 File: src/shared/components/bottom-sheet/bottom-sheet-indicator.tsx:5-5 Timestamp: 2025-07-10T09:58:36.134Z Learning: MATEBALL-CLIENT 프로젝트의 `src/shared/styles/custom-utilities.css`에서 `.flex-col` 클래스는 이미 `apply flex flex-col;`을 포함하고 있어서 별도로 `flex` 클래스를 추가할 필요가 없습니다. CSS 클래스 관련 제안을 하기 전에 반드시 커스텀 유틸리티 클래스 파일을 먼저 확인해야 합니다.Learnt from: heesunee PR: MATEBALL/MATEBALL-CLIENT#77 File: src/shared/components/card/match-card/components/card-header.tsx:56-56 Timestamp: 2025-07-08T13:43:15.684Z Learning: MATEBALL-CLIENT 프로젝트에서는 `src/shared/styles/custom-utilities.css`에 커스텀 유틸리티 클래스들이 정의되어 있습니다. 특히 `.flex-row` 클래스는 이미 `apply flex flex-row;`를 포함하고 있어서 별도로 `flex` 클래스를 추가할 필요가 없습니다.src/shared/routes/protected-routes.tsx (1)
33-34: Guide를 보호 라우트로 둔 것이 의도인가요?이용 가이드는 비로그인 사용자도 볼 가능성이 높습니다. 공개 라우트로 옮길지 제품 정책 확인 바랍니다.
src/shared/routes/lazy.ts (1)
10-12: Lazy 로딩 추가 LGTM.경로와 파일명 일치하며, 청크 분리에도 문제 없어 보입니다.
src/shared/constants/header.ts (1)
17-23: 보텀 내비 표시 경로에 GUIDE 추가 LGTM.홈 탭 다중 경로 활성화 로직과의 일관성만 최종 확인 부탁드립니다.
src/pages/home/components/top-section.tsx (2)
2-15: 라우트 상수 사용 + preload 실패 핸들링 제안
- 하드코딩된 '/guide' 대신 ROUTES.GUIDE 사용을 권장합니다.
- dynamic import 실패 시 미처리된 rejection 로그가 날 수 있으니 catch로 흡수 또는 로깅을 권장합니다.
[ suggest_optional_refactor ]
적용 diff 예시:
import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; +import { ROUTES } from '@routes/routes-config'; // 가이드 페이지 미리 로드 useEffect(() => { - import('@pages/guide/guide'); + import('@pages/guide/guide').catch(() => { + // ignore preload failures + }); }, []); const handleBannerClick = () => { - navigate('/guide'); + navigate(ROUTES.GUIDE); };
20-24: 배너 클릭 연동 방향성 좋습니다홈 상단 배너 → 가이드 진입 흐름이 자연스럽습니다. 상수화만 반영되면 충분해 보입니다.
src/shared/components/card/banner-card/banner-card.tsx (2)
13-13: button 루트 전환은 접근성 측면에서 적절합니다type="button" 지정으로 폼 상호작용 부작용도 방지됩니다.
15-18: 레이아웃 깨짐 가능성: flex 누락overlay 컨테이너에 flex-col만 있고 flex가 없어 의도한 세로 정렬이 적용되지 않을 수 있습니다.
적용 diff 예시:
- <div className="absolute inset-0 flex-col gap-[0.8rem] py-[2rem] pl-[2.4rem]"> + <div className="absolute inset-0 flex flex-col gap-[0.8rem] py-[2rem] pl-[2.4rem]">⛔ Skipped due to learnings
Learnt from: heesunee PR: MATEBALL/MATEBALL-CLIENT#102 File: src/shared/components/bottom-sheet/bottom-sheet-indicator.tsx:5-5 Timestamp: 2025-07-10T09:58:36.134Z Learning: MATEBALL-CLIENT 프로젝트의 `src/shared/styles/custom-utilities.css`에서 `.flex-col` 클래스는 이미 `apply flex flex-col;`을 포함하고 있어서 별도로 `flex` 클래스를 추가할 필요가 없습니다. CSS 클래스 관련 제안을 하기 전에 반드시 커스텀 유틸리티 클래스 파일을 먼저 확인해야 합니다.Learnt from: heesunee PR: MATEBALL/MATEBALL-CLIENT#77 File: src/shared/components/card/match-card/components/card-header.tsx:56-56 Timestamp: 2025-07-08T13:43:15.684Z Learning: MATEBALL-CLIENT 프로젝트에서는 `src/shared/styles/custom-utilities.css`에 커스텀 유틸리티 클래스들이 정의되어 있습니다. 특히 `.flex-row` 클래스는 이미 `apply flex flex-row;`를 포함하고 있어서 별도로 `flex` 클래스를 추가할 필요가 없습니다.src/shared/components/bottom-navigation/constants/bottom-navigation.ts (1)
6-6: 홈 탭 다중 경로 활성화 설계 적절HOME/Guide 모두에서 홈 탭 활성화를 의도대로 지원합니다.
src/shared/components/bottom-navigation/bottom-navigation.tsx (2)
13-20: 다중 경로 활성화 로직 LGTM배열 경로에서 includes로 활성화 판정하는 접근이 단순하고 명확합니다.
22-28: 정책 일치 확인 완료
현재 코드가 배열 경로(홈 탭) 항상 활성화 및 매칭 미완료 시 다른 탭 비활성화 정책을 정확히 반영하고 있어 추가 수정 불필요합니다.
src/pages/guide/guide.tsx
Outdated
| onTouchEnd={handleTouchEnd} | ||
| onMouseDown={handleMouseDown} | ||
| aria-roledescription="carousel" | ||
| aria-live="polite" |
There was a problem hiding this comment.
aria-roledescription="carousel" 이건 스크린 리더 사용자에게 이 요소가 캐러셀임을 알려준다고 합니당
aria-live="polite" 스크린 리더에게 내용이 변경될 때 알려주는데, 캐러셀에서 슬라이드가 바뀔 때 스크린 리더 사용자에게 알리는 역할을 한다고 해요!
src/shared/components/bottom-navigation/constants/bottom-navigation.ts
Outdated
Show resolved
Hide resolved
7a925e2 to
27c38d8
Compare
Deploying mateball-client with
|
| Latest commit: |
27c38d8
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://937107c2.mateball-client.pages.dev |
| Branch Preview URL: | https://feat--322-guide-page.mateball-client.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/pages/guide/constants/guide-images.ts(1 hunks)src/pages/guide/guide.tsx(1 hunks)src/pages/home/components/top-section.tsx(1 hunks)src/shared/components/bottom-navigation/bottom-navigation.tsx(1 hunks)src/shared/components/bottom-navigation/constants/bottom-navigation.ts(1 hunks)src/shared/components/card/banner-card/banner-card.tsx(1 hunks)src/shared/constants/header.ts(1 hunks)src/shared/routes/lazy.ts(1 hunks)src/shared/routes/protected-routes.tsx(2 hunks)src/shared/routes/routes-config.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- src/shared/constants/header.ts
- src/shared/components/bottom-navigation/bottom-navigation.tsx
- src/shared/components/card/banner-card/banner-card.tsx
- src/shared/components/bottom-navigation/constants/bottom-navigation.ts
- src/shared/routes/protected-routes.tsx
- src/shared/routes/lazy.ts
- src/pages/home/components/top-section.tsx
- src/pages/guide/guide.tsx
🔇 Additional comments (2)
src/shared/routes/routes-config.ts (1)
22-22: GUIDE 라우트 연결 확인 완료
지연 로드, 보호 라우트, 하단 내비게이션, 홈 배너 클릭 등 모든 연결 지점 정상 작동합니다.src/pages/guide/constants/guide-images.ts (1)
10-10: 타입 노출 방식 좋습니다as const + (typeof …)[number] 조합으로 소비 측 타입 안전성이 확보됩니다.
| export const GUIDE_IMAGES = [ | ||
| { id: 1, src: 'images/guide_image_1.webp', alt: '가이드 1' }, | ||
| { id: 2, src: 'images/guide_image_2.webp', alt: '가이드 2' }, | ||
| { id: 3, src: 'images/guide_image_3.webp', alt: '가이드 3' }, | ||
| { id: 4, src: 'images/guide_image_4.webp', alt: '가이드 4' }, | ||
| { id: 5, src: 'images/guide_image_5.webp', alt: '가이드 5' }, | ||
| { id: 6, src: 'images/guide_image_6.webp', alt: '가이드 6' }, | ||
| ] as const; |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
이미지 상수 정의 적절하나 접근성/경로 확인 권장
- alt가 모두 “가이드 N”으로 동일해 스크린 리더 유용성이 낮습니다. 정보 전달용이면 더 구체적으로, 장식용이면 alt를 빈 문자열로 처리하고 컴포넌트에서 aria-hidden 고려를 권장합니다.
- src 경로가 'images/...' 상대 경로입니다. 빌드/배포 환경(Vite/CRA 등)에서 public 경로 기준인지 절대경로('/images/...')가 필요한지 확인해 주세요.
이미지 자산 존재와 로딩 경로를 점검하는 스크립트입니다.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "[1] 이미지 자산 존재 확인"
fd -HI 'guide_image_*.webp' | sed -e 's/^/ /'
echo "[2] 가이드 페이지에서 alt/role 사용 확인"
rg -nC3 -g "src/**" -P "GUIDE_IMAGES|<img|alt=|aria-hidden" src/pages/guide/guide.tsx || true
echo "[3] 빌드 시 public 경로 사용 여부 점검(일반적인 패턴)"
rg -nC2 -g "src/**" -P "/images/guide_image_\\d+\\.webp|new URL\\(" Length of output: 1849
이미지 자산 미존재, 경로 및 접근성 문제 해결 필요
src/pages/guide/constants/guide-images.ts에서 참조하는images/guide_image_*.webp파일이 리포지토리에 없습니다.- 상대경로
images/...는 빌드 환경에서/guide/.../images/...등으로 잘못 해석될 수 있으니 public 기준 절대경로(/images/...)로 변경하거나 빌드 설정에서 경로 해석 방식을 검증하세요. - 현재
alt="가이드 N"이 aria-label(가이드 이미지 N / 6)과 중복되어 스크린리더에서 중복 안내가 발생합니다. 정보 전달용이면 더 구체적 설명, 장식용이면alt=""및aria-hidden적용 바랍니다.
🤖 Prompt for AI Agents
In src/pages/guide/constants/guide-images.ts lines 1-8 the image entries
reference non-existent relative paths and use alt text that duplicates
aria-labels for screen readers; fix by moving/adding the image files into the
public/images folder (or whichever public/static dir your build expects) and
update each src to an absolute public path like /images/guide_image_X.webp, and
resolve accessibility duplication by either providing meaningful descriptive alt
text (e.g., "가이드 이미지 X — [short description]") if the image conveys information,
or marking them as decorative by setting alt="" and adding aria-hidden="true" at
the img usage site; ensure your changes match the app's image-loading
conventions (public paths vs imports) and update any consuming components to use
the new absolute paths and appropriate aria attributes.
#️⃣ Related Issue
Closes #322
💎 PR Point
기존에 만들어져 있는 carousel-indicator과 useslide 사용하여 이용가이드 페이지 구현하였습니다.
📸 Screenshot
Summary by CodeRabbit