ERP-node/docs/shadcn-ui-적용-상태-분석-보고서.md

11 KiB

shadcn/ui 적용 상태 분석 보고서

작성일: 2025-01-27
기준: shadcn/ui 공식 문서 (https://ui.shadcn.com)

📋 목차

  1. 개요
  2. 적용 상태 요약
  3. 양호한 부분
  4. 개선이 필요한 부분
  5. 우선순위별 개선 사항
  6. 구체적인 수정 필요 파일

개요

이 보고서는 프로젝트 전반에 걸쳐 shadcn/ui 공식 문서 기준을 얼마나 잘 준수하고 있는지 분석한 결과입니다.

분석 범위:

  • 설정 파일 (components.json, globals.css, tailwind.config)
  • UI 컴포넌트 (frontend/components/ui/)
  • 비즈니스 컴포넌트 (frontend/components/, frontend/lib/registry/)
  • 스타일 가이드 준수 여부

적용 상태 요약

잘 적용된 부분 (70%)

  1. 기본 설정

    • components.json 설정 올바름
    • CSS 변수 시스템 정상 작동
    • cn() 유틸리티 함수 사용
  2. 기본 UI 컴포넌트

    • Button, Card, Input 등 기본 컴포넌트는 shadcn 표준 따름
    • 다크모드 지원 구조 정상

⚠️ 개선이 필요한 부분 (30%)

  1. 하드코딩된 색상 사용 (약 2,000+ 건)

    • bg-blue-500, bg-gray-50, text-red-500 등 직접 색상 사용
    • #ffffff, #f9fafb 등 인라인 스타일 색상
  2. 비표준 스타일 패턴

    • border-blue-500, ring-blue-100 등 직접 색상 사용
    • focus:border-orange-500 등 커스텀 포커스 색상
  3. 중첩 박스 문제

    • 일부 컴포넌트에서 불필요한 중첩 구조 발견

양호한 부분

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: 핵심 컴포넌트 수정 (즉시)

대상 파일:

  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 변수 사용
  2. frontend/lib/registry/components/date-input/DateInputComponent.tsx

    • 동일한 문제 패턴
  3. frontend/lib/registry/components/table-list/TableListComponent.tsx

    • 인라인 스타일 색상: #ffffff, #374151, #64748b

🟡 Priority 2: 페이지 레벨 수정 (단기)

대상 파일:

  1. frontend/app/(main)/dashboard/page.tsx

    • bg-blue-500, text-white, bg-gray-50, text-gray-900
  2. frontend/app/(main)/dashboard/[dashboardId]/page.tsx

    • 동일한 패턴
  3. frontend/components/screen/InteractiveScreenViewer.tsx

    • bg-gray-50, text-gray-700

🟢 Priority 3: 위젯/차트 컴포넌트 (중기)

대상 파일:

  1. frontend/components/dashboard/widgets/*.tsx

    • 위젯별 커스텀 색상이 필요할 수 있으나, 가능한 한 CSS 변수 사용
  2. 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-600
  • bg-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-700
  • border-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주)

  1. TextInputComponent.tsx
  2. DateInputComponent.tsx
  3. TableListComponent.tsx

Phase 2: 주요 페이지 (2주)

  1. Dashboard 페이지들
  2. Screen 페이지들
  3. Admin 페이지들

Phase 3: 위젯/차트 (3주)

  1. Dashboard 위젯들
  2. 차트 컴포넌트들
  3. 3D 위젯들

Phase 4: 전체 정리 (장기)

  1. 나머지 모든 파일 점진적 교체
  2. 린터 규칙 추가 (하드코딩 색상 금지)
  3. 코드 리뷰 가이드라인 업데이트

개선 효과

예상 효과

  1. 일관성 향상

    • 모든 컴포넌트가 동일한 색상 시스템 사용
    • 다크모드 전환 시 자동 대응
  2. 유지보수성 향상

    • 색상 변경 시 CSS 변수만 수정하면 전체 반영
    • 테마 커스터마이징 용이
  3. 접근성 향상

    • 시맨틱 색상 사용으로 의미 전달 명확
    • 다크모드 지원 자동화
  4. 코드 품질 향상

    • 하드코딩 제거로 코드 간결화
    • shadcn 공식 문서 준수

체크리스트

기본 설정

  • components.json 설정 올바름
  • globals.css CSS 변수 설정 완료
  • cn() 유틸리티 함수 존재
  • 기본 UI 컴포넌트 shadcn 표준 준수

색상 시스템

  • 하드코딩된 색상 제거 (2,000+ 건)
  • 인라인 스타일 색상 제거 (354건)
  • CSS 변수 사용으로 전환
  • 다크모드 색상 테스트

컴포넌트 패턴

  • 표준 Button variant 사용
  • 표준 Input 스타일 사용
  • 표준 Card 구조 사용
  • 중첩 박스 문제 해결

문서화

  • 스타일 가이드 업데이트
  • 코드 리뷰 체크리스트 추가
  • 린터 규칙 추가

결론

현재 상태:

  • 기본 설정과 핵심 UI 컴포넌트는 shadcn 표준을 잘 따르고 있음
  • ⚠️ 비즈니스 컴포넌트에서 하드코딩된 색상 사용이 많음
  • ⚠️ 일부 컴포넌트에서 비표준 스타일 패턴 사용

권장 사항:

  1. 즉시 조치: 핵심 컴포넌트 (TextInput, DateInput, TableList) 색상 통일
  2. 단기 조치: 주요 페이지 레벨 색상 교체
  3. 중기 조치: 위젯/차트 컴포넌트 점진적 개선
  4. 장기 조치: 린터 규칙 추가 및 코드 리뷰 가이드라인 업데이트

목표:

  • 모든 컴포넌트에서 하드코딩된 색상 제거
  • CSS 변수 기반 색상 시스템 완전 적용
  • shadcn/ui 공식 문서 100% 준수

참고 자료