Skip to content

[release] v1.0.2#388

Merged
seongwon030 merged 95 commits intomainfrom
develop-fe
May 9, 2025
Merged

[release] v1.0.2#388
seongwon030 merged 95 commits intomainfrom
develop-fe

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented May 9, 2025

#️⃣연관된 이슈

ex) #이슈번호, #이슈번호

📝작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지/동영상 첨부 가능)

중점적으로 리뷰받고 싶은 부분(선택)

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

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

논의하고 싶은 부분(선택)

논의하고 싶은 부분이 있다면 작성해주세요.

🫡 참고사항

Summary by CodeRabbit

  • New Features

    • 클럽 상세 페이지에 사진 모달 기능이 추가되어 사진을 크게 볼 수 있습니다.
    • 소개 페이지가 새로 추가되어 헤더의 "소개" 버튼을 통해 접근할 수 있습니다.
    • 로딩 상태를 보여주는 스피너 컴포넌트가 도입되었습니다.
  • 개선 및 변경

    • 모바일 및 데스크톱 환경에 맞춘 반응형 레이아웃 개선.
    • 사진 리스트, 카드, 버튼 등 주요 컴포넌트의 스타일 및 prop 명명 규칙 일관성 강화.
    • 헤더의 모바일 메뉴가 드로어 방식으로 변경되어 사용성이 향상되었습니다.
    • Pretendard, Krona One 폰트가 외부 스타일시트로 분리되어 글로벌 스타일 import가 제거되었습니다.
  • 버그 수정

    • 이미지 로딩 실패 시 "이미지 준비중.." 안내 문구가 표시됩니다.
  • 기타

    • 일부 타입 및 인터페이스가 내부적으로 정리되고, 코드 구조가 모듈화되었습니다.

seongwon030 and others added 30 commits April 28, 2025 17:11
…tag-clicked-effects-FE-96

[fix] 소개페이지 a태그 클릭 시 파란색 전환효과 및 밑줄 표시 제거
- Description -> ClubInfoItem
- InfoList -> ClubInfoSection
input width를 100%에서 calc(100% - 32px)로 조정하여
input과 버튼 사이에 적절한 간격을 확보하고 레이아웃 깨짐을 방지함
- 검색창 유연하게 늘어나도록
- timeout 변수를 useEffect 스코프에서 선언하도록 변경
- 컴포넌트 언마운트 시 clearTimeout 정상 동작 보장
…e-FE-97

[refactor] 활동사진 지연로딩 제거
@seongwon030 seongwon030 requested a review from oesnuj May 9, 2025 08:00
@seongwon030 seongwon030 self-assigned this May 9, 2025
@seongwon030 seongwon030 added 💻 FE Frontend 📈 release 릴리즈 배포 labels May 9, 2025
@netlify
Copy link

netlify bot commented May 9, 2025

Deploy Preview for moadong ready!

Name Link
🔨 Latest commit 74b7c32
🔍 Latest deploy log https://app.netlify.com/sites/moadong/deploys/681dbd817edce00008142593
😎 Deploy Preview https://deploy-preview-388--moadong.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 35
Accessibility: 87
Best Practices: 92
SEO: 92
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 9, 2025

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 79195c5 and 74b7c32.

