Skip to content

[feature] 상세페이지 소개 내용 및 FAQ 컴포넌트 구현#959

Merged
seongwon030 merged 8 commits intodevelop-fefrom
feature/#952-club-detail-introduction-MOA-446
Dec 23, 2025
Merged

[feature] 상세페이지 소개 내용 및 FAQ 컴포넌트 구현#959
seongwon030 merged 8 commits intodevelop-fefrom
feature/#952-club-detail-introduction-MOA-446

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented Dec 23, 2025

#️⃣연관된 이슈

ex) #952

📝작업 내용

1. ClubDetailContent 컴포넌트 신규 구현

동아리 상세 페이지의 핵심 정보를 보여주는 독립적인 컴포넌트를 개발했습니다.

  • 포함 섹션: 소개글, 활동 내용, 수상 경력, 인재상, 활동 혜택, 자주 묻는 질문(FAQ)
  • 수상 경력(Awards) 특화 디자인: 학기 배지와 성과 리스트를 결합한 전용 UI를 적용했습니다.

FAQ 섹션 추가: 자주 묻는 질문을 효율적으로 보여주기 위해 아코디언 UI를 도입했습니다.

  • 여러 항목을 동시에 펼쳐볼 수 있는 다중 토글 기능을 지원합니다.
  • 질문(Q)과 답변(A)을 구분하는 스타일을 적용했습니다. (회전하는 화살표 아이콘, 배경색 구분 등)

2. 리팩토링 및 헬퍼 적용

스타일 파일에서 typography 객체를 CSS 속성으로 변환해주는 setTypography 헬퍼 함수를 도입했습니다.

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

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

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

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

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

🫡 참고사항

Summary by CodeRabbit

  • 새로운 기능
    • 클럽 상세 통합 콘텐츠 추가(소개·활동·수상·이상적 지원자·혜택·FAQ, 클릭형 FAQ 아코디언 포함)
  • 스타일
    • 모바일 대응 레이아웃, 학기 배지·수상 목록·FAQ 시각 스타일 적용 및 신규 타이포그래피 등 스타일 토큰 추가
  • 리팩터
    • 여러 섹션을 통합해 렌더 흐름 단순화
  • 기타
    • FAQ 토글 클릭 이벤트 추적용 이벤트 항목 추가

✏️ Tip: You can customize this high-level summary in your review settings.

- 모바일 호환성을 위해 타이포그래피 테마에 `title7` 추가
- ClubDetailContent 반응형 스타일 및 폰트 크기 조정
- 동아리 상세 정보 표시 UI 추가 및 스타일 정의
- 텍스트 줄바꿈 처리 최적화 및 모바일 뷰 폰트/간격 조정
@seongwon030 seongwon030 requested a review from oesnuj December 23, 2025 08:36
@seongwon030 seongwon030 self-assigned this Dec 23, 2025
@seongwon030 seongwon030 added ✨ Feature 기능 개발 💻 FE Frontend labels Dec 23, 2025
@vercel
Copy link

vercel bot commented Dec 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
moadong Ready Ready Preview, Comment Dec 23, 2025 3:27pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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

Walkthrough

ClubDetail 페이지에 소개·활동·수상·지원자 정보·FAQ를 렌더링하는 신규 ClubDetailContent 컴포넌트를 추가하고, 해당 컴포넌트용 styled-components 스타일 모듈과 테마의 타이포그래피 토큰(title7)을 확장했으며, FAQ 토글 이벤트 상수를 추가했습니다.

Changes

Cohort / File(s) 변경 요약
ClubDetailContent 스타일 정의
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
Container, Section, SectionTitle, TextContainer, Text, AwardGroup, SemesterBadge, AwardList, AwardItem, FaqSection, FaqHeader, FaqList, FaqItem, QuestionRow, QuestionText, ArrowIcon($isOpen prop), AnswerContainer, AnswerBox 등 다수의 styled-components 추가 — 테마 타이포그래피/색상, 반응형 미디어쿼리, FAQ 아코디언 스타일 포함
ClubDetailContent 컴포넌트
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
새로운 React 컴포넌트 추가 및 기본 export. Award, IdealCandidate, Faq 인터페이스 정의. 소개문, 활동설명(한글 제목 포함), 학기별 수상 목록, 이상적 지원자/혜택, FAQ 아코디언(토글 상태 관리 및 Mixpanel 이벤트 전송) 렌더링 로직 구현
페이지 통합
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
기존 개별 섹션(InfoTabs, InfoBox, IntroduceBox, PhotoList 등)을 대체하여 ClubDetailContent를 임포트·사용하고 관련 props(활동설명, 수상, 이상적 지원자, 혜택, FAQ 등)를 전달하도록 변경
테마 타이포그래피
frontend/src/styles/theme/typography.ts
typography.titletitle7 토큰(16px, weight 700) 추가
이벤트 상수 추가
frontend/src/constants/eventName.ts
USER_EVENTFAQ_TOGGLE_CLICKED: 'FAQ Toggle Clicked' 항목 추가

Sequence Diagram(s)

(생성 조건 미충족 — 변경은 주로 UI 컴포넌트·스타일 추가 및 로컬 토글/렌더링으로, 다중 시스템 간의 순차 흐름 시각화가 필요하지 않아 생략)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

🎨 Design

Suggested reviewers

  • oesnuj
  • lepitaaar
  • seongje973

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[feature] 상세페이지 소개 내용 및 FAQ 컴포넌트 구현' accurately describes the main changes: implementing club detail page introduction content and FAQ components.
Linked Issues check ✅ Passed The pull request implements the ClubDetailContent component with intro, activity, awards, ideal candidate, benefits, and FAQ sections as required by MOA-446, with mobile and desktop styling using responsive media queries.
Out of Scope Changes check ✅ Passed All changes are within scope: new styling module, ClubDetailContent component implementation, typography scale addition, event constant for FAQ analytics, and integration into ClubDetailPage align with MOA-446 objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#952-club-detail-introduction-MOA-446

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9bde3b6 and 1cc8dad.

📒 Files selected for processing (1)
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 1

🧹 Nitpick comments (3)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx (2)

9-9: TODO 주석을 처리할 수 있도록 도와드릴 수 있습니다.

tags 필드가 추가될 수 있다는 TODO가 있습니다. 이 기능 구현 코드를 생성하거나 이슈로 등록하는 것을 도와드릴까요?


56-57: 배열 인덱스를 key로 사용하는 것을 개선해주세요.

현재 awards.mapachievements.map에서 배열 인덱스를 key로 사용하고 있습니다. 배열이 재정렬되거나 항목이 추가/삭제될 경우 React의 재조정(reconciliation) 과정에서 문제가 발생할 수 있습니다.

가능하다면 각 항목의 고유한 식별자(예: ID나 semester+achievement 조합)를 key로 사용하는 것을 권장합니다.

🔎 개선 제안

awards가 고유 ID를 가지고 있다면 다음과 같이 수정할 수 있습니다:

-  {awards.map((award, index) => (
-    <S.AwardGroup key={index}>
+  {awards.map((award) => (
+    <S.AwardGroup key={`${award.semester}`}>
      <S.SemesterBadge>{award.semester}</S.SemesterBadge>
      <S.AwardList>
-        {award.achievements.map((item, idx) => (
-          <S.AwardItem key={idx}>{item}</S.AwardItem>
+        {award.achievements.map((item, idx) => (
+          <S.AwardItem key={`${award.semester}-${idx}`}>{item}</S.AwardItem>
        ))}
      </S.AwardList>
    </S.AwardGroup>
  ))}

더 나은 방법은 각 achievement에 고유 ID가 있다면 그것을 사용하는 것입니다.

Also applies to: 60-61

frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (1)

71-87: font-weight 중복 설정을 개선할 수 있습니다.

SemesterBadge에서 setTypography를 통해 font-weight를 설정한 후 즉시 다시 오버라이드하고 있습니다:

  • Line 79: typography.paragraph.p5는 weight 500을 설정
  • Line 80: font-weight: 600으로 즉시 오버라이드
  • Line 84-85에서도 동일한 패턴 반복

이는 코드를 혼란스럽게 만들 수 있습니다. 다음 방법들을 고려해보세요:

  1. weight 600인 타이포그래피 토큰을 사용 (예: typography.paragraph.p2)
  2. setTypography를 사용하지 않고 font-size만 직접 설정
🔎 개선 제안

방법 1: 적절한 타이포그래피 토큰 사용

  ${media.mobile} {
-    ${setTypography(typography.paragraph.p6)};
-    font-weight: 600;
+    ${setTypography(typography.paragraph.p2)};
  }

방법 2: font-size만 직접 설정

  export const SemesterBadge = styled.div`
    /* ... */
-    ${setTypography(typography.paragraph.p5)};
-    font-weight: 600;
+    font-size: ${typography.paragraph.p5.size};
+    font-weight: 600;
    /* ... */
    
    ${media.mobile} {
-      ${setTypography(typography.paragraph.p6)};
-      font-weight: 600;
+      font-size: ${typography.paragraph.p6.size};
+      font-weight: 600;
    }
  `;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between aab9273 and 5b21ce9.

📒 Files selected for processing (3)
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/styles/theme/typography.ts
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries with if/else or IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/styles/theme/typography.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
frontend/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated components/HOCs
Separate significantly different conditional UI/logic into distinct components
Colocate simple, localized logic or use inline definitions to reduce context switching
Choose field-level or form-level cohesion based on form requirements when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/styles/theme/typography.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Separate significantly different conditional UI/logic into distinct components

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
📚 Learning: 2025-07-19T05:05:10.196Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🧬 Code graph analysis (1)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (3)
frontend/src/styles/mediaQuery.ts (1)
  • media (8-14)
frontend/src/styles/theme/typography.ts (1)
  • typography (1-24)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
🔇 Additional comments (2)
frontend/src/styles/theme/typography.ts (1)

9-9: LGTM! 새로운 타이포그래피 토큰이 적절하게 추가되었습니다.

기존 title 토큰들의 크기 패턴(40px → 18px)을 잘 따르고 있으며, 모바일 반응형 디자인에 활용될 것으로 보입니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (1)

6-9: LGTM! 타이포그래피 헬퍼 함수가 잘 구현되었습니다.

setTypography 헬퍼 함수는 타이포그래피 토큰을 CSS 속성으로 변환하는 깔끔한 추상화입니다. 코드 재사용성과 일관성을 높여줍니다.

- 다중 선택 가능한 FAQ 아코디언(Accordion) UI 추가
- Section과 구분되는 FAQ 전용 헤더 및 리스트 스타일 정의
@seongwon030 seongwon030 changed the title [feature] 상세페이지 소개 내용 컴포넌트 구현 [feature] 상세페이지 소개 내용 및 FAQ 컴포넌트 구현 Dec 23, 2025
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: 0

🧹 Nitpick comments (3)
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (2)

50-60: 주석 처리된 코드를 제거하거나 명확히 해주세요.

이전 UI 컴포넌트들(InfoTabs, InfoBox, IntroduceBox, PhotoList)이 주석 처리되어 있습니다. 새 컴포넌트로의 전환이 완료되었다면 주석 처리된 코드를 제거하여 코드베이스를 깔끔하게 유지하는 것이 좋습니다. 만약 임시로 참고용으로 남겨둔 것이라면, TODO 주석을 추가하거나 제거 예정 일정을 명시해주세요.


61-104: 컴포넌트 통합이 잘 구현되었습니다.

새로운 ClubDetailContent 컴포넌트가 적절하게 통합되었으며, 테스트 데이터를 통해 컴포넌트의 모든 섹션을 확인할 수 있도록 구성되어 있습니다.

선택적 개선사항: FAQ 데이터(lines 90-103)에서 질문과 답변이 모두 동일한 텍스트("동아리에 가입하고 싶어요.")로 되어 있습니다. 실제 사용 케이스를 더 잘 반영하는 다양한 테스트 데이터를 사용하면 개발 및 리뷰 과정에서 도움이 될 수 있습니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (1)

6-9: 타이포그래피 헬퍼 함수가 유용합니다.

setTypography 헬퍼 함수는 테마의 타이포그래피 토큰을 CSS 속성으로 변환하는 간결한 추상화를 제공하며, 코드 전반에 걸쳐 일관성을 유지하는 데 도움이 됩니다.

선택적 개선사항: 만약 이 헬퍼가 다른 스타일 파일에서도 사용될 가능성이 있다면, @/styles/utils 또는 유사한 공유 유틸리티 위치로 추출하는 것을 고려해보세요.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5b21ce9 and 10d93df.

📒 Files selected for processing (3)
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries with if/else or IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
frontend/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated components/HOCs
Separate significantly different conditional UI/logic into distinct components
Colocate simple, localized logic or use inline definitions to reduce context switching
Choose field-level or form-level cohesion based on form requirements when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Use Component Composition instead of Props Drilling to reduce coupling

Applied to files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
📚 Learning: 2025-07-19T05:05:10.196Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Separate significantly different conditional UI/logic into distinct components

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Abstract complex logic/interactions into dedicated components/HOCs

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts
🧬 Code graph analysis (1)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (3)
frontend/src/styles/mediaQuery.ts (1)
  • media (8-14)
frontend/src/styles/theme/typography.ts (1)
  • typography (1-24)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
🔇 Additional comments (4)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx (3)

4-26: 인터페이스 정의가 명확합니다.

타입 정의가 잘 구조화되어 있으며, 모든 props를 optional로 설정한 것은 조건부 렌더링을 지원하기 위한 적절한 설계입니다. Line 10의 TODO 주석도 향후 확장 가능성을 명확히 표시하고 있습니다.


36-43: FAQ 아코디언 상태 관리가 올바르게 구현되었습니다.

다중 선택이 가능한 아코디언 동작이 정확하게 구현되었으며, 함수형 업데이트 패턴을 사용하여 상태 업데이트의 안정성을 보장하고 있습니다.


98-133: FAQ 섹션이 정상적으로 렌더링됩니다.

이전 리뷰에서 지적되었던 faqs prop 미렌더링 문제가 해결되었습니다. FAQ 아코디언 UI가 완전하게 구현되어 있으며, 질문 클릭 시 답변이 토글되는 동작이 올바르게 작동합니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.styles.ts (1)

113-218: FAQ 아코디언 스타일링이 잘 구현되었습니다.

FAQ 섹션의 스타일링이 체계적으로 구성되어 있으며, 다음 요소들이 특히 우수합니다:

  • ArrowIcon$isOpen transient prop 사용 (styled-components v6 권장 패턴)
  • 부드러운 회전 애니메이션 (0.3s ease)
  • ::before 의사 요소를 통한 Q./A. 접두사 구현으로 마크업 간결성 유지
  • 반응형 패딩 및 타이포그래피 조정

- 동아리 상세 FAQ 열람 여부 및 관심 질문 분석을 위한 로그 수집 구현
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: 2

🧹 Nitpick comments (2)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx (2)

117-133: FAQ 아코디언에 접근성 속성을 추가하는 것을 권장합니다.

현재 FAQ 토글 버튼에 ARIA 속성과 키보드 지원이 없어 스크린 리더 사용자와 키보드 전용 사용자의 접근성이 제한됩니다.

다음 개선사항을 고려해 주세요:

  • role="button" 추가
  • aria-expanded={isOpen} 추가
  • onKeyDown 핸들러로 Enter/Space 키 지원
  • tabIndex={0} 추가 (포커스 가능하도록)
🔎 접근성 개선 제안
-<S.QuestionRow onClick={() => handleToggleFaq(index)}>
+<S.QuestionRow 
+  role="button"
+  tabIndex={0}
+  aria-expanded={isOpen}
+  onClick={() => handleToggleFaq(index)}
+  onKeyDown={(e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      handleToggleFaq(index);
+    }
+  }}
+>
  <S.QuestionText>{faq.question}</S.QuestionText>

또한 답변 영역에 role="region"aria-labelledby를 추가하면 더욱 향상됩니다.


109-144: FAQ 섹션을 별도 컴포넌트로 추출하는 것을 고려해보세요.

FAQ 섹션(35줄)은 자체 상태와 이벤트 핸들링 로직을 포함하고 있어 독립적인 컴포넌트로 추출하면 테스트 가능성과 재사용성이 향상됩니다.

💡 리팩토링 제안

새로운 FaqSection 컴포넌트를 생성:

// FaqSection.tsx
interface FaqSectionProps {
  faqs: Faq[];
}

const FaqSection = ({ faqs }: FaqSectionProps) => {
  const trackEvent = useMixpanelTrack();
  const [openFaqIndices, setOpenFaqIndices] = useState<number[]>([]);
  
  const handleToggleFaq = (index: number) => {
    // ... 기존 로직
  };
  
  return (
    <S.FaqSection>
      {/* ... 기존 JSX */}
    </S.FaqSection>
  );
};

그리고 ClubDetailContent에서 사용:

-{faqs && faqs.length > 0 && (
-  <S.FaqSection>
-    {/* ... 35 lines ... */}
-  </S.FaqSection>
-)}
+{faqs && faqs.length > 0 && <FaqSection faqs={faqs} />}

Based on coding guidelines: "Abstract complex logic/interactions into dedicated components/HOCs"

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 10d93df and 7f9cafb.

📒 Files selected for processing (2)
  • frontend/src/constants/eventName.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries with if/else or IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Files:

  • frontend/src/constants/eventName.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/constants/eventName.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
frontend/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated components/HOCs
Separate significantly different conditional UI/logic into distinct components
Colocate simple, localized logic or use inline definitions to reduce context switching
Choose field-level or form-level cohesion based on form requirements when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🧠 Learnings (4)
📓 Common learnings
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Separate significantly different conditional UI/logic into distinct components

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
📚 Learning: 2025-07-19T05:05:10.196Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx
🧬 Code graph analysis (1)
frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx (1)
frontend/src/constants/eventName.ts (1)
  • USER_EVENT (1-36)
🔇 Additional comments (2)
frontend/src/constants/eventName.ts (1)

35-35: LGTM!

FAQ 토글 이벤트 상수가 기존 패턴과 일관되게 추가되었습니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailContent/ClubDetailContent.tsx (1)

40-54: LGTM!

FAQ 토글 로직과 이벤트 트래킹이 올바르게 구현되었습니다. 특히 isOpening을 명명된 변수로 선언하여 가독성을 높였고, 배열 접근 전 bounds checking을 통해 안전성을 확보했습니다.

- Awards: semester 기반 key 사용
- FAQs: question 기반 key 사용
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.

sectionTitle 어미를 하나로 맞추면 좋을 것 같아요
수고하셨습니다 👍

@seongwon030 seongwon030 merged commit 4bc7dd1 into develop-fe Dec 23, 2025
3 checks passed
@seongwon030 seongwon030 deleted the feature/#952-club-detail-introduction-MOA-446 branch December 23, 2025 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] MOA-446 동아리 상세페이지 소개 내용 컴포넌트 구현

2 participants

Comments