Skip to content

[refactor] 디자인 시스템 기반 공통 스타일 구조 정리 및 토큰화#946

Merged
oesnuj merged 12 commits intodevelop-fefrom
refactor/#943-design-system-style-tokens-MOA-431
Dec 21, 2025
Merged

[refactor] 디자인 시스템 기반 공통 스타일 구조 정리 및 토큰화#946
oesnuj merged 12 commits intodevelop-fefrom
refactor/#943-design-system-style-tokens-MOA-431

Conversation

@oesnuj
Copy link
Member

@oesnuj oesnuj commented Dec 21, 2025

#️⃣ 연관된 이슈


📝 작업 요약

이번 PR에서는 디자인 시스템 도입의 초기 단계로, styled-components 기반에서 색상·타이포그래피 토큰을 정의하고 이를 하나의 테마로 통합했습니다.

기존에 하드코딩되어 있던 스타일을 제거하고, ThemeProvider를 통해 전역적으로 일관된 스타일을 사용할 수 있는 환경을 구축했습니다.


🛠 작업 내용

1. 디자인 시스템 기반 구조 구축

색상 토큰 정의

  • 위치: frontend/src/styles/theme/colors.ts
  • Primary / Secondary / Accent / Base / Neutral(Gray) 팔레트 정의
  • 각 색상별 shade 체계(100~900) 구성

타이포그래피 토큰 정의

  • 위치: frontend/src/styles/theme/typography.ts
  • Heading(H1~H6), Body, Caption, Label 스타일 정의
  • font-size / font-weight / line-height 체계화

테마 통합

  • 위치: frontend/src/styles/theme/index.ts
  • colors, typography를 하나의 theme 객체로 통합
  • TypeScript 타입 정의를 통해 타입 안정성 확보

2. 동아리 관련 색상 상수화

  • 위치: frontend/src/styles/clubTags.ts
  • 동아리 구분(중동 / 과동) 및 카테고리별 색상 정의
  • 모집 상태별 색상 정의
    • 모집중 / 모집마감 / 상시모집
image

3. 컴포넌트 리팩토링

ClubTag 컴포넌트

  • 하드코딩된 색상을 TAG_COLORS 상수로 교체
  • 텍스트 색상을 theme.colors.gray[900] 기준으로 통일

ClubStateBox 컴포넌트

  • 상태별 색상을 STATUS_COLORS 상수로 분리
  • #fffffftheme.colors.base.white 사용

SelectTags 컴포넌트

  • 태그 데이터 구조 개선
    • string[]TagOption[]
  • 각 태그에 색상 토큰 적용 가능하도록 확장
  • 선택된 태그의 텍스트 색상을 #3a3a3a로 통일하여 가독성 개선
image

4. ThemeProvider 설정

  • App.tsx에 ThemeProvider 적용
  • 전역적으로 theme 접근 가능한 환경 구성
    • ({ theme }) => theme.colors.xxx 형태 사용

💬 논의하고 싶은 부분

  • 하드코딩 색상 마이그레이션 전략
    • 남아있는 컴포넌트들의 색상 토큰화 작업을 어떤 기준으로 우선 적용하면 좋을지 의견 부탁드립니다.

🫡 참고 사항

  • 이번 작업은 디자인 시스템 도입의 첫 단계입니다.
  • styled-components에서는 ThemeProvider를 통해 theme 접근
  • JS 로직 등 직접 접근이 필요한 경우
    import { colors } from '@/styles/theme/colors';