📒 Files selected for processing (5)
  • frontend/src/components/common/Spinner/Spinner.tsx (1 hunks)
  • frontend/src/hooks/PhotoList/useResponsiveLayout.ts (1 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/IntroducePage/IntroducePage.tsx (1 hunks)

Walkthrough

이 변경사항은 프론트엔드에서 사진 리스트 및 모달 기능을 대대적으로 리팩토링하고, 소개 페이지(IntroducePage) 및 모바일 메뉴 드로어를 도입합니다. 스타일드 컴포넌트의 props 네이밍을 $로 통일했으며, 각종 타입 및 인터페이스 정의 위치를 조정하였습니다. 또한, 글로벌 폰트 적용 방식을 변경하고, 다양한 UI 컴포넌트와 커스텀 훅을 추가 및 개선하였습니다.

Changes

파일/경로 그룹 변경 요약
.prettierrc, public/index.html, src/styles/Global.styles.ts Prettier 설정 및 글로벌 폰트 import 방식을 @import에서 <link>로 변경.
src/App.tsx, src/pages/IntroducePage/IntroducePage.tsx, src/pages/IntroducePage/IntroducePage.styles.ts, src/components/common/Spinner/Spinner.tsx IntroducePage(소개 페이지) 및 Spinner 컴포넌트 추가, 라우팅 반영.
src/components/common/Header/Header.tsx, src/components/common/Header/Header.styles.ts, src/services/header/useMobileMenu.ts, src/services/header/useHeaderService.ts 모바일 메뉴 드로어 및 관련 커스텀 훅 도입, Introduce 버튼 동작 개선, 스타일 추가.
src/components/ClubLogo/ClubLogo.tsx, src/components/ClubStateBox/ClubStateBox.tsx, src/components/common/SearchBox/SearchBox.tsx, src/components/common/SearchBox/SearchBox.styles.ts, src/pages/MainPage/components/Banner/Banner.tsx, src/pages/MainPage/components/Banner/Banner.styles.ts, src/pages/MainPage/components/ClubCard/ClubCard.tsx, src/pages/MainPage/components/ClubCard/ClubCard.styles.ts, src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.tsx, src/pages/MainPage/components/StatusRadioButton/StatusRadioButton.styles.ts 스타일드 컴포넌트 props 네이밍을 $ 접두사로 통일.
src/pages/ClubDetailPage/ClubDetailPage.tsx, src/pages/ClubDetailPage/components/ClubProfile/ClubProfile.tsx PhotoList에 clubName prop 추가, ClubLogo props 네이밍 변경.
src/pages/ClubDetailPage/components/InfoBox/InfoBox.tsx, src/types/Info.ts, src/types/club.ts Info 관련 타입 외부 import 제거 및 파일 내 정의, 불필요 타입/인터페이스 삭제.
src/pages/ClubDetailPage/components/PhotoList/PhotoList.tsx, src/pages/ClubDetailPage/components/PhotoList/PhotoList.styles.ts, src/pages/ClubDetailPage/components/PhotoList/PhotoCardList/PhotoCardList.tsx, src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.tsx, src/pages/ClubDetailPage/components/PhotoList/PhotoModal/PhotoModal.styles.ts PhotoList 리팩토링: 카드 렌더링 분리, 모달 기능 및 스타일 추가, 커스텀 훅 도입.
src/hooks/PhotoList/usePhotoModal.ts, src/hooks/PhotoList/usePhotoNavigation.ts, src/hooks/PhotoList/useResponsiveLayout.ts, src/hooks/PhotoModal/useModalNavigation.ts 사진 모달 및 리스트용 커스텀 훅 신설 및 개선, 네비게이션 로직 분리.
src/constants/photoLayout.ts 사진 카드 레이아웃 상수 신설.
src/components/common/LazyImage/LazyImage.tsx, src/components/common/LazyImage/LazyImage.test.tsx LazyImage 컴포넌트 단순화 및 관련 테스트 케이스 제거.
src/pages/AdminPage/components/ImagePreview/ImagePreview.tsx, src/pages/AdminPage/components/ImageUpload/ImageUpload.tsx 이미지 관련 props 인터페이스 외부 import 제거, 파일 내 정의로 변경.
src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts 모바일 환경에서 카테고리 버튼 위치 조정.
src/utils/debounce.ts debounce 함수 선언 방식 및 타입 개선.

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 렌더
Loading
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 변경
Loading

Possibly related PRs

  • #366: IntroducePage 컴포넌트 및 라우팅, 모바일 메뉴 드로어 도입 등 본 PR과 직접적으로 동일한 코드 수준의 도입 및 리팩토링이 포함되어 있음.
  • #357: ImageUploadProps, ImagePreviewProps 타입을 외부에서 import하지 않고 각 파일 내에서 직접 정의하도록 리팩토링, 본 PR의 타입 구조 변경과 직접적으로 연관됨.
  • #377: 스타일드 컴포넌트의 props 네이밍을 $로 통일하는 동일한 리팩토링이 여러 컴포넌트에 적용됨.

Suggested reviewers

  • oesnuj
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 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.
    • Generate unit testing code for this file.
    • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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
Member

@oesnuj oesnuj left a comment

Choose a reason for hiding this comment

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

1.0.2 릴리즈 🚀
수고했어용

Copy link
Contributor

@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: 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 suggestion

useEffect 의존성 배열을 완성해주세요.

현재 useEffect 내부에서 setTranslateXcalculateTranslateX 함수를 사용하고 있지만, 의존성 배열에는 포함되어 있지 않습니다. 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) 적용
  • 섬네일과 현재 이미지 상태 표시
  • 조건부 렌더링을 통한 최적화

조금 더 개선할 수 있는 부분:

  1. 이미지 로드 실패 시 대체 텍스트나 폴백 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 을 추가해 스크린 리더 지원을 개선하세요
imgalt 만으로는 버튼 자체의 의미가 노출되지 않아, 보조기기가 “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 컴포넌트의 isActive prop도 $isActive로 변경해야 합니다.


210-239: Styled Components의 트랜스파일 최적화를 위해 prop 이름에 '$' 접두사를 사용하세요.

최신 styled-components 관례에 따라 isActive prop 앞에 '$' 접두사를 붙여야 합니다.

-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

📥 Commits

Reviewing files that changed from the base of the PR and between e2f9645 and 79195c5.

⛔ Files ignored due to path filters (2)
  • frontend/src/assets/images/introduce/Introduce.png is excluded by !**/*.png
  • frontend/src/assets/images/introduce/delete.png is 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 인터페이스 정의 검토
labelvalue를 문자열로 고정해 clubDetail의 각 필드 타입(string)과 일치시킨 점이 적절합니다. 추가 프로퍼티가 필요할 경우 로컬에서 확장하기에도 유연합니다.


11-14: ClubInfoSection 인터페이스 검토
섹션의 titledescriptions 구조를 명시적으로 선언해 가독성을 높였습니다. 재사용 가능성도 확보되어 있어 적절한 설계로 보입니다.


21-23: ClubInfoSectionWithRefrefIndex 추가
기존 공유 타입 대신 컴포넌트 내부에 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 네이밍 규칙이 적용되었습니다.

variantimageSrc props가 $variant$imageSrc로 변경되었습니다. 이는 스타일드 컴포넌트의 트랜지언트 props 네이밍 규칙을 따르는 것으로, DOM 속성과 스타일링 props를 구분하는 좋은 관행입니다.

frontend/src/components/common/SearchBox/SearchBox.tsx (1)

42-42: 스타일드 컴포넌트 props 네이밍 규칙이 적용되었습니다.

isFocused props를 $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을 사용한 메모이제이션과 의존성 배열 관리도 잘 되어있습니다.

oesnuj and others added 6 commits May 9, 2025 17:15
- role="status"와 aria-label 추가로 스크린 리더 지원
- height prop 추가로 유연한 높이 조절 가능
- SpinnerProps 인터페이스 추가로 타입 안정성 확보
…ty-FE-110

[feature] Spinner 컴포넌트 접근성 개선 및 높이 prop 추가
[fix] PhotoList 리팩토링 및 잠재적 버그 대응 작업
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 📈 release 릴리즈 배포

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants