11 KiB
shadcn/ui 적용 상태 분석 보고서
작성일: 2025-01-27
기준: shadcn/ui 공식 문서 (https://ui.shadcn.com)
📋 목차
개요
이 보고서는 프로젝트 전반에 걸쳐 shadcn/ui 공식 문서 기준을 얼마나 잘 준수하고 있는지 분석한 결과입니다.
분석 범위:
- 설정 파일 (components.json, globals.css, tailwind.config)
- UI 컴포넌트 (
frontend/components/ui/) - 비즈니스 컴포넌트 (
frontend/components/,frontend/lib/registry/) - 스타일 가이드 준수 여부
적용 상태 요약
✅ 잘 적용된 부분 (70%)
-
기본 설정
components.json설정 올바름- CSS 변수 시스템 정상 작동
cn()유틸리티 함수 사용
-
기본 UI 컴포넌트
- Button, Card, Input 등 기본 컴포넌트는 shadcn 표준 따름
- 다크모드 지원 구조 정상
⚠️ 개선이 필요한 부분 (30%)
-
하드코딩된 색상 사용 (약 2,000+ 건)
bg-blue-500,bg-gray-50,text-red-500등 직접 색상 사용#ffffff,#f9fafb등 인라인 스타일 색상
-
비표준 스타일 패턴
border-blue-500,ring-blue-100등 직접 색상 사용focus:border-orange-500등 커스텀 포커스 색상
-
중첩 박스 문제
- 일부 컴포넌트에서 불필요한 중첩 구조 발견
양호한 부분
1. 기본 설정 ✅
components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"baseColor": "neutral",
"cssVariables": true
}
}
✅ shadcn 공식 설정과 일치
globals.css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
/* ... */
}
✅ HSL 형식, 공식 기본값 사용
2. 기본 UI 컴포넌트 ✅
Button 컴포넌트 (frontend/components/ui/button.tsx)
const buttonVariants = cva("inline-flex items-center justify-center ...", {
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-white ...",
// ...
},
},
});
✅ shadcn 공식 패턴 준수
Card 컴포넌트 (frontend/components/ui/card.tsx)
function Card({ className, ...props }) {
return (
<div className={cn("bg-card text-card-foreground rounded-xl border ...")} />
);
}
✅ CSS 변수 사용, 표준 구조
Input 컴포넌트 (frontend/components/ui/input.tsx)
className={cn(
"border-input bg-transparent ...",
"focus-visible:border-ring focus-visible:ring-ring/50 ...",
className
)}
✅ 시맨틱 색상 사용
3. 유틸리티 함수 ✅
lib/utils.ts
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
✅ 공식 구현과 동일
개선이 필요한 부분
1. 하드코딩된 색상 사용 ❌
문제점
직접 색상 클래스 사용 (약 1,600+ 건)
// ❌ 잘못된 예시
<div className="bg-blue-500 text-white">버튼</div>
<div className="bg-gray-50 text-gray-700">카드</div>
<span className="text-red-500">에러</span>
인라인 스타일 색상 (약 354건)
// ❌ 잘못된 예시
<div style={{ backgroundColor: "#ffffff" }}>
<div style={{ backgroundColor: "#f9fafb" }}>
<div style={{ color: "#64748b" }}>
올바른 패턴
// ✅ 올바른 예시
<div className="bg-primary text-primary-foreground">버튼</div>
<div className="bg-muted text-muted-foreground">카드</div>
<span className="text-destructive">에러</span>
2. 비표준 포커스 스타일 ❌
문제점
직접 색상 사용
// ❌ 잘못된 예시 (TextInputComponent.tsx)
className={`
${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"}
focus:border-orange-500 focus:ring-2 focus:ring-orange-100
`}
올바른 패턴
// ✅ 올바른 예시
className={cn(
"border-input",
isSelected && "border-ring ring-2 ring-ring/50",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-2"
)}
3. 불필요한 인라인 스타일 ❌
문제점
하드코딩된 색상 값
// ❌ 잘못된 예시 (TableListComponent.tsx)
style={{
backgroundColor: "#ffffff",
color: "#374151",
fontSize: "14px"
}}
올바른 패턴
// ✅ 올바른 예시
className={cn(
"bg-background text-foreground",
"text-sm"
)}
4. 중첩 박스 문제 ⚠️
일부 컴포넌트에서 발견
// ⚠️ 중첩된 구조 (CardLayoutRenderer.tsx)
<Card>
<CardContent>
<div className="border rounded-lg p-4">
{" "}
{/* 중첩된 박스 */}
내용
</div>
</CardContent>
</Card>
권장 구조
// ✅ 단일 레벨
<Card>
<CardContent>내용</CardContent>
</Card>
우선순위별 개선 사항
🔴 Priority 1: 핵심 컴포넌트 수정 (즉시)
대상 파일:
-
frontend/lib/registry/components/text-input/TextInputComponent.tsx- 하드코딩된 색상:
border-blue-500,ring-blue-100,border-gray-300,bg-gray-100,focus:border-orange-500 - 개선: CSS 변수 사용
- 하드코딩된 색상:
-
frontend/lib/registry/components/date-input/DateInputComponent.tsx- 동일한 문제 패턴
-
frontend/lib/registry/components/table-list/TableListComponent.tsx- 인라인 스타일 색상:
#ffffff,#374151,#64748b
- 인라인 스타일 색상:
🟡 Priority 2: 페이지 레벨 수정 (단기)
대상 파일:
-
frontend/app/(main)/dashboard/page.tsxbg-blue-500,text-white,bg-gray-50,text-gray-900등
-
frontend/app/(main)/dashboard/[dashboardId]/page.tsx- 동일한 패턴
-
frontend/components/screen/InteractiveScreenViewer.tsxbg-gray-50,text-gray-700등
🟢 Priority 3: 위젯/차트 컴포넌트 (중기)
대상 파일:
-
frontend/components/dashboard/widgets/*.tsx- 위젯별 커스텀 색상이 필요할 수 있으나, 가능한 한 CSS 변수 사용
-
frontend/components/admin/dashboard/widgets/*.tsx- 동일
⚪ Priority 4: 기타 (장기)
대상 파일:
- 나머지 모든 파일에서 하드코딩된 색상 점진적 교체
구체적인 수정 필요 파일
📁 핵심 컴포넌트 (즉시 수정 필요)
1. TextInputComponent.tsx
문제:
border-blue-500,ring-blue-100,border-gray-300,bg-gray-100,text-gray-400,focus:border-orange-500- 총 8곳에서 비표준 색상 사용
수정 예시:
// Before
className={`... ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ...`}
// After
className={cn(
"border-input",
isSelected && "border-ring ring-2 ring-ring/50",
"focus-visible:border-ring focus-visible:ring-ring/50"
)}
2. DateInputComponent.tsx
문제:
- TextInputComponent와 동일한 패턴
3. TableListComponent.tsx
문제:
- 인라인 스타일:
backgroundColor: "#ffffff",color: "#374151",color: "#64748b" - 하드코딩된 색상 클래스:
bg-gray-50,bg-white
수정 예시:
// Before
style={{ backgroundColor: "#ffffff", color: "#374151" }}
className="bg-gray-50"
// After
className={cn("bg-background text-foreground", "bg-muted")}
📁 페이지 레벨 (단기 수정)
1. dashboard/page.tsx
문제:
bg-blue-500,text-white,hover:bg-blue-600bg-gray-50,text-gray-900,text-gray-600
수정 예시:
// Before
<button className="bg-blue-500 text-white hover:bg-blue-600">
<h1 className="text-gray-900">제목</h1>
// After
<Button>버튼</Button>
<h1 className="text-foreground">제목</h1>
2. screen/InteractiveScreenViewer.tsx
문제:
bg-gray-50,text-gray-700border-green-300,bg-green-50
수정 예시:
// Before
className = "bg-gray-50 text-gray-700";
className = "border-green-300 bg-green-50";
// After
className = "bg-muted text-muted-foreground";
className = "border-success/30 bg-success/10";
📁 위젯 컴포넌트 (커스텀 색상 필요 시)
주의사항:
- 위젯에서 특정 색상이 필요할 때는 CSS 변수로 확장하는 것을 권장
- 예:
--success,--warning,--info등
개선 우선순위 가이드
Phase 1: 핵심 컴포넌트 (1주)
- ✅ TextInputComponent.tsx
- ✅ DateInputComponent.tsx
- ✅ TableListComponent.tsx
Phase 2: 주요 페이지 (2주)
- ✅ Dashboard 페이지들
- ✅ Screen 페이지들
- ✅ Admin 페이지들
Phase 3: 위젯/차트 (3주)
- ✅ Dashboard 위젯들
- ✅ 차트 컴포넌트들
- ✅ 3D 위젯들
Phase 4: 전체 정리 (장기)
- ✅ 나머지 모든 파일 점진적 교체
- ✅ 린터 규칙 추가 (하드코딩 색상 금지)
- ✅ 코드 리뷰 가이드라인 업데이트
개선 효과
예상 효과
-
일관성 향상
- 모든 컴포넌트가 동일한 색상 시스템 사용
- 다크모드 전환 시 자동 대응
-
유지보수성 향상
- 색상 변경 시 CSS 변수만 수정하면 전체 반영
- 테마 커스터마이징 용이
-
접근성 향상
- 시맨틱 색상 사용으로 의미 전달 명확
- 다크모드 지원 자동화
-
코드 품질 향상
- 하드코딩 제거로 코드 간결화
- shadcn 공식 문서 준수
체크리스트
기본 설정
- components.json 설정 올바름
- globals.css CSS 변수 설정 완료
- cn() 유틸리티 함수 존재
- 기본 UI 컴포넌트 shadcn 표준 준수
색상 시스템
- 하드코딩된 색상 제거 (2,000+ 건)
- 인라인 스타일 색상 제거 (354건)
- CSS 변수 사용으로 전환
- 다크모드 색상 테스트
컴포넌트 패턴
- 표준 Button variant 사용
- 표준 Input 스타일 사용
- 표준 Card 구조 사용
- 중첩 박스 문제 해결
문서화
- 스타일 가이드 업데이트
- 코드 리뷰 체크리스트 추가
- 린터 규칙 추가
결론
현재 상태:
- ✅ 기본 설정과 핵심 UI 컴포넌트는 shadcn 표준을 잘 따르고 있음
- ⚠️ 비즈니스 컴포넌트에서 하드코딩된 색상 사용이 많음
- ⚠️ 일부 컴포넌트에서 비표준 스타일 패턴 사용
권장 사항:
- 즉시 조치: 핵심 컴포넌트 (TextInput, DateInput, TableList) 색상 통일
- 단기 조치: 주요 페이지 레벨 색상 교체
- 중기 조치: 위젯/차트 컴포넌트 점진적 개선
- 장기 조치: 린터 규칙 추가 및 코드 리뷰 가이드라인 업데이트
목표:
- 모든 컴포넌트에서 하드코딩된 색상 제거
- CSS 변수 기반 색상 시스템 완전 적용
- shadcn/ui 공식 문서 100% 준수