- Primary, Secondary, Accent, Base, Neutral 색상 체계 구축
- 서비스 메인 브랜드 컬러(Primary)
- 태그/상태/보조 강조용 컬러(Secondary 1-6)
- 상태/의미 전달용 강조 컬러(Accent 1-3)
- 기본 배경/텍스트 컬러(Base)
- 텍스트/라인/배경용 무채색(Gray 100-900)
- Title 스타일 (title1-6)
- Paragraph 스타일 (p1-7)
- Button 스타일 (button1-2)
- 각 스타일별 size, weight, letterSpacing 정의
- colors와 typography를 하나의 theme 객체로 통합
- Theme 타입 export하여 타입 안정성 확보
- ThemeProvider에서 사용할 수 있도록 준비
- styles/clubTags.ts 생성
- TAG_COLORS: 동아리 분류/분과별 색상 정의 (secondary 색상 활용)
- STATUS_COLORS: 모집 상태별 색상 정의 (accent/gray 색상 활용)
- 중앙 집중식 색상 관리로 일관성 확보
변경 파일
- ClubTag.tsx: 로컬 TagColors 제거 → TAG_COLORS import
- ClubStateBox.tsx: 로컬 STATE_COLORS 제거 → STATUS_COLORS import
- 태그 데이터 구조를 문자열에서 TagOption 객체로 변경
- 각 태그에 중앙 관리되는 색상 상수(TAG_COLORS) 적용
- 동아리 구분 및 카테고리 태그에 개별 색상 지정
@oesnuj oesnuj requested a review from seongwon030 December 21, 2025 12:31
@oesnuj oesnuj self-assigned this Dec 21, 2025
@oesnuj oesnuj added 🎨 Design 마크업 & 스타일링 🔨 Refactor 코드 리팩토링 💻 FE Frontend labels Dec 21, 2025
@vercel
Copy link

vercel bot commented Dec 21, 2025

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

Project Deployment Review Updated (UTC)
moadong Ready Ready Preview, Comment Dec 21, 2025 1:37pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 21, 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

이 PR은 애플리케이션에 디자인 토큰 기반 테마 시스템을 도입합니다. 새로운 색상 및 타이포그래피 토큰을 정의하고, ThemeProvider를 통해 전역 테마를 제공하며, 기존 컴포넌트들의 하드코딩된 스타일을 토큰 기반 색상 매핑으로 교체합니다.

Changes

Cohort / File(s) 변경 요약
테마 시스템 기초
frontend/src/styles/theme/colors.ts, frontend/src/styles/theme/typography.ts, frontend/src/styles/theme/index.ts
새로운 디자인 토큰 모듈 추가: colors(계층적 색상 그룹), typography(제목/본문/버튼 타이포그래피), theme(통합 테마 객체 및 Type 정의)
색상 매핑 상수
frontend/src/styles/clubTags.ts
TAG_COLORS(클럽 태그명 → 색상) 및 STATUS_COLORS(모집 상태 → 색상) 매핑 상수 추가
앱 테마 적용
frontend/src/App.tsx
ThemeProvider를 최상위 래퍼로 추가하여 Router를 감싸고 전역 테마 제공
컴포넌트 테마 통합
frontend/src/components/ClubStateBox/ClubStateBox.tsx, frontend/src/components/ClubTag/ClubTag.tsx
로컬 인라인 스타일 로직을 제거하고 STATUS_COLORS 및 TAG_COLORS 임포트로 교체; StyledBox props 단순화
SelectTags 컴포넌트 리팩토링
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx, frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.ts
TagOption 인터페이스(value, label, color) 도입; string\[\] → TagOption\[\]로 변경; 버튼 스타일에 색상 prop 추가
ClubInfoEditTab 데이터 구조 업데이트
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
DIVISION_LABELS 매핑 추가; divisions/categories를 문자열 배열에서 value/label/color 객체 배열로 리팩토링

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • theme 모듈 검토: 새로운 colors, typography, index 파일들의 구조 및 토큰 정의 일관성 확인
  • 색상 매핑 검토: TAG_COLORS, STATUS_COLORS의 키 값 및 테마 색상 참조 정확성 검증
  • SelectTags 인터페이스 변경: TagOption 도입으로 인한 타입 안정성 및 하위 호환성 확인
  • 컴포넌트 props 변경: ClubStateBox, ClubTag, SelectTags의 props 수정이 사용처에서 올바르게 전달되는지 검토
  • ThemeProvider 통합: App.tsx의 래퍼 구조가 기존 라우팅 및 컴포넌트 렌더링에 영향을 주지 않는지 확인

Possibly related issues

Possibly related PRs

Suggested reviewers

  • seongwon030
  • lepitaaar
  • Zepelown
  • suhyun113

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 '디자인 시스템 기반 공통 스타일 구조 정리 및 토큰화'로 변경 사항의 핵심을 명확히 나타냅니다.
Linked Issues check ✅ Passed PR의 모든 주요 변경사항이 MOA-431의 목표와 체크리스트 항목을 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 디자인 시스템 토큰화 목표 범위 내에 있으며, 불필요한 변경은 없습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 refactor/#943-design-system-style-tokens-MOA-431

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
frontend/src/components/ClubTag/ClubTag.tsx (2)

30-47: 텍스트 색상을 테마 토큰으로 교체하세요.

Line 39에서 하드코딩된 색상 '#3a3a3a'를 사용하고 있습니다. 디자인 시스템 일관성을 위해 테마의 gray[900]을 사용해야 합니다.

🔎 제안하는 수정
 const StyledTag = styled.span<{ color: string }>`
   display: flex;
   align-items: center;
   padding: ${TAG_STYLES.desktop.padding};
   height: 28px;
   border-radius: ${TAG_STYLES.desktop.borderRadius};
   background-color: ${({ color }) => color};
   font-size: ${TAG_FONT_SIZE.desktop.fontSize};
   font-weight: 600;
-  color: #3a3a3a;
+  color: ${({ theme }) => theme.colors.gray[900]};
 
   @media (max-width: 500px) {
     height: 25px;
     font-size: ${TAG_FONT_SIZE.mobile.fontSize};
     padding: ${TAG_STYLES.mobile.padding};
     border-radius: ${TAG_STYLES.mobile.borderRadius};
   }
 `;

50-58: 폴백 색상을 테마 토큰으로 교체하세요.

Line 51에서 알 수 없는 태그 타입에 대한 폴백으로 하드코딩된 'rgba(237, 237, 237, 1)'을 사용하고 있습니다. 테마의 회색 톤을 사용해야 합니다.

🔎 제안하는 수정
+import { useTheme } from 'styled-components';
+
 const ClubTag = ({ type, children, className }: TagProps) => {
+  const theme = useTheme();
-  const backgroundColor = TAG_COLORS[type] || 'rgba(237, 237, 237, 1)';
+  const backgroundColor = TAG_COLORS[type] || theme.colors.gray[200];
   return (
     <StyledTag
       color={backgroundColor}
       className={className}
     >{`#${children || type}`}</StyledTag>
   );
 };
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.ts (1)

8-25: 하드코딩된 색상 값들을 테마 토큰으로 교체하세요.

Lines 17-18, 23에 하드코딩된 색상 값들이 있습니다. 디자인 시스템의 일관성을 위해 theme 객체의 색상을 사용해야 합니다.

🔎 제안하는 수정
 export const Button = styled.button<ButtonProps>`
   font-size: 0.875rem;
   padding: 5px 8px;
   border-radius: 4px;
   border: none;
   transition: all 0.1s;
   font-weight: 600;
   cursor: pointer;
   background-color: ${(props) =>
-    props.selected ? props.color || '#FF5414' : 'rgba(0, 0, 0, 0.05)'};
-  color: ${(props) => (props.selected ? '#3a3a3a' : '#4B4B4B')};
+    props.selected ? props.color || props.theme.colors.primary[900] : props.theme.colors.gray[100]};
+  color: ${(props) => (props.selected ? props.theme.colors.gray[900] : props.theme.colors.gray[800])};
 
   &:hover {
     opacity: ${(props) => (props.selected ? 0.9 : 1)};
     background-color: ${(props) =>
-      props.selected ? props.color || '#ea580c' : '#d1d5db'};
+      props.selected ? props.color || props.theme.colors.primary[800] : props.theme.colors.gray[400]};
   }
 `;

참고: 'rgba(0, 0, 0, 0.05)'gray[100]로, '#d1d5db'gray[400]로, hover시 '#ea580c'primary[800]로 매핑했습니다.

🧹 Nitpick comments (3)
frontend/src/styles/clubTags.ts (1)

4-14: 중동/과동/자유 색상을 테마 토큰으로 이동하는 것을 권장합니다.

TAG_COLORS의 일부 항목(Lines 5-7: 중동, 과동, 자유)은 하드코딩된 rgba 값을 사용하는 반면, 나머지는 colors.secondary[x].tag를 사용하여 일관성이 부족합니다.

🔎 모든 색상을 테마 토큰으로 통일하는 제안

frontend/src/styles/theme/colors.ts에 division 섹션을 추가:

+  // Division Color : 동아리 구분 색상
+  division: {
+    중동: 'rgba(230, 247, 255, 1)',
+    과동: 'rgba(210, 230, 255, 1)',
+    자유: 'rgba(237, 237, 237, 0.8)',
+  },

그런 다음 frontend/src/styles/clubTags.ts에서:

 export const TAG_COLORS: Record<string, string> = {
-  중동: 'rgba(230, 247, 255, 1)',
-  과동: 'rgba(210, 230, 255, 1)',
-  자유: 'rgba(237, 237, 237, 0.8)',
+  중동: colors.division.중동,
+  과동: colors.division.과동,
+  자유: colors.division.자유,
   봉사: colors.secondary[1].tag,
   // ... rest
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (1)

51-70: 태그 옵션 구조가 TAG_COLORS와 잘 통합되었습니다.

divisions와 categories 배열이 SelectTags 컴포넌트의 새로운 TagOption 인터페이스와 잘 맞물립니다.

선택 사항: categories 구조 간소화 고려

categories의 경우 labelvalue와 동일하므로, 향후 유지보수를 위해 다음과 같이 간소화할 수 있습니다:

const categoryValues = ['봉사', '종교', '취미교양', '학술', '운동', '공연'] as const;
const categories = categoryValues.map(cat => ({
  value: cat,
  label: cat,
  color: TAG_COLORS[cat],
}));

단, 현재 구조도 명확하므로 이는 선택적 개선사항입니다.

frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx (1)

27-27: 권장 리팩토링: 배열 인덱스 대신 안정적인 key를 사용하세요.

현재 key={index}를 사용하고 있는데, 이는 태그 목록이 재정렬되거나 필터링될 경우 React의 재조정(reconciliation) 알고리즘이 비효율적으로 동작할 수 있습니다. tag.value가 고유한 식별자이므로 이를 key로 사용하는 것이 더 안정적입니다.

🔎 수정 제안
 {tags.map((tag, index) => (
   <Styled.Button
-    key={index}
+    key={tag.value}
     onClick={() => {
       trackEvent(ADMIN_EVENT.CLUB_TAG_SELECT_BUTTON_CLICKED, {
         tagName: tag.value,
📜 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 4778611 and 63c909b.

📒 Files selected for processing (10)
  • frontend/src/App.tsx (2 hunks)
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx (3 hunks)
  • frontend/src/components/ClubTag/ClubTag.tsx (2 hunks)
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (2 hunks)
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.ts (2 hunks)
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx (2 hunks)
  • frontend/src/styles/clubTags.ts (1 hunks)
  • frontend/src/styles/theme/colors.ts (1 hunks)
  • frontend/src/styles/theme/index.ts (1 hunks)
  • frontend/src/styles/theme/typography.ts (1 hunks)
🧰 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/styles/clubTags.ts
  • frontend/src/styles/theme/typography.ts
  • frontend/src/App.tsx
  • frontend/src/styles/theme/index.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx
  • frontend/src/styles/theme/colors.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/components/ClubTag/ClubTag.tsx
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/styles/clubTags.ts
  • frontend/src/styles/theme/typography.ts
  • frontend/src/App.tsx
  • frontend/src/styles/theme/index.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx
  • frontend/src/styles/theme/colors.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/components/ClubTag/ClubTag.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/App.tsx
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/components/ClubTag/ClubTag.tsx
🧠 Learnings (8)
📚 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/**/*.{ts,tsx,js,jsx} : Replace magic numbers with named constants for clarity

Applied to files:

  • frontend/src/styles/clubTags.ts
  • frontend/src/styles/theme/typography.ts
  • frontend/src/App.tsx
  • frontend/src/styles/theme/index.ts
  • frontend/src/styles/theme/colors.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/components/ClubTag/ClubTag.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/**/*.{ts,tsx,js,jsx} : Define constants near related logic or ensure names link them clearly to avoid silent failures

Applied to files:

  • frontend/src/styles/clubTags.ts
  • frontend/src/styles/theme/typography.ts
  • frontend/src/styles/theme/index.ts
  • frontend/src/styles/theme/colors.ts
📚 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/styles/clubTags.ts
  • frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.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} : Abstract complex logic/interactions into dedicated components/HOCs

Applied to files:

  • frontend/src/App.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/**/*.{ts,tsx,js,jsx} : Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Applied to files:

  • frontend/src/App.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.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/App.tsx
  • frontend/src/components/ClubTag/ClubTag.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/App.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
📚 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/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
🧬 Code graph analysis (4)
frontend/src/styles/clubTags.ts (1)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/App.tsx (2)
frontend/src/styles/theme/index.ts (1)
  • theme (4-7)
frontend/src/context/AdminClubContext.tsx (1)
  • AdminClubProvider (15-37)
frontend/src/components/ClubStateBox/ClubStateBox.tsx (2)
frontend/src/styles/theme/index.ts (1)
  • theme (4-7)
frontend/src/styles/clubTags.ts (1)
  • STATUS_COLORS (17-21)
frontend/src/components/ClubTag/ClubTag.tsx (1)
frontend/src/styles/clubTags.ts (1)
  • TAG_COLORS (4-14)
🔇 Additional comments (8)
frontend/src/styles/theme/index.ts (1)

1-9: 테마 구조가 잘 구성되었습니다.

색상과 타이포그래피 토큰을 단일 theme 객체로 통합하고 TypeScript 타입을 제공하는 구조가 명확하고 확장 가능합니다. as const를 사용하여 불변성을 보장한 점도 좋습니다.

frontend/src/App.tsx (1)

14-15: ThemeProvider 통합이 올바르게 구현되었습니다.

전역 테마를 적용하기 위해 ThemeProvider로 라우터 트리를 감싼 구조가 적절하며, QueryClientProvider 하위에 배치된 점도 좋습니다.

Also applies to: 25-26, 66-66

frontend/src/components/ClubStateBox/ClubStateBox.tsx (1)

4-8: 상태 텍스트 매핑이 명확하게 정의되었습니다.

STATE_TEXT를 통해 상태 코드를 한국어로 변환하는 로직이 명확하고 유지보수하기 쉽습니다.

frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (1)

19-22: DIVISION_LABELS를 통한 레이블 분리가 잘 구성되었습니다.

동아리 구분 레이블을 별도 상수로 정의하여 유지보수성과 명확성을 높였습니다.

frontend/src/styles/theme/colors.ts (1)

1-81: 색상 토큰 시스템이 체계적으로 잘 구성되었습니다.

Primary, Secondary, Accent, Base, Neutral(Gray)로 명확하게 구분된 색상 팔레트가 디자인 시스템의 견고한 기반을 제공합니다. 각 섹션에 대한 주석과 as const를 통한 타입 안전성 확보도 우수합니다.

frontend/src/styles/theme/typography.ts (1)

5-6: 검증 요청: title3와 title4가 동일한 값을 가지고 있습니다.

title3title4가 모두 { size: '22px', weight: 'Bold', letterSpacing: '-2%' }로 동일한 값을 가지고 있습니다. 디자인 시스템 명세에서 의도적으로 동일한 스타일을 부여한 것인지, 아니면 실수인지 확인이 필요합니다.

만약 실제로 다른 용도로 사용되지만 현재 스타일이 동일한 것이라면 문제없으나, 불필요한 중복이라면 하나로 통합하는 것을 고려해보세요.

frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx (2)

5-9: 잘 설계된 인터페이스입니다.

TagOption 인터페이스가 명확하게 정의되어 있으며, value(로직용), label(표시용), color(스타일용)를 분리한 구조가 확장성과 유지보수성 측면에서 우수합니다. 기존의 단순 문자열 배열에서 객체 기반 구조로의 전환이 디자인 시스템 토큰화 목표에 잘 부합합니다.


25-40: 리팩토링이 잘 수행되었습니다.

태그 데이터 구조를 string[]에서 TagOption[]으로 변경한 리팩토링이 올바르게 적용되었습니다:

  • 이벤트 트래킹과 onChange에서 tag.value 사용
  • UI 표시에 tag.label 사용
  • 스타일링에 tag.color 전달
  • 선택 상태 비교 로직도 tag.value 기반으로 정확히 처리

이러한 변경으로 향후 태그별로 다른 색상 토큰을 적용할 수 있는 확장성이 확보되었습니다.

Copy link
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

@oesnuj oesnuj merged commit 03451ae into develop-fe Dec 21, 2025
3 checks passed
@oesnuj oesnuj deleted the refactor/#943-design-system-style-tokens-MOA-431 branch January 25, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎨 Design 마크업 & 스타일링 💻 FE Frontend 🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments