Conversation
…tag-clicked-effects-FE-96 [fix] 소개페이지 a태그 클릭 시 파란색 전환효과 및 밑줄 표시 제거
- Description -> ClubInfoItem - InfoList -> ClubInfoSection
input width를 100%에서 calc(100% - 32px)로 조정하여 input과 버튼 사이에 적절한 간격을 확보하고 레이아웃 깨짐을 방지함
- 검색창 유연하게 늘어나도록
- timeout 변수를 useEffect 스코프에서 선언하도록 변경 - 컴포넌트 언마운트 시 clearTimeout 정상 동작 보장
- shouldLoad 삭제
…e-FE-97 [refactor] 활동사진 지연로딩 제거
…e-FE-100 [feature] 소개페이지 임시 이미지로 대체 및 메뉴바 구현
…ning-FE-104 [fix] styled-components unknown prop warning 제거
…-101 [feature] 활동사진 확대 모달 구현 및 PhotoList 구조 리팩토링
✅ Deploy Preview for moadong ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
|
Warning Rate limit exceeded@oesnuj has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 54 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (5)
Walkthrough이 변경사항은 프론트엔드에서 사진 리스트 및 모달 기능을 대대적으로 리팩토링하고, 소개 페이지(IntroducePage) 및 모바일 메뉴 드로어를 도입합니다. 스타일드 컴포넌트의 props 네이밍을 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App
participant Header
participant useMobileMenu
participant MobileMenuDrawer
participant Router
participant IntroducePage
User->>Header: 모바일 메뉴 버튼 클릭
Header->>useMobileMenu: openMenu()
useMobileMenu-->>Header: isMenuOpen = true
Header->>MobileMenuDrawer: isOpen=true 렌더
User->>MobileMenuDrawer: Introduce 클릭
MobileMenuDrawer->>Header: handleIntroduceClick()
Header->>Router: /introduce로 이동
Router->>IntroducePage: IntroducePage 렌더
sequenceDiagram
participant User
participant ClubDetailPage
participant PhotoList
participant PhotoCardList
participant PhotoModal
participant usePhotoModal
participant usePhotoNavigation
ClubDetailPage->>PhotoList: clubName, feeds 전달
PhotoList->>PhotoCardList: photoUrls, imageErrors 등 전달
User->>PhotoCardList: 사진 클릭
PhotoCardList->>usePhotoModal: open(index)
usePhotoModal-->>PhotoModal: isOpen=true, index 전달
User->>PhotoModal: 좌/우 버튼 또는 썸네일 클릭
PhotoModal->>useModalNavigation: handlePrev/handleNext/setIndex
useModalNavigation-->>PhotoModal: index 변경
Possibly related PRs
Suggested reviewers
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (2)
frontend/src/hooks/PhotoList/usePhotoNavigation.ts (2)
4-21:⚠️ Potential issue타입 정의와 파라미터 사이의 불일치를 수정해주세요.
타입 정의에는
translateX속성이 포함되어 있지만, 실제 매개변수 목록에는 없습니다. 이로 인해 타입 불일치가 발생하고 있습니다.export const usePhotoNavigation = ({ currentIndex, setCurrentIndex, photosLength, cardWidth, containerWidth, setTranslateX, isMobile, + translateX, }: { currentIndex: number; setCurrentIndex: React.Dispatch<React.SetStateAction<number>>; photosLength: number; cardWidth: number; containerWidth: number; translateX: number; setTranslateX: React.Dispatch<React.SetStateAction<number>>; isMobile: boolean; }) => {
29-31: 🛠️ Refactor suggestionuseEffect 의존성 배열을 완성해주세요.
현재 useEffect 내부에서
setTranslateX와calculateTranslateX함수를 사용하고 있지만, 의존성 배열에는 포함되어 있지 않습니다. React 훅 규칙에 따라 이 값들도 의존성 배열에 포함해야 합니다.useEffect(() => { setTranslateX(calculateTranslateX(currentIndex)); - }, [currentIndex, containerWidth, cardWidth, photosLength]); + }, [currentIndex, containerWidth, cardWidth, photosLength, setTranslateX, calculateTranslateX]);
🧹 Nitpick comments (13)
frontend/src/pages/ClubDetailPage/components/InfoBox/InfoBox.tsx (1)
26-33:infoData반복 생성 최적화 제안
현재 컴포넌트가 렌더될 때마다infoData배열을 새로 생성하고 있습니다.clubDetail값이 변경되지 않을 때 불필요한 재연산을 피하기 위해useMemo로 캐싱을 권장합니다.- const infoData: ClubInfoSectionWithRef[] = [ + const infoData = React.useMemo<ClubInfoSectionWithRef[]>(() => [ { title: '모집정보', descriptions: [ { label: '모집기간', value: clubDetail.recruitmentPeriod }, { label: '모집대상', value: clubDetail.recruitmentTarget }, ], refIndex: INFOTABS_SCROLL_INDEX.INTRODUCE_INFO_TAB, }, { title: '동아리정보', descriptions: [ { label: '회장이름', value: clubDetail.presidentName }, { label: '전화번호', value: clubDetail.presidentPhoneNumber }, ], refIndex: INFOTABS_SCROLL_INDEX.CLUB_INFO_TAB, }, - ], [clubDetail]); + ], [clubDetail]);frontend/public/index.html (1)
42-47: 폰트 로딩 최적화 제안
Pretendard와 Google Fonts 링크를 추가한 것은 적절하지만, 웹폰트 로딩 성능을 개선하기 위해rel="preconnect"또는rel="preload"를 함께 고려해보세요.+ <link rel="preconnect" href="https://cdn.jsdelivr.net" /> + <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" /> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Krona+One&display=swap" />frontend/src/pages/IntroducePage/IntroducePage.tsx (1)
17-22: 이미지 로딩 최적화를 위한 제안큰 이미지 로딩 시 사용자 경험을 더욱 개선할 수 있습니다.
<Styled.IntroduceImage src={IntroduceImage} alt='소개 이미지' style={{ display: loading ? 'none' : 'block' }} onLoad={() => setLoading(false)} + loading="lazy" + decoding="async" />frontend/src/services/header/useMobileMenu.ts (1)
19-19: 이벤트 추적 메시지에 대한 제안이벤트 추적 메시지를 더 표준화된 형식으로 작성하면 좋겠습니다.
- trackEvent('Mobile Menubar delete Button Clicked'); + trackEvent('mobile_menu.close_button_clicked');frontend/src/pages/IntroducePage/IntroducePage.styles.ts (1)
17-21: 이미지 스타일 개선 제안이미지가 모바일에서 더 잘 표시되도록 몇 가지 속성을 추가할 수 있습니다.
export const IntroduceImage = styled.img` width: 100vw; height: auto; margin-top: 62px; + max-width: 100%; + object-fit: contain; + + @media (max-width: 500px) { + margin-top: 52px; + } `;frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.tsx (1)
52-96: 접근성과 사용성을 고려한 UI 구현모달 UI가 사용자 경험과 접근성을 고려하여 잘 구현되었습니다. 특히 다음 사항이 인상적입니다:
- 클릭 이벤트 전파 방지(
stopPropagation)- 접근성 라벨(
aria-label) 적용- 섬네일과 현재 이미지 상태 표시
- 조건부 렌더링을 통한 최적화
조금 더 개선할 수 있는 부분:
- 이미지 로드 실패 시 대체 텍스트나 폴백 UI를 제공하면 더 좋을 것 같습니다:
- <Styled.Image src={urls[currentIndex]} alt='활동 사진' /> + <Styled.Image + src={urls[currentIndex]} + alt='활동 사진' + onError={(e) => { + e.currentTarget.src = '/path/to/fallback-image.jpg'; + e.currentTarget.alt = '이미지를 불러올 수 없습니다'; + }} + />frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoList.styles.ts (1)
43-47: 변환 애니메이션 최적화를 위해will-change선언을 추가해 보세요
transform속성이 지속적으로 변경되는 요소에will-change: transform;을 선언하면 브라우저가 GPU 레이어를 미리 생성해 렌더링을 최적화할 수 있습니다. 모바일 기기에서 빠르게 스와이프할 때 프레임 드롭을 줄이는 데 도움이 됩니다.transition: transform 0.3s ease; + will-change: transform;frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoCardList/PhotoCardList.tsx (1)
20-23: React key로 배열 인덱스를 사용하는 것은 재정렬 시 버그를 유발할 수 있습니다
사진 배열이 동적으로 변경되면 동일 인덱스의 다른 URL 이 동일 key 를 갖게 되어 불필요한 DOM 재사용이 발생합니다. URL 이 고유하다면 URL 기반 key 를 사용하거나, 그렇지 않다면uuid등 명확히 고유한 값을 생성해 주세요.- <Styled.PhotoCard key={index} onClick={() => onImageClick(index)}> + <Styled.PhotoCard key={`${url}-${index}`} onClick={() => onImageClick(index)}>frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoList.tsx (1)
67-76: 네비게이션 버튼에aria-label을 추가해 스크린 리더 지원을 개선하세요
img의alt만으로는 버튼 자체의 의미가 노출되지 않아, 보조기기가 “button” 의 역할을 인지하기 어렵습니다.- <Styled.NavigationButton direction='left' onClick={handlePrev}> + <Styled.NavigationButton + direction='left' + aria-label='이전 사진' + onClick={handlePrev}>
right버튼도 동일하게 적용해 주세요.frontend/src/hooks/PhotoList/usePhotoNavigation.ts (1)
46-49: 스크롤 제한 로직이 모바일 환경에 맞게 개선되었습니다.모바일과 데스크톱 환경에서 서로 다른 스크롤 제한을 적용하는 로직이 추가되었습니다. 이제 모바일에서는 마지막 사진까지 스크롤 가능하고, 데스크톱에서는 마지막에서 두 번째 사진까지만 스크롤 가능합니다. 이 방식은 사용자 경험을 향상시키지만, 주석을 추가하여 이러한 결정의 이유를 설명하면 유지보수가 더 쉬워질 것입니다.
const canScrollLeft = currentIndex > 0 && photosLength > 1; +// 모바일에서는 마지막 사진까지, 데스크톱에서는 마지막 두 장을 남겨두고 스크롤을 제한합니다. const canScrollRight = isMobile ? currentIndex < photosLength - 1 : currentIndex < photosLength - 2;frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.styles.ts (3)
121-165: Styled Components의 트랜스파일 최적화를 위해 prop 이름에 '$' 접두사를 사용하세요.최신 styled-components 관례에 따르면, DOM에 전달되지 않아야 하는 props 이름 앞에 '$' 접두사를 붙여야 합니다. 이는 불필요한 HTML 속성 경고를 방지하고 트랜스파일 최적화에 도움이 됩니다.
-export const NavButton = styled.button<{ position: 'left' | 'right' }>` +export const NavButton = styled.button<{ $position: 'left' | 'right' }>` position: absolute; top: 50%; transform: translateY(-50%); - ${({ position }) => (position === 'left' ? 'left: 16px;' : 'right: 16px;')} + ${({ $position }) => ($position === 'left' ? 'left: 16px;' : 'right: 16px;')} width: 46px; height: 46px; border-radius: 50%; background: rgba(255, 255, 255, 0.9); border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; z-index: 2; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); transition: all 0.2s; user-select: none; outline: none; -webkit-tap-highlight-color: transparent; img { width: 28px; height: 28px; user-select: none; -webkit-user-drag: none; pointer-events: none; } &:hover { background: rgba(255, 255, 255, 1); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } @media (max-width: 600px) { - ${({ position }) => (position === 'left' ? 'left: 8px;' : 'right: 8px;')} + ${({ $position }) => ($position === 'left' ? 'left: 8px;' : 'right: 8px;')} width: 38px; height: 38px; img { width: 22px; height: 22px; } } `;위와 같은 방식으로
Thumbnail컴포넌트의isActiveprop도$isActive로 변경해야 합니다.
210-239: Styled Components의 트랜스파일 최적화를 위해 prop 이름에 '$' 접두사를 사용하세요.최신 styled-components 관례에 따라
isActiveprop 앞에 '$' 접두사를 붙여야 합니다.-export const Thumbnail = styled.button<{ isActive: boolean }>` - border: 2px solid ${({ isActive }) => (isActive ? '#ff5414' : 'transparent')}; +export const Thumbnail = styled.button<{ $isActive: boolean }>` + border: 2px solid ${({ $isActive }) => ($isActive ? '#ff5414' : 'transparent')}; border-radius: 6px; padding: 0; background: none; cursor: pointer; width: 44px; height: 44px; flex-shrink: 0; overflow: hidden; transition: all 0.2s; &:hover { - border-color: ${({ isActive }) => (isActive ? '#ff5414' : '#ddd')}; + border-color: ${({ $isActive }) => ($isActive ? '#ff5414' : '#ddd')}; }
27-44: 색상 상수나 테마 시스템을 사용하여 일관성을 유지하세요.현재 코드에서는 색상 값(#ff5414, #ddd, rgba(0, 0, 0, 0.2) 등)이 여러 곳에 하드코딩되어 있습니다. 이런 값들을 상수로 정의하거나 테마 시스템을 사용하면 일관성을 유지하고 나중에 테마 변경이 필요할 때 수정이 용이해집니다.
파일 상단에 색상 상수를 정의하고 이를 참조하는 방식을 추천합니다:
import styled from 'styled-components'; +// 색상 상수 +const COLORS = { + primary: '#ff5414', + white: '#fff', + black: '#000', + lightGray: '#ddd', + shadowLight: 'rgba(0, 0, 0, 0.1)', + shadowMedium: 'rgba(0, 0, 0, 0.2)', + overlay: 'rgba(0, 0, 0, 0.7)', + buttonBackground: 'rgba(255, 255, 255, 0.9)', +}; // 이후 스타일 코드에서 COLORS 객체 참조그리고 각 스타일에서 하드코딩된 값 대신 상수를 사용하세요. 예:
- background: #fff; + background: ${COLORS.white};Also applies to: 76-80, 105-119, 210-239
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
-
frontend/src/assets/images/introduce/Introduce.pngis excluded by!**/*.png -
frontend/src/assets/images/introduce/delete.pngis excluded by!**/*.png
📒 Files selected for processing (42)
-
frontend/.prettierrc(1 hunks) -
frontend/public/index.html(1 hunks) -
frontend/src/App.tsx(2 hunks) -
frontend/src/components/ClubLogo/ClubLogo.tsx(2 hunks) -
frontend/src/components/ClubStateBox/ClubStateBox.tsx(3 hunks) -
frontend/src/components/common/Header/Header.styles.ts(3 hunks) -
frontend/src/components/common/Header/Header.tsx(4 hunks) -
frontend/src/components/common/LazyImage/LazyImage.test.tsx(0 hunks) -
frontend/src/components/common/LazyImage/LazyImage.tsx(1 hunks) -
frontend/src/components/common/SearchBox/SearchBox.styles.ts(2 hunks) -
frontend/src/components/common/SearchBox/SearchBox.tsx(2 hunks) -
frontend/src/components/common/Spinner/Spinner.tsx(1 hunks) -
frontend/src/constants/photoLayout.ts(1 hunks) -
frontend/src/hooks/PhotoList/usePhotoModal.ts(1 hunks) -
frontend/src/hooks/PhotoList/usePhotoNavigation.ts(3 hunks) -
frontend/src/hooks/PhotoList/useResponsiveLayout.ts(1 hunks) -
frontend/src/hooks/PhotoModal/useModalNavigation.ts(1 hunks) -
frontend/src/pages/AdminPage/components/ImagePreview/ImagePreview.tsx(1 hunks) -
frontend/src/pages/AdminPage/components/ImageUpload/ImageUpload.tsx(2 hunks) -
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx(1 hunks) -
frontend/src/pages/ClubDetailPage/components/ClubProfile/ClubProfile.tsx(1 hunks) -
frontend/src/pages/ClubDetailPage/components/InfoBox/InfoBox.tsx(1 hunks) -
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoCardList/PhotoCardList.tsx(1 hunks) -
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoList.styles.ts(2 hunks) -
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoList.tsx(1 hunks) -
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.styles.ts(1 hunks) -
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.tsx(1 hunks) -
frontend/src/pages/IntroducePage/IntroducePage.styles.ts(1 hunks) -
frontend/src/pages/IntroducePage/IntroducePage.tsx(1 hunks) -
frontend/src/pages/MainPage/components/Banner/Banner.styles.ts(2 hunks) -
frontend/src/pages/MainPage/components/Banner/Banner.tsx(1 hunks) -
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts(1 hunks) -
frontend/src/pages/MainPage/components/ClubCard/ClubCard.styles.ts(2 hunks) -
frontend/src/pages/MainPage/components/ClubCard/ClubCard.tsx(1 hunks) -
frontend/src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.styles.ts(2 hunks) -
frontend/src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.tsx(1 hunks) -
frontend/src/services/header/useHeaderService.ts(1 hunks) -
frontend/src/services/header/useMobileMenu.ts(1 hunks) -
frontend/src/styles/Global.styles.ts(0 hunks) -
frontend/src/types/Info.ts(0 hunks) -
frontend/src/types/club.ts(1 hunks) -
frontend/src/utils/debounce.ts(1 hunks)
💤 Files with no reviewable changes (3)
- frontend/src/styles/Global.styles.ts
- frontend/src/components/common/LazyImage/LazyImage.test.tsx
- frontend/src/types/Info.ts
🧰 Additional context used
🧬 Code Graph Analysis (5)
frontend/src/pages/IntroducePage/IntroducePage.tsx (1)
frontend/src/pages/IntroducePage/IntroducePage.styles.ts (1)
IntroduceImage(17-21)
frontend/src/hooks/PhotoList/useResponsiveLayout.ts (1)
frontend/src/constants/photoLayout.ts (2)
MOBILE_CARD_WIDTH(6-6)DESKTOP_CARD_WIDTH(5-5)
frontend/src/pages/ClubDetailPage/components/InfoBox/InfoBox.tsx (2)
frontend/src/types/club.ts (1)
ClubDetail(12-21)frontend/src/pages/ClubDetailPage/components/InfoBox/InfoBox.styles.ts (1)
InfoBox(17-31)
frontend/src/pages/IntroducePage/IntroducePage.styles.ts (2)
frontend/src/components/common/Header/Header.styles.ts (1)
HeaderStyles(3-18)frontend/src/components/common/Footer/Footer.styles.ts (1)
FooterContainer(3-7)
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.tsx (1)
frontend/src/hooks/PhotoModal/useModalNavigation.ts (1)
useModalNavigation(3-17)
🔇 Additional comments (81)
frontend/.prettierrc (1)
13-14: Prettier 설정 변경 시 버전 호환성 확인 필요
singleAttributePerLine옵션은 Prettier v3 이상에서만 동작합니다.
프로젝트에서 사용 중인 Prettier 버전을 검토하고, v3 미만인 경우package.json의 devDependencies를 업데이트하거나 해당 옵션을 제거하세요.frontend/src/pages/AdminPage/components/ImagePreview/ImagePreview.tsx (1)
4-7: 인터페이스 정의 이동 완료ImagePreviewProps 인터페이스를 공유 타입 파일에서 컴포넌트 내부로 이동하여 결합도를 낮추었습니다. 각 컴포넌트가 자신의 props 타입을 직접 관리하도록 하는 좋은 리팩토링입니다.
frontend/src/types/club.ts (2)
12-14: ClubDetail 인터페이스 속성 재정렬description 속성을 인터페이스 최상단으로 이동하였습니다. 중요 속성을 상단에 배치하는 것은 가독성에 도움이 됩니다.
17-18: recruitmentForm 위치 조정presidentPhoneNumber 다음에 recruitmentForm 속성을 배치하여 관련 속성끼리 그룹화했습니다.
frontend/src/pages/AdminPage/components/ImageUpload/ImageUpload.tsx (2)
7-11: 인터페이스 정의 이동 완료ImageUploadProps 인터페이스를 공유 타입 파일에서 컴포넌트 내부로 이동하여 결합도를 낮추었습니다. 각 컴포넌트가 자신의 props 타입을 직접 관리하도록 하는 좋은 리팩토링입니다.
30-33: 들여쓰기 수정파일 크기 체크 조건문 내부의 들여쓰기를 수정하여 코드 가독성을 개선했습니다.
frontend/src/pages/ClubDetailPage/components/InfoBox/InfoBox.tsx (3)
6-9:ClubInfoItem인터페이스 정의 검토
label과value를 문자열로 고정해clubDetail의 각 필드 타입(string)과 일치시킨 점이 적절합니다. 추가 프로퍼티가 필요할 경우 로컬에서 확장하기에도 유연합니다.
11-14:ClubInfoSection인터페이스 검토
섹션의title과descriptions구조를 명시적으로 선언해 가독성을 높였습니다. 재사용 가능성도 확보되어 있어 적절한 설계로 보입니다.
21-23:ClubInfoSectionWithRef에refIndex추가
기존 공유 타입 대신 컴포넌트 내부에refIndex를 가진 로컬 타입으로 선언해 의도를 명확히 한 점이 좋습니다.frontend/src/pages/MainPage/components/Banner/Banner.tsx (1)
113-113: 스타일드 컴포넌트 prop 네이밍 일관성 확보
isAnimating을$isAnimating으로 변경하여 DOM에 불필요한 prop 전달을 방지한 점이 적절합니다. 전반적인 styled-components 네이밍 컨벤션과 잘 맞습니다.frontend/src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.tsx (1)
33-34: 스타일드 컴포넌트 Prop 네이밍 일관화 승인
isActive를$isActive로 변경하여 styled-components 전용 prop임을 명확히 하고, DOM으로 전달되는 prop을 줄인 점이 아주 좋습니다.frontend/src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.styles.ts (1)
13-18: Boolean Prop Prefix 적용 적절
isActive→$isActive로 변경해 불필요한 DOM prop 전달을 방지하고, 조건부 스타일링 로직도 의도대로 유지된 것이 확인되었습니다.Also applies to: 22-24, 40-43
frontend/src/services/header/useHeaderService.ts (1)
22-25: 소개 페이지 네비게이션 기능이 추가되었습니다.소개 페이지로 이동하는 네비게이션 기능이
goIntroducePage함수에 추가되었습니다. 이전에는 이벤트 추적만 있었지만, 이제navigate('/introduce')기능이 포함되어 더 완전한 구현이 되었습니다.frontend/src/pages/ClubDetailPage/components/ClubProfile/ClubProfile.tsx (1)
24-24: 스타일드 컴포넌트 props 네이밍 규칙이 적용되었습니다.
variant와imageSrcprops가$variant와$imageSrc로 변경되었습니다. 이는 스타일드 컴포넌트의 트랜지언트 props 네이밍 규칙을 따르는 것으로, DOM 속성과 스타일링 props를 구분하는 좋은 관행입니다.frontend/src/components/common/SearchBox/SearchBox.tsx (1)
42-42: 스타일드 컴포넌트 props 네이밍 규칙이 적용되었습니다.
isFocusedprops를$isFocused로 변경하여 스타일드 컴포넌트의 트랜지언트 props 네이밍 규칙을 일관되게 적용했습니다. 이는 불필요한 HTML 속성 전달을 방지하고 코드 일관성을 높이는 좋은 변경입니다.Also applies to: 56-57
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts (1)
14-14: 모바일 뷰에서 카테고리 버튼 위치 조정이 적용되었습니다.모바일 뷰(max-width: 500px)에서
CategoryButtonContainer의 상단 위치가 46px에서 56px로 조정되었습니다. 이는 헤더 높이 및 다른 컴포넌트의 수직 간격 변경과 함께 모바일 레이아웃의 일관성을 향상시킵니다.frontend/src/pages/MainPage/components/ClubCard/ClubCard.tsx (2)
31-32: styled-components 트랜지언트 프롭스 적용 개선스타일드 컴포넌트에 전달되는 prop에 $ 접두사를 적용하여 DOM 요소로 전달되는 것을 방지했습니다. 이는 React 콘솔 경고를 줄이고 불필요한 HTML 속성을 방지하는 좋은 방법입니다.
36-36: ClubLogo 컴포넌트에 트랜지언트 프롭스 적용ClubLogo 컴포넌트에도 일관되게 $ 접두사를 적용했습니다. 이는 프로젝트 전체의 스타일드 컴포넌트 프롭스 네이밍 컨벤션과 일치합니다.
frontend/src/App.tsx (3)
9-10: 상대 경로에서 절대 경로로 임포트 개선 및 IntroducePage 추가임포트 경로를 상대 경로에서 절대 경로(@/ 별칭 사용)로 변경하여 코드 가독성과 유지보수성을 향상시켰습니다. 또한 새로운 IntroducePage 컴포넌트를 추가하였습니다.
12-13: 절대 경로 임포트 사용 개선RecruitEditTab과 AccountEditTab 컴포넌트도 일관되게 절대 경로로 임포트하도록 변경했습니다. 이는 코드베이스의 일관성을 높입니다.
45-45: IntroducePage를 위한 새 라우트 추가소개 페이지를 위한 새로운 라우트가 적절하게 추가되었습니다. 이 변경은 AI 요약에서 언급된 IntroducePage 기능 추가와 일치합니다.
frontend/src/pages/MainPage/components/Banner/Banner.styles.ts (2)
17-17: 모바일 뷰 마진 조정모바일 화면(500px 이하)에서 마진 상단 값을 42px에서 56px로 늘려 UI 레이아웃을 개선했습니다. 이는 모바일 환경에서 사용자 경험을 향상시킬 것입니다.
46-53: 스타일드 컴포넌트 프롭스 네이밍 컨벤션 적용SlideWrapper 컴포넌트에서 isAnimating을 $isAnimating으로 변경하여 트랜지언트 프롭스 패턴을 적용했습니다. 이것은 styled-components에서 권장하는 방식으로, DOM에 불필요한 속성이 전달되는 것을 방지합니다.
frontend/src/components/ClubStateBox/ClubStateBox.tsx (3)
25-25: 스타일드 컴포넌트 트랜지언트 프롭스 타입 정의 개선StyledBox 컴포넌트의 타입 정의에서 bgColor와 textColor를 $bgColor와 $textColor로 변경하여 트랜지언트 프롭스 패턴을 적용했습니다. 이는 타입스크립트와의 일관성을 유지하는 좋은 방법입니다.
34-35: 스타일 속성에서 트랜지언트 프롭스 참조 수정템플릿 리터럴 내에서 프롭 참조를 $bgColor와 $textColor로 변경하여 타입 정의와 일치시켰습니다. 이는 코드의 일관성을 유지하는 데 중요합니다.
52-52: 컴포넌트 사용 시 트랜지언트 프롭스 전달 방식 개선StyledBox 컴포넌트에 프롭을 전달할 때 $bgColor와 $textColor로 이름을 변경하여 일관된 네이밍 컨벤션을 유지했습니다. 이는 프로젝트 전체에서 적용된 $ 접두사 패턴과 일치합니다.
frontend/src/pages/MainPage/components/ClubCard/ClubCard.styles.ts (4)
4-5: 스타일드 컴포넌트의 props 네이밍 관례를 따른 변경이 잘 적용되었습니다.styled-components v6부터 권장되는 트랜지언트 props($로 시작) 네이밍 관례를 적용하셨군요. 이는 DOM 요소로 불필요한 props가 전달되는 것을 방지하여 React 경고 메시지를 없애는 좋은 접근입니다.
14-15: state prop 네이밍 변경이 일관되게 적용되었습니다.조건부 스타일링에 사용되는 $state 변경이 올바르게 적용되었습니다.
22-22: isClicked prop 네이밍 변경이 정확히 적용되었습니다.transform 속성에서 사용되는 $isClicked 변경이 올바르게 적용되었습니다.
26-27: hover 상태의 조건부 스타일링에도 prop 네이밍 변경이 잘 적용되었습니다.hover 상태에서 사용되는 $isClicked 변경도 일관되게 적용되었습니다.
frontend/src/pages/IntroducePage/IntroducePage.tsx (3)
1-7: 필요한 모듈과 컴포넌트가 적절히 임포트되었습니다.React, styled components, 공통 컴포넌트 및 이미지 자산이 명확하게 임포트되었습니다.
8-10: 이미지 로딩 상태 관리가 잘 구현되었습니다.useState를 사용한 loading 상태 관리가 적절합니다.
11-26: 페이지 구조와 로딩 처리가 잘 구현되었습니다.Header, 이미지, Footer 구조가 명확하며, 로딩 중에는 Spinner를 표시하고 이미지는 숨기는 방식이 좋습니다. 이미지 로드 완료 시 loading 상태 변경 처리도 잘 되어 있습니다.
frontend/src/services/header/useMobileMenu.ts (4)
4-6: 인터페이스 정의가 명확합니다.MobileMenuProp 인터페이스가 간결하게 정의되어 있습니다.
8-15: 모바일 메뉴 상태 관리와 토글 함수가 적절히 구현되었습니다.상태 관리와 handleMenuClick 콜백 실행이 잘 구현되어 있습니다.
17-20: 메뉴를 닫는 함수의 최적화가 잘 되어 있습니다.useCallback을 사용하여 함수 참조 안정성을 확보하고, Mixpanel 이벤트 추적이 적절히 구현되었습니다.
22-28: 키보드 접근성이 고려된 좋은 구현입니다.Escape 키 이벤트 처리와 이벤트 리스너 정리가 잘 구현되어 있습니다. 접근성 측면에서 훌륭합니다.
frontend/src/pages/IntroducePage/IntroducePage.styles.ts (3)
5-11: 헤더 스타일 확장이 적절히 구현되었습니다.기존 HeaderStyles를 확장하고 모바일 환경에 맞게 스타일을 오버라이드한 부분이 좋습니다.
13-15: 푸터 스타일 확장이 적절합니다.FooterContainer를 확장하여 margin-top을 조정한 부분이 좋습니다.
17-21: 이미지 스타일 정의가 적절합니다.전체 뷰포트 너비에 맞는 이미지 스타일과 헤더 높이를 고려한 margin-top 설정이 좋습니다.
frontend/src/components/ClubLogo/ClubLogo.tsx (5)
6-9: props 이름에 $ 접두사 추가 변경 적절합니다.스타일드 컴포넌트에서 사용되는 props에 $ 접두사를 추가하여 transient props로 명확하게 표시했습니다. 이는 DOM으로 전달되지 않아야 하는 props를 구분하는 좋은 방법입니다.
22-25: StyledClubLogo 컴포넌트의 props 타입에 $ 접두사 추가 적절합니다.스타일드 컴포넌트의 prop 타입 정의에도 일관되게 $ 접두사를 적용했습니다.
26-34: 템플릿 리터럴 내에서 props 참조 업데이트 적절합니다.CSS 템플릿 리터럴 내에서 props 참조를 새로운 이름($로 시작하는 이름)으로 일관되게 업데이트했습니다.
37-41: 미디어 쿼리 내 props 참조 업데이트 적절합니다.미디어 쿼리 내에서도 props 참조를 새로운 이름으로 일관되게 업데이트했습니다.
45-47: ClubLogo 컴포넌트 업데이트 적절합니다.ClubLogo 컴포넌트의 props와 StyledClubLogo에 전달하는 props 이름을 일관되게 업데이트했습니다.
frontend/src/components/common/Header/Header.tsx (6)
6-6: useMobileMenu 훅 추가 적절합니다.모바일 메뉴 기능을 위한 커스텀 훅을 추가하였습니다.
11-11: 삭제 아이콘 추가 적절합니다.모바일 메뉴 드로어를 닫기 위한 삭제 아이콘을 추가하였습니다.
24-29: MobileMenuProp 인터페이스 정의 적절합니다.모바일 메뉴 드로어 컴포넌트를 위한 props 인터페이스를 명확하게 정의했습니다.
31-58: MobileMenuDrawer 컴포넌트 구현 적절합니다.모바일 메뉴 드로어 컴포넌트를 추가하여 모바일 사용자 경험을 개선했습니다. 드로어에는 홈 버튼, 닫기 버튼, 그리고 "모아동 소개" 메뉴 항목이 포함되어 있습니다.
115-117: useMobileMenu 훅 사용 적절합니다.모바일 메뉴 상태 관리를 위해 useMobileMenu 훅을 사용하고 초기화했습니다.
120-131: 모바일 헤더와 드로어 연결 적절합니다.모바일 헤더와 새로 추가된 드로어 컴포넌트를 연결하여 일관된 사용자 경험을 제공합니다.
frontend/src/components/common/SearchBox/SearchBox.styles.ts (10)
3-3: SearchBoxContainer에 $isFocused 접두사 추가 적절합니다.스타일드 컴포넌트에서 사용되는 props에 $ 접두사를 추가하여 transient props로 명확하게 표시했습니다.
6-9: SearchBoxContainer 스타일 개선 적절합니다.수평 중앙 정렬을 추가하고 너비와 패딩을 조정하여 검색 상자의 레이아웃을 개선했습니다.
15-17: 모바일 반응형 스타일 조정 적절합니다.500px 이하 화면에서의 너비, 높이, 패딩을 조정하여 모바일 환경에서의 사용성을 개선했습니다.
20-21: $isFocused prop 참조 업데이트 적절합니다.스타일 속성에서 사용되는 prop 참조를 새로운 이름으로 일관되게 업데이트했습니다.
26-27: 입력 필드 레이아웃 개선 적절합니다.flex 레이아웃을 사용하고 계산된 너비를 적용하여 입력 필드의 레이아웃을 개선했습니다.
46-48: 추가 미디어 쿼리 브레이크포인트 적절합니다.500px 이하 화면에서의 폰트 크기를 조정하여 가독성을 개선했습니다.
51-52: SearchButton에 $isFocused 접두사 추가 및 flex-shrink 설정 적절합니다.스타일드 컴포넌트의 prop 이름을 일관되게 업데이트하고, 버튼이 축소되지 않도록 flex-shrink 속성을 설정했습니다.
58-59: 버튼 크기 명시적 설정 적절합니다.버튼의 너비와 높이를 명시적으로 설정하여 일관된 크기를 유지합니다.
61-63: 이미지 크기 조정 적절합니다.이미지가 버튼 영역을 완전히 채우도록 너비와 높이를 설정했습니다.
67-71: 모바일 환경에서의 버튼 크기 및 필터 조정 적절합니다.모바일 환경에서 버튼 크기를 조정하고, $isFocused prop을 사용하여 포커스 상태에 따른 필터 효과를 적용했습니다.
frontend/src/components/common/Header/Header.styles.ts (10)
74-80: IntroduceButtonStyles에 명시적 스타일 추가 적절합니다.링크의 기본 스타일을 재정의하기 위해 color와 text-decoration 속성을 명시적으로 설정했습니다. 방문한 링크(visited)에도 동일한 스타일을 적용하여 일관된 모양을 유지합니다.
97-97: MobileHeaderContainer 높이 증가 적절합니다.모바일 헤더의 높이를 56px로 증가시켜 터치 영역을 확대하고 가독성을 개선했습니다.
113-114: MobileMainIcon 크기 조정 적절합니다.모바일 메인 아이콘과 이미지 크기를 더 크게 조정하여 가독성과 사용자 경험을 개선했습니다.
Also applies to: 120-120
127-128: MobileMenu 크기 조정 적절합니다.모바일 메뉴 버튼과 이미지 크기를 더 크게 조정하여 터치 영역을 확대하고 사용자 경험을 개선했습니다.
Also applies to: 134-134
140-154: DrawerContainer 스타일 구현 적절합니다.모바일 메뉴 드로어를 위한 컨테이너 스타일을 추가했습니다. isOpen prop에 따라 드로어의 위치와 가시성이 전환되는 애니메이션 효과가 적용되었습니다.
156-162: DrawerWrapper 스타일 구현 적절합니다.드로어 내부 요소를 감싸는 래퍼 스타일을 추가했습니다. flex 레이아웃을 사용하여 내용을 세로로 배치하고 중앙 정렬했습니다.
164-170: DrawerHeader 스타일 구현 적절합니다.드로어 헤더 영역의 스타일을 추가했습니다. flex 레이아웃을 사용하여 로고와 닫기 버튼을 수평으로 배치하고, 간격을 적절히 조정했습니다.
172-177: DrawerMainIcon 스타일 구현 적절합니다.드로어 내 메인 로고 이미지의 스타일을 추가했습니다. 적절한 크기와 커서 스타일을 설정했습니다.
179-183: DrawerDeleteIcon 스타일 구현 적절합니다.드로어 닫기 아이콘의 스타일을 추가했습니다. 적절한 크기와 flex-shrink 속성을 설정했습니다.
185-193: MenubarIntroduceBox 스타일 구현 적절합니다."모아동 소개" 메뉴 항목의 스타일을 추가했습니다. 인라인 flex 레이아웃, 패딩, 둥근 모서리, 배경색 등을 적용하여 시각적으로 구분되는 버튼 형태로 구현했습니다.
frontend/src/constants/photoLayout.ts (1)
1-6: 명확한 레이아웃 상수 정의, 좋은 패턴입니다!상수를 중앙화하여 관리하는 방식은 유지보수에 매우 유리합니다. 카드 간격과 디바이스별 컨텐츠 너비를 명확하게 분리하고, 이를 바탕으로 전체 카드 너비를 계산하는 접근법이 좋습니다.
한 가지 제안: 상수의 의미와 사용처에 대한 간단한 JSDoc 주석을 추가하면 다른 개발자들이 이 상수들을 더 쉽게 이해하고 활용할 수 있을 것입니다.
frontend/src/components/common/LazyImage/LazyImage.tsx (1)
9-34: LazyImage 컴포넌트 로직 단순화, 좋은 개선입니다!복잡한 지연 로딩 로직을 단순화하고 고정된 지연 시간(100ms)을 사용하는 방식으로 변경한 것은 코드 가독성과 유지보수성을 크게 향상시켰습니다. 특히 observer가 교차점을 감지한 후 즉시 disconnect하고, cleanup 함수에서 timeout을 정리하는 부분은 메모리 누수를 방지하는 좋은 예시입니다.
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (1)
64-68: PhotoList에 clubName 프롭 추가, 적절한 통합입니다!PhotoList 컴포넌트에 clubName 프롭을 추가함으로써 모달에서 동아리 이름을 표시할 수 있게 되었습니다. 이는 사용자 경험 측면에서 유용한 정보를 제공하는 좋은 개선사항입니다.
frontend/src/utils/debounce.ts (1)
1-11: 타입 안전성이 향상된 debounce 함수 리팩토링, 잘 했습니다!
any타입에서unknown으로 변경한 것은 타입 안전성을 높이는 올바른 접근법입니다. 화살표 함수 형태와 명확한 반환 타입 표기는 현대적인 TypeScript 패턴을 잘 따르고 있습니다. 특히 타입 매개변수와 Parameters 유틸리티 타입을 활용하여 함수의 타입 안전성을 보장한 점이 인상적입니다.frontend/src/hooks/PhotoList/usePhotoModal.ts (1)
1-14: 깔끔하고 재사용 가능한 모달 훅 구현 👍모달 상태 관리를 위한 커스텀 훅을 효과적으로 구현했습니다. 상태와 관련 함수를 잘 캡슐화하여 컴포넌트에서 쉽게 활용할 수 있도록 했습니다.
frontend/src/hooks/PhotoModal/useModalNavigation.ts (1)
3-17: 좋은 관심사 분리와 최적화 구현 👏모달 내 네비게이션 로직을 별도 훅으로 분리한 접근이 좋습니다.
useCallback을 통한 핸들러 함수 메모이제이션과 순환(circular) 인덱싱 로직이 잘 구현되어 있습니다.frontend/src/hooks/PhotoList/useResponsiveLayout.ts (1)
1-41: 반응형 레이아웃 관리를 위한 유용한 커스텀 훅창 크기와 컨테이너 요소의 너비에 따라 반응형 레이아웃을 관리하는 훅을 잘 구현했습니다. 핵심 이슈만 수정하면 매우 유용하게 사용될 것 같습니다.
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.tsx (3)
6-15: 인터페이스 설계가 명확합니다
PhotoModalProps인터페이스가 필요한 속성들을 명확하게 정의하고 있습니다. 사진 관련 속성을 중첩 객체로 그룹화한 것도 좋은 접근입니다.
26-33: 모달 열릴 때 스크롤 방지 처리 잘 되었습니다모달이 열릴 때 body 스크롤을 방지하고, 닫힐 때 복원하는 로직이 적절하게 구현되었습니다. 클린업 함수에서 원래 상태로 복원하는 것도 좋습니다.
35-48: 키보드 이벤트 처리가 잘 구현되었습니다키보드 탐색을 위한 이벤트 핸들러가 적절히 구현되어 있습니다.
useCallback을 사용한 메모이제이션과 의존성 배열 관리도 잘 되어있습니다.
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoList.styles.ts
Show resolved
Hide resolved
frontend/src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.styles.ts
Show resolved
Hide resolved
- role="status"와 aria-label 추가로 스크린 리더 지원 - height prop 추가로 유연한 높이 조절 가능 - SpinnerProps 인터페이스 추가로 타입 안정성 확보
…ty-FE-110 [feature] Spinner 컴포넌트 접근성 개선 및 높이 prop 추가
[fix] PhotoList 리팩토링 및 잠재적 버그 대응 작업

#️⃣연관된 이슈
📝작업 내용
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
New Features
개선 및 변경
버그 수정
기타