Skip to content

Comments

[feature] 카테고리 버튼을 리디자인하고 선택 효과를 적용한다#751

Merged
suhyun113 merged 9 commits intodevelop-fefrom
feature/#743-update-category-button-MOA-235
Sep 21, 2025
Merged

[feature] 카테고리 버튼을 리디자인하고 선택 효과를 적용한다#751
suhyun113 merged 9 commits intodevelop-fefrom
feature/#743-update-category-button-MOA-235

Conversation

@suhyun113
Copy link
Collaborator

@suhyun113 suhyun113 commented Sep 20, 2025

#️⃣연관된 이슈

ex) #743

📝작업 내용

변경된 카테고리 버튼을 적용했습니다.

image

버튼의 선택 효과를 적용했습니다.

image

모바일의 경우

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

개발하면서 발견한건데, 개발 서버 기준으로 동아리 개수가 적을 경우 스크롤이 없습니다. 그래서 카테고리를 이동할 때, 종교 카테고리를 선택하면 아래와 같이 배너가 이상하게 적용됩니다.

image -> 종교 카테고리를 한 번 선택하고 나서 배너가 이동하면, 다시 괜찮아지지만, 그 이후 다른 카테고리를 선택하면, 다시 스크롤바가 생기면서 배너가 이상해집니다... image

🫡 참고사항

Summary by CodeRabbit

  • 신기능
    • 카테고리 선택 시 해당 항목에 활성 아이콘이 표시되어 선택 상태를 즉시 확인할 수 있습니다.
  • 스타일
    • 카테고리 버튼 상단 여백과 버튼 패딩을 줄여 전체 간격을 조정했습니다.
    • 데스크톱에서 아이콘 크기를 키워 가독성을 향상했습니다.
    • 화면 너비별로 아이콘 크기, 캡션 글자 크기·줄간격·여백을 세밀히 조정해 모바일 가독성과 공간 활용을 개선했습니다.
    • 캡션 텍스트에 색상을 추가해 대비를 강화했습니다.

@suhyun113 suhyun113 self-assigned this Sep 20, 2025
@suhyun113 suhyun113 added ✨ Feature 기능 개발 🎨 Design 마크업 & 스타일링 💻 FE Frontend labels Sep 20, 2025
@vercel
Copy link

vercel bot commented Sep 20, 2025

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

Project Deployment Preview Comments Updated (UTC)
moadong Ready Ready Preview Comment Sep 21, 2025 0:12am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 20, 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.
  • 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

카테고리 버튼 스타일(간격·아이콘 크기·타이포)을 조정하고, 활성/비활성 아이콘 매핑을 중앙화한 모듈을 추가했다. CategoryButtonList는 zustand의 selectedCategory를 읽어 활성 상태에 따라 active/inactive 아이콘을 선택해 렌더링하도록 변경되었고, 셀렉터 포맷만 소소하게 리팩터링됐다.

Changes

Cohort / File(s) Summary
스타일 변경
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts
컨테이너 마진 축소(60px→32px) 및 모바일 마진 단순화; 버튼 패딩 변경(8px8px 0); 아이콘 데스크탑 기본 크기 확대(36→56) 및 뷰포트별 축소 규칙 추가; 캡션 폰트 크기/색(#787878)/간격 및 반응형 조정.
아이콘 자원 및 매핑 추가
frontend/src/assets/images/icons/category_button/index.ts
inactive/active 상태별 SVG 임포트 및 inactiveCategoryIcons / activeCategoryIcons 레코드 매핑 추가(카테고리 키 → 경로).
렌더링 로직 변경
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx
개별 아이콘 임포트 제거 후 매핑 사용으로 교체. Category에서 icon 제거·type 사용. zustand의 useSelectedCategory에서 selectedCategory를 읽어 현재 선택 항목이면 activeCategoryIcons[category.type] 사용, 아니면 inactiveCategoryIcons[category.type] 사용하도록 변경. 클릭 핸들링(트래킹/검색 리셋/setSelectedCategory)은 유지.
스토어 셀렉터 포맷 변경
frontend/src/store/useCategoryStore.ts
setSelectedCategory 셀렉터를 한 줄로 리팩터링(기능적 변경 없음).
상수 매핑 교체
frontend/src/constants/CLUB_UNION_INFO.ts
개별 아바타 임포트 제거, inactiveCategoryIcons를 사용해 MEMBER_AVATARS 매핑을 재지정(이미지 경로 참조만 변경).

Sequence Diagram(s)

sequenceDiagram
  actor U as 사용자
  participant CBL as CategoryButtonList
  participant Icons as Icon Mapping Module
  participant Store as useSelectedCategory (zustand)
  participant Analytics as Analytics
  participant Search as SearchStore

  U->>CBL: 카테고리 버튼 클릭
  CBL->>Analytics: 클릭 이벤트 전송
  CBL->>Search: 검색 상태 초기화
  CBL->>Store: setSelectedCategory(category.type)
  Store-->>CBL: selectedCategory 갱신 알림
  CBL->>Icons: 요청(카테고리.type, selectedCategory)
  Icons-->>CBL: active or inactive icon path
  CBL-->>U: UI 갱신(아이콘: active/inactive)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • lepitaaar
  • oesnuj
  • Zepelown

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 제목 "[feature] 카테고리 버튼을 리디자인하고 선택 효과를 적용한다"는 PR의 핵심 변경사항인 카테고리 버튼의 디자인 변경 및 선택 상태 적용을 명확하고 간결하게 요약하고 있어, 변경 내용과 직접적으로 일치합니다.
Linked Issues Check ✅ Passed PR은 카테고리 버튼 리디자인(스타일 조정: frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts)과 선택 효과(활성/비활성 아이콘 매핑 및 선택 상태 반영: frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx, 새 아이콘 매핑 frontend/src/assets/images/icons/category_button/index.ts)를 구현하고 있으며, linked issue MOA-235의 체크리스트 항목들을 충족합니다; 공개 API 변경은 없습니다.
Out of Scope Changes Check ✅ Passed 변경 내용은 주로 카테고리 버튼 관련 스타일·아이콘 중앙화 및 렌더링 로직에 국한되며, CLUB_UNION_INFO.ts에서 아이콘 소스를 inactiveCategoryIcons로 전환한 것은 자산 리팩터링에 해당하므로 요구사항 범위에서 벗어난 큰 기능 변경으로 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#743-update-category-button-MOA-235

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 (5)
frontend/src/store/useCategoryStore.ts (1)

29-31: zustand 구독 2회 → 1회로 축소(shallow 비교 권장)

동일 훅을 두 번 호출해 두 개의 구독이 생깁니다. 미미하지만 하나의 셀렉터로 묶고 shallow 비교를 적용하면 불필요한 리렌더를 줄일 수 있습니다.

적용 diff:

-  const selectedCategory = useCategoryStore((state) => state.selectedCategory);
-  const setSelectedCategory = useCategoryStore((state) => state.setSelectedCategory);
-  return { selectedCategory, setSelectedCategory };
+  const { selectedCategory, setSelectedCategory } = useCategoryStore(
+    (state) => ({ selectedCategory: state.selectedCategory, setSelectedCategory: state.setSelectedCategory }),
+    shallow,
+  );
+  return { selectedCategory, setSelectedCategory };

추가(파일 상단 임포트):

import { shallow } from 'zustand/shallow';
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx (2)

21-26: 카테고리 id를 유니온 타입으로 고정하여 오타/런타임 오류 예방

id를 문자열 유니온으로 제한하면 선택/비교 로직의 안정성이 올라갑니다(오타로 인한 미매칭 방지).

적용 diff:

-interface Category {
-  id: string;
-  name: string;
-  icon: string;
-  activeIcon: string
-}
+type CategoryId = 'all' | '봉사' | '종교' | '취미교양' | '학술' | '운동' | '공연';
+
+interface Category {
+  id: CategoryId;
+  name: string;
+  icon: string;
+  activeIcon: string;
+}

57-63: button 기본 type 지정 및 접근성 상태 노출(aria-pressed) 추가

  • 기본 type 미지정 시 폼 내부에서 의도치 않게 submit 됩니다.
  • 선택 상태를 스크린리더에 노출하면 접근성이 개선됩니다.

적용 diff:

-        <Styled.CategoryButton
+        <Styled.CategoryButton
           key={category.id}
-          onClick={() => handleCategoryClick(category)}
+          onClick={() => handleCategoryClick(category)}
+          type="button"
+          aria-pressed={selectedCategory === category.id}
         >
-          <img src={selectedCategory === category.id ? category.activeIcon : category.icon} alt={category.name} />
+          <img
+            src={selectedCategory === category.id ? category.activeIcon : category.icon}
+            alt={category.name}
+            loading="lazy"
+          />
           <span>{category.name}</span>
         </Styled.CategoryButton>

추가로, 가독성을 위해 조건을 변수로 뽑는 것도 고려해 주세요(가이드라인: 복합 불린을 명명된 변수로). 예: const isSelected = selectedCategory === category.id.

frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts (2)

7-7: 여러 magic number를 상수/토큰으로 치환

여러 px 값과 색상이 하드코딩되어 있습니다. 상수 또는 디자인 토큰(theme)으로 연결하면 유지보수성과 일관성이 좋아집니다.

적용 diff(치환 예):

-  margin-top: 32px;
+  margin-top: ${MARGIN_TOP_DESKTOP}px;
@@
-    margin: 16px 0 12px 0; 
+    margin: ${MARGIN_TOP_MOBILE}px 0 ${MARGIN_BOTTOM_MOBILE}px 0; 
@@
-  padding: 8px 0px;
+  padding: ${BUTTON_PADDING_Y}px 0;
@@
-    width: 56px;
-    height: 56px;
+    width: ${ICON_SIZE_DESKTOP}px;
+    height: ${ICON_SIZE_DESKTOP}px;
@@
-      width: 40px;
-      height: 40px;
+      width: ${ICON_SIZE_SM}px;
+      height: ${ICON_SIZE_SM}px;
@@
-      width: 23px;
-      height: 23px;
+      width: ${ICON_SIZE_XS}px;
+      height: ${ICON_SIZE_XS}px;
@@
-    font-size: 14px;
+    font-size: ${FONT_SIZE_BASE}px;
@@
-    color: #787878;
-    margin-top: 8px;
+    color: ${TEXT_COLOR_SECONDARY};
+    margin-top: ${LABEL_MARGIN_TOP_BASE}px;
@@
-      font-size: 12px;
+      font-size: ${FONT_SIZE_SM}px;
@@
-      font-size: 10px;
-      margin-top: 4px;
+      font-size: ${FONT_SIZE_XS}px;
+      margin-top: ${LABEL_MARGIN_TOP_SM}px;
@@
-      font-size: 8px;
+      font-size: ${FONT_SIZE_XXS}px;

상수 선언(파일 상단에 추가):

const MARGIN_TOP_DESKTOP = 32;
const MARGIN_TOP_MOBILE = 16;
const MARGIN_BOTTOM_MOBILE = 12;

const BUTTON_PADDING_Y = 8;

const ICON_SIZE_DESKTOP = 56;
const ICON_SIZE_SM = 40;
const ICON_SIZE_XS = 23;

const FONT_SIZE_BASE = 14;
const FONT_SIZE_SM = 12;
const FONT_SIZE_XS = 10;
const FONT_SIZE_XXS = 10; // 가독성 확보를 위해 8 → 10 권장

const LABEL_MARGIN_TOP_BASE = 8;
const LABEL_MARGIN_TOP_SM = 4;

const TEXT_COLOR_SECONDARY = '#787878'; // 가능하면 theme.colors.textSecondary 사용

Also applies to: 10-10, 25-25, 33-34, 38-39, 42-43, 48-48, 50-51, 56-56, 61-62, 67-67


10-10: 스크롤바 토글로 인한 배너 레이아웃 흔들림 완화 제안

보고된 현상은 수직 스크롤바 생성/제거 시 뷰포트 폭이 변해 발생할 수 있습니다. 전역 스타일에 scrollbar-gutter: stable both-edges를 적용해 레이아웃 변동을 줄여보세요(지원 브라우저에서 유효).

전역 스타일 예(별도 파일):

// GlobalStyle.ts
export const GlobalStyle = createGlobalStyle`
  html { scrollbar-gutter: stable both-edges; }
  /* 대안: 항상 스크롤바 확보 */
  /* html { overflow-y: scroll; } */
`;

배너/헤더와의 z-index, sticky(top: 56px) 충돌 여부도 함께 점검 바랍니다.

📜 Review details

Configuration used: CodeRabbit 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 b1ee1de and 0fae831.

⛔ Files ignored due to path filters (14)
  • frontend/src/assets/images/icons/category_button/category_all_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_all_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_hobby_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_hobby_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_performance_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_performance_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_religion_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_religion_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_sport_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_sport_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_study_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_study_button_icon_active.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_volunteer_button_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/category_button/category_volunteer_button_icon_active.svg is excluded by !**/*.svg
📒 Files selected for processing (3)
  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts (2 hunks)
  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx (3 hunks)
  • frontend/src/store/useCategoryStore.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.

Files:

  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx
  • frontend/src/store/useCategoryStore.ts
  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts
frontend/**/*.tsx

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order 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.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.

Files:

  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx
🧬 Code graph analysis (1)
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx (1)
frontend/src/store/useCategoryStore.ts (1)
  • useSelectedCategory (28-32)
🔇 Additional comments (1)
frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx (1)

10-16: active 아이콘 도입 LGTM — 자산 누락 없음 (검증 완료)

frontend/src/assets/images/icons/category_button 내 category_*_button_icon_active.svg 7/7 파일 존재 확인.

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.

적용 수고하셨습니당 🙌
참고로 총동연 페이지에서도 동일한 카테고리 아이콘들을 사용하고 있어서 변경사항 있으면 그쪽도 같이 확인해주시면 감사하겠습니다~~

image

Comment on lines 10 to 16
import iconAllActive from '@/assets/images/icons/category_button/category_all_button_icon_active.svg';
import iconVolunteerActive from '@/assets/images/icons/category_button/category_volunteer_button_icon_active.svg';
import iconReligionActive from '@/assets/images/icons/category_button/category_religion_button_icon_active.svg';
import iconHobbyActive from '@/assets/images/icons/category_button/category_hobby_button_icon_active.svg';
import iconStudyActive from '@/assets/images/icons/category_button/category_study_button_icon_active.svg';
import iconSportActive from '@/assets/images/icons/category_button/category_sport_button_icon_active.svg';
import iconPerformanceActive from '@/assets/images/icons/category_button/category_performance_button_icon_active.svg';
Copy link
Member

Choose a reason for hiding this comment

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

처음에는 아이콘이 몇 개 안 될 줄 알고 개별 import 했는데
이렇게 14개 정도로 늘어나면 index.ts로 모아서 재export 하는 게 훨씬 깔끔하겠네요

방식은 크게 두 가지가 있어용

1️⃣ 단순 모아주기 방식

카테고리 아이콘들 폴더에 index.ts를 만들고, 각 SVG의 default export를 이름 붙여 다시 export 합니다.

// index.ts
...
export { default as iconAllActive } from './category_all_button_icon_active.svg';
export { default as iconVolunteerActive } from './category_volunteer_button_icon_active.svg';
export { default as iconReligionActive } from './category_religion_button_icon_active.svg';
export { default as iconHobbyActive } from './category_hobby_button_icon_active.svg';
export { default as iconStudyActive } from './category_study_button_icon_active.svg';
export { default as iconSportActive } from './category_sport_button_icon_active.svg';
export { default as iconPerformanceActive } from './category_performance_button_icon_active.svg';

→ 사용하는 쪽에서는 한줄로 가능

import {
...
  iconAllActive,
  iconVolunteerActive,
  iconReligionActive,
  iconHobbyActive,
  iconStudyActive,
  iconSportActive,
  iconPerformanceActive,
} from '@/assets/images/icons/category_button';

2️⃣ 객체(Map)으로 묶기 방식

만약 카테고리별로 매핑이 필요하다면 객체로 관리하는 것도 좋아요.

// index.ts
import all from './category_all_button_icon_active.svg';
import volunteer from './category_volunteer_button_icon_active.svg';
import religion from './category_religion_button_icon_active.svg';
import hobby from './category_hobby_button_icon_active.svg';
import study from './category_study_button_icon_active.svg';
import sport from './category_sport_button_icon_active.svg';
import performance from './category_performance_button_icon_active.svg';
...

export const categoryIcons = {
  all,
  volunteer,
  religion,
  hobby,
  study,
  sport,
  performance,
} as const;

→ 사용 시에는 이렇게 더 짧게 가능함다, 대신 .으로 내부 접근 필요하죠

import { categoryIcons } from '@/assets/images/icons/category_button';

<img src={categoryIcons.study} alt="스터디 아이콘" />

장점

  1. import 구문이 훨씬 짧아짐 (코드 가독성 ↑)
  2. 아이콘 추가/삭제 관리가 쉬움 (한 곳에서만 관리)
  3. (2번 객체 방식일 경우) 카테고리 키 기반 접근 가능 → 반복 코드 줄고 확장성 ↑
  4. 파일 구조 변경 시 유지보수 용이 (경로가 바뀌어도 index.ts만 수정)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

조언 감사합니다!!!

export const inactiveCategoryIcons : Record<string, string> = {
    all : iconAll,
    volunteer : iconVolunteer,
    religion : iconReligion,
    hobby : iconHobby,
    study : iconStudy,
    sport : iconSport,
    performance : iconPerformance
}

export const activeCategoryIcons : Record<string, string> = {
    all : iconAllActive,
    volunteer : iconVolunteerActive,  
    religion : iconReligionActive,
    hobby : iconHobbyActive,
    study : iconStudyActive,
    sport : iconSportActive,
    performance : iconPerformanceActive
}

수정 완료했습니다! import가 많아서 정신없었는데, 깔끔해진 것 같아요~

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 (2)
frontend/src/assets/images/icons/category_button/index.ts (2)

16-24: 타입 안전성 강화: Record<string, string> → CategoryType 유니온으로 한정

키가 자유로운 string이면 누락/오타가 런타임 undefined로 새어 나올 위험이 있습니다. 카테고리 키를 유니온으로 고정하고 Readonly로 동결해 주세요. 소비자 코드(스토어, 리스트)도 동일 타입을 재사용하면 불일치가 사전에 차단됩니다.

다음과 같이 변경을 제안합니다.

+// 카테고리 키 소스 오브 트루스
+export const CATEGORY_TYPES = ['all','volunteer','religion','hobby','study','sport','performance'] as const;
+export type CategoryType = typeof CATEGORY_TYPES[number];

-export const inactiveCategoryIcons : Record<string, string> = {
+export const inactiveCategoryIcons: Readonly<Record<CategoryType, string>> = {
     all : iconAll,
     volunteer : iconVolunteer,
     religion : iconReligion,
     hobby : iconHobby,
     study : iconStudy,
     sport : iconSport,
     performance : iconPerformance
 }

또는 다음과 같이 satisfies를 사용할 수도 있습니다(개인 선호):

export const inactiveCategoryIcons = {
  all: iconAll,
  volunteer: iconVolunteer,
  religion: iconReligion,
  hobby: iconHobby,
  study: iconStudy,
  sport: iconSport,
  performance: iconPerformance,
} satisfies Record<CategoryType, string>;

26-34: 동일한 타입 제약을 active 맵에도 적용

active 맵도 동일한 타입 제약을 적용해 키 불일치를 방지하세요.

-export const activeCategoryIcons : Record<string, string> = {
+export const activeCategoryIcons: Readonly<Record<CategoryType, string>> = {
     all : iconAllActive,
     volunteer : iconVolunteerActive,  
     religion : iconReligionActive,
     hobby : iconHobbyActive,
     study : iconStudyActive,
     sport : iconSportActive,
     performance : iconPerformanceActive
 }

또한 소비자에서의 분기 단순화를 위해 선택적 헬퍼를 제공할 수 있습니다(선택):

export const getCategoryIcon = (type: CategoryType, isActive: boolean): string =>
  isActive ? activeCategoryIcons[type] : inactiveCategoryIcons[type];
📜 Review details

Configuration used: CodeRabbit 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 c250cd4 and 1bf6582.

📒 Files selected for processing (2)
  • frontend/src/assets/images/icons/category_button/index.ts (1 hunks)
  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx
🧰 Additional context used
📓 Path-based instructions (1)
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.

Files:

  • frontend/src/assets/images/icons/category_button/index.ts
🔇 Additional comments (2)
frontend/src/assets/images/icons/category_button/index.ts (2)

16-34: 키 명칭 일치 확인 — 수정 불필요

icons 모듈(frontend/src/assets/images/icons/category_button/index.ts)과 사용처(frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.tsx, frontend/src/store/useCategoryStore.ts)에서 모두 'sport' 키로 일치합니다.


1-14: SVG 활성/비활성 페어의 viewBox/크기 일치 여부 확인 필요

활성/비활성 아이콘의 viewBox/width/height 불일치로 선택 시 레이아웃 점프가 발생할 수 있습니다 — PR 본문에서 언급된 '종교' 배너 이상과 연관 가능성이 있으니 frontend/src/assets/images/icons/category_button/ 폴더의 SVG 페어를 확인하고 제공한 검사 스크립트를 로컬에서 실행하여 불일치 출력(또는 스크린샷)을 첨부하십시오.

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 (2)
frontend/src/constants/CLUB_UNION_INFO.ts (2)

12-21: 타입 안전성 강화: as const + satisfies로 키 오타를 컴파일 타임에 차단

현재 inactiveCategoryIconsRecord<string, string>라 속성 오타가 컴파일 타임에 검출되지 않습니다. 이 맵은 변경 빈도가 낮으므로 리터럴 고정과 키 유니언을 적용해 안전성을 높이는 걸 권장합니다.

아래처럼 키 유니언을 선언하고, 맵에 as const satisfies를 적용해 주세요.

@@
-const MEMBER_AVATARS = {
+type MemberAvatarKey =
+  | 'PRESIDENT'
+  | 'VICE_PRESIDENT'
+  | 'SECRETARY'
+  | 'PROMOTION'
+  | 'RELIGION'
+  | 'HOBBY'
+  | 'STUDY'
+  | 'VOLUNTEER'
+  | 'PERFORMANCE'
+  | 'SPORT';
+
+const MEMBER_AVATARS = {
   PRESIDENT: inactiveCategoryIcons.all,
   VICE_PRESIDENT: inactiveCategoryIcons.all,
   SECRETARY: inactiveCategoryIcons.all,
   PROMOTION: inactiveCategoryIcons.all,
   RELIGION: inactiveCategoryIcons.religion,
   HOBBY: inactiveCategoryIcons.hobby,
   STUDY: inactiveCategoryIcons.study,
   VOLUNTEER: inactiveCategoryIcons.volunteer,
   PERFORMANCE: inactiveCategoryIcons.performance,
   SPORT: inactiveCategoryIcons.sport,
-};
+} as const satisfies Record<MemberAvatarKey, string>;

추가로, 가능하다면 아이콘 모듈(category_button/index.ts)에서도 Record<string,string> 대신 as const로 키를 고정해 keyof를 노출하면 전역적으로 더 안전해집니다.


12-21: 배너 흔들림 이슈 대응안(참고): 스크롤바 토글로 인한 레이아웃 시프트 방지

PR 설명의 배너 레이아웃 깨짐은 스크롤바 등장/제거에 따른 컨테이너 폭 변화일 가능성이 큽니다. 카테고리 선택과 맞물려 발생한다면, 컨테이너에 아래 CSS를 고려해 주세요.

.container {
  /* 스크롤바 유무와 관계없이 공간 예약 */
  scrollbar-gutter: stable both-edges;
}

/* 광범위 호환성 보완책 */
@supports not (scrollbar-gutter: stable) {
  .container { overflow-y: scroll; } /* 항상 세로 스크롤 공간 확보 */
}

의도된 레이아웃 컨테이너에 적용 후, 문제 재현 케이스(종교 카테고리 선택)에서 시프트가 사라지는지 확인 부탁드립니다.

📜 Review details

Configuration used: CodeRabbit 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 1bf6582 and cf0eabc.

📒 Files selected for processing (1)
  • frontend/src/constants/CLUB_UNION_INFO.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.

Files:

  • frontend/src/constants/CLUB_UNION_INFO.ts
🧬 Code graph analysis (1)
frontend/src/constants/CLUB_UNION_INFO.ts (1)
frontend/src/assets/images/icons/category_button/index.ts (1)
  • inactiveCategoryIcons (16-24)
🔇 Additional comments (2)
frontend/src/constants/CLUB_UNION_INFO.ts (2)

12-21: 디자인 의도 확인: 임원 4개 항목이 모두 all 아이콘 사용

PRESIDENT/VICE_PRESIDENT/SECRETARY/PROMOTION이 동일하게 all 아이콘을 쓰는 것이 최종 디자인 의도인지 확인 부탁드립니다. 역할별 별도 아바타가 필요 없다면 현재 구현으로 충분합니다.


1-1: 중앙화된 아이콘 모듈 import 적절 — 경로 별칭(@) 확인 필요 (자동검증 불가)

배럴에서의 명시적 import는 적절합니다. 자동 검증 중 frontend/tsconfig.json이 유효한 JSON이 아니라 '@' → 'src' 매핑 확인과 inactiveCategoryIcons export 검사에 실패했습니다. 아래를 확인해 재검증해 주세요.

위치:

  • frontend/tsconfig.json
  • frontend/src/assets/images/icons/category_button/index.ts

로컬에서 실행할 검증 명령:

python3 -m json.tool frontend/tsconfig.json
rg -n -C2 "inactiveCategoryIcons" frontend/src || true
rg -n -C2 -P "export\s+(const|default)\s+inactiveCategoryIcons" frontend/src || true
ls -la frontend/src/assets/images/icons/category_button || true

@suhyun113 suhyun113 merged commit 3c8b17f into develop-fe Sep 21, 2025
5 checks passed
@lepitaaar lepitaaar deleted the feature/#743-update-category-button-MOA-235 branch October 21, 2025 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎨 Design 마크업 & 스타일링 💻 FE Frontend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants