[refactor] 디자인 시스템 기반 공통 스타일 구조 정리 및 토큰화#946
Conversation
- 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) 적용 - 동아리 구분 및 카테고리 태그에 개별 색상 지정
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| 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
- [refactor] MOA-431 디자인 시스템 기반 공통 스타일 구조 정리 및 토큰화 #943: 색상 및 타이포그래피 토큰 중앙화 및 TAG_COLORS, STATUS_COLORS 매핑을 통한 디자인 시스템 통합이 이 이슈의 목표와 직접 일치합니다.
Possibly related PRs
- [feature] 메인페이지 새로운 카드 디자인을 적용한다 #773: ClubStateBox 컴포넌트에 대한 동일 파일 수정으로, 인라인 STATE_COLORS 로직을 테마 기반 STATUS_COLORS로 교체하는 변경이 연관됩니다.
- [fix] 데스크탑, 모바일 카드 디자인을 피그마와 통일한다 #830: ClubStateBox 및 ClubTag 동일 컴포넌트 파일 수정으로 스타일/동작 변경이 관련됩니다.
- [release] v1.1.0 #676: App.tsx의 코드 레벨 수정(라우터 컴포넌트 구조 변경)으로 연관됩니다.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
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, // ... restfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (1)
51-70: 태그 옵션 구조가 TAG_COLORS와 잘 통합되었습니다.divisions와 categories 배열이 SelectTags 컴포넌트의 새로운 TagOption 인터페이스와 잘 맞물립니다.
선택 사항: categories 구조 간소화 고려
categories의 경우
label이value와 동일하므로, 향후 유지보수를 위해 다음과 같이 간소화할 수 있습니다: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.
📒 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 withif/elseor 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.tsfrontend/src/styles/theme/typography.tsfrontend/src/App.tsxfrontend/src/styles/theme/index.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsxfrontend/src/styles/theme/colors.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/components/ClubStateBox/ClubStateBox.tsxfrontend/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.tsfrontend/src/styles/theme/typography.tsfrontend/src/App.tsxfrontend/src/styles/theme/index.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsxfrontend/src/styles/theme/colors.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.styles.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/components/ClubStateBox/ClubStateBox.tsxfrontend/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.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/components/ClubStateBox/ClubStateBox.tsxfrontend/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.tsfrontend/src/styles/theme/typography.tsfrontend/src/App.tsxfrontend/src/styles/theme/index.tsfrontend/src/styles/theme/colors.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/components/ClubStateBox/ClubStateBox.tsxfrontend/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.tsfrontend/src/styles/theme/typography.tsfrontend/src/styles/theme/index.tsfrontend/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.tsfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/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.tsxfrontend/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.tsxfrontend/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.tsxfrontend/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.tsxfrontend/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가 동일한 값을 가지고 있습니다.
title3와title4가 모두{ 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기반으로 정확히 처리이러한 변경으로 향후 태그별로 다른 색상 토큰을 적용할 수 있는 확장성이 확보되었습니다.
#️⃣ 연관된 이슈
📝 작업 요약
이번 PR에서는 디자인 시스템 도입의 초기 단계로, styled-components 기반에서 색상·타이포그래피 토큰을 정의하고 이를 하나의 테마로 통합했습니다.
기존에 하드코딩되어 있던 스타일을 제거하고, ThemeProvider를 통해 전역적으로 일관된 스타일을 사용할 수 있는 환경을 구축했습니다.
🛠 작업 내용
1. 디자인 시스템 기반 구조 구축
색상 토큰 정의
frontend/src/styles/theme/colors.ts타이포그래피 토큰 정의
frontend/src/styles/theme/typography.ts테마 통합
frontend/src/styles/theme/index.ts2. 동아리 관련 색상 상수화
frontend/src/styles/clubTags.ts3. 컴포넌트 리팩토링
ClubTag 컴포넌트
TAG_COLORS상수로 교체theme.colors.gray[900]기준으로 통일ClubStateBox 컴포넌트
STATUS_COLORS상수로 분리#ffffff→theme.colors.base.white사용SelectTags 컴포넌트
string[]→TagOption[]#3a3a3a로 통일하여 가독성 개선4. ThemeProvider 설정
App.tsx에 ThemeProvider 적용({ theme }) => theme.colors.xxx형태 사용💬 논의하고 싶은 부분
🫡 참고 사항