ERP-node/docs/ADMIN_STYLE_GUIDE_EXAMPLE.md

11 KiB

관리자 페이지 스타일 가이드 적용 예시

개요

사용자 관리 페이지를 예시로 shadcn/ui 스타일 가이드에 맞춰 재작성했습니다. 이 예시를 기준으로 다른 관리자 페이지들도 일관된 스타일로 통일할 수 있습니다.

적용된 주요 원칙

1. Color System (색상 시스템)

CSS Variables 사용 (하드코딩된 색상 금지)

// ❌ 잘못된 예시
<div className="bg-gray-50 text-gray-900">

// ✅ 올바른 예시
<div className="bg-background text-foreground">
<div className="bg-card text-card-foreground">
<div className="bg-muted text-muted-foreground">
<div className="text-primary">
<div className="text-destructive">

적용 사례:

  • 페이지 배경: bg-background
  • 카드 배경: bg-card
  • 보조 텍스트: text-muted-foreground
  • 주요 액션: text-primary, border-primary
  • 에러 메시지: text-destructive, bg-destructive/10

2. Typography (타이포그래피)

일관된 폰트 크기와 가중치

// 페이지 제목
<h1 className="text-3xl font-bold tracking-tight">사용자 관리</h1>

// 섹션 제목
<h4 className="text-sm font-semibold">고급 검색 옵션</h4>

// 본문 텍스트
<p className="text-sm text-muted-foreground">설명 텍스트</p>

// 라벨
<label className="text-sm font-medium">필드 라벨</label>

// 보조 텍스트
<p className="text-xs text-muted-foreground">도움말</p>

3. Spacing System (간격)

일관된 간격 사용 (4px 기준)

// 컴포넌트 간 간격
<div className="space-y-6">          // 24px (페이지 레벨)
<div className="space-y-4">          // 16px (섹션 레벨)
<div className="space-y-2">          // 8px (필드 레벨)

// 패딩
<div className="p-6">                // 24px (카드)
<div className="p-4">                // 16px (내부 섹션)

// 갭
<div className="gap-4">              // 16px (flex/grid)
<div className="gap-2">              // 8px (버튼 그룹)

4. Border & Radius (테두리 및 둥근 모서리)

표준 radius 사용

// 카드/패널
<div className="rounded-lg border bg-card">

// 입력 필드
<Input className="rounded-md">

// 버튼
<Button className="rounded-md">

5. Button Variants (버튼 스타일)

표준 variants 사용

// Primary 액션
<Button variant="default" size="default" className="h-10 gap-2 text-sm font-medium">
  <Plus className="h-4 w-4" />
  사용자 등록
</Button>

// Secondary 액션
<Button variant="outline" size="default" className="h-10 gap-2 text-sm font-medium">
  고급 검색
</Button>

// Ghost 버튼 (아이콘 전용)
<Button variant="ghost" size="icon" className="h-8 w-8">
  <Key className="h-4 w-4" />
</Button>

크기 표준:

  • h-10: 기본 버튼 (40px)
  • h-9: 작은 버튼 (36px)
  • h-8: 아이콘 버튼 (32px)

6. Input States (입력 필드 상태)

표준 Input 스타일

// 기본
<Input className="h-10 text-sm" />

// 포커스 (자동 적용)
// focus:ring-2 focus:ring-ring

// 로딩/액티브
<Input className="h-10 text-sm border-primary ring-2 ring-primary/20" />

// 비활성화
<Input disabled className="cursor-not-allowed bg-muted text-muted-foreground" />

7. Form Structure (폼 구조)

표준 필드 구조

<div className="space-y-2">
  <label htmlFor="field-id" className="text-sm font-medium">
    필드 라벨
  </label>
  <Input
    id="field-id"
    placeholder="힌트 텍스트"
    className="h-10 text-sm"
  />
  <p className="text-xs text-muted-foreground">
    도움말 텍스트
  </p>
</div>

8. Table Structure (테이블 구조)

표준 테이블 스타일

<div className="rounded-lg border bg-card shadow-sm">
  <Table>
    <TableHeader>
      <TableRow className="border-b bg-muted/50 hover:bg-muted/50">
        <TableHead className="h-12 text-sm font-semibold">
          컬럼명
        </TableHead>
      </TableRow>
    </TableHeader>
    <TableBody>
      <TableRow className="border-b transition-colors hover:bg-muted/50">
        <TableCell className="h-16 text-sm">
          데이터
        </TableCell>
      </TableRow>
    </TableBody>
  </Table>
</div>

높이 표준:

  • 헤더: h-12 (48px)
  • 데이터 행: h-16 (64px)

9. Loading States (로딩 상태)

Skeleton UI

<div className="h-4 animate-pulse rounded bg-muted"></div>

10. Empty States (빈 상태)

표준 Empty State

<TableCell colSpan={columns} className="h-32 text-center">
  <div className="flex flex-col items-center justify-center gap-2 text-muted-foreground">
    <p className="text-sm">등록된 데이터가 없습니다.</p>
  </div>
</TableCell>

11. Error States (에러 상태)

표준 에러 메시지

<div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4">
  <div className="flex items-center justify-between">
    <p className="text-sm font-semibold text-destructive">오류가 발생했습니다</p>
    <button
      onClick={clearError}
      className="text-destructive transition-colors hover:text-destructive/80"
      aria-label="에러 메시지 닫기"
    >
      
    </button>
  </div>
  <p className="mt-1.5 text-sm text-destructive/80">{errorMessage}</p>
</div>

12. Responsive Design (반응형)

모바일 우선 접근

// 레이아웃
<div className="flex flex-col gap-4 sm:flex-row sm:items-center">

// 그리드
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">

// 텍스트
<h1 className="text-2xl sm:text-3xl font-bold">

// 간격
<div className="p-4 sm:p-6">

13. Accessibility (접근성)

필수 적용 사항

// Label과 Input 연결
<label htmlFor="user-id" className="text-sm font-medium">
  사용자 ID
</label>
<Input id="user-id" />

// 버튼에 aria-label
<Button aria-label="에러 메시지 닫기">
  
</Button>

// Switch에 aria-label
<Switch
  checked={isActive}
  onCheckedChange={handleChange}
  aria-label="사용자 상태 토글"
/>

페이지 구조 템플릿

Page Component

export default function AdminPage() {
  return (
    <div className="flex min-h-screen flex-col bg-background">
      <div className="container mx-auto space-y-6 p-6">
        {/* 페이지 헤더 */}
        <div className="space-y-2 border-b pb-4">
          <h1 className="text-3xl font-bold tracking-tight">페이지 제목</h1>
          <p className="text-sm text-muted-foreground">페이지 설명</p>
        </div>

        {/* 메인 컨텐츠 */}
        <MainComponent />
      </div>
    </div>
  );
}

Toolbar Component

export function Toolbar() {
  return (
    <div className="space-y-4">
      {/* 검색 영역 */}
      <div className="rounded-lg border bg-card p-4">
        <div className="mb-4 flex flex-col gap-4 sm:flex-row sm:items-center">
          {/* 검색 입력 */}
          <div className="flex-1">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input placeholder="검색..." className="h-10 pl-10 text-sm" />
            </div>
          </div>
          
          {/* 버튼 */}
          <Button variant="outline" className="h-10 gap-2 text-sm font-medium">
            고급 검색
          </Button>
        </div>
      </div>

      {/* 액션 버튼 영역 */}
      <div className="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
        <div className="text-sm text-muted-foreground">
           <span className="font-semibold text-foreground">{count.toLocaleString()}</span> 
        </div>
        
        <Button className="h-10 gap-2 text-sm font-medium">
          <Plus className="h-4 w-4" />
          등록
        </Button>
      </div>
    </div>
  );
}

적용해야 할 다른 관리자 페이지

우선순위 1 (핵심 페이지)

  • 메뉴 관리 (/admin/menu)
  • 공통코드 관리 (/admin/commonCode)
  • 회사 관리 (/admin/company)
  • 테이블 관리 (/admin/tableMng)

우선순위 2 (자주 사용하는 페이지)

  • 외부 연결 관리 (/admin/external-connections)
  • 외부 호출 설정 (/admin/external-call-configs)
  • 배치 관리 (/admin/batch-management)
  • 레이아웃 관리 (/admin/layouts)

우선순위 3 (기타 관리 페이지)

  • 템플릿 관리 (/admin/templates)
  • 표준 관리 (/admin/standards)
  • 다국어 관리 (/admin/i18n)
  • 수집 관리 (/admin/collection-management)

체크리스트

각 페이지 작업 시 다음을 확인하세요:

레이아웃

  • bg-background 사용 (하드코딩된 색상 없음)
  • container mx-auto space-y-6 p-6 구조
  • 페이지 헤더에 border-b pb-4

색상

  • CSS Variables만 사용 (bg-card, text-muted-foreground 등)
  • bg-gray-*, text-gray-* 등 하드코딩 제거

타이포그래피

  • 페이지 제목: text-3xl font-bold tracking-tight
  • 섹션 제목: text-sm font-semibold
  • 본문: text-sm
  • 보조 텍스트: text-xs text-muted-foreground

간격

  • 페이지 레벨: space-y-6
  • 섹션 레벨: space-y-4
  • 필드 레벨: space-y-2
  • 카드 패딩: p-4 또는 p-6

버튼

  • 표준 variants 사용 (default, outline, ghost)
  • 표준 크기: h-10 (기본), h-9 (작음), h-8 (아이콘)
  • 텍스트: text-sm font-medium
  • 아이콘 + 텍스트: gap-2

입력 필드

  • 높이: h-10
  • 텍스트: text-sm
  • Label과 Input htmlFor/id 연결
  • space-y-2 구조

테이블

  • rounded-lg border bg-card shadow-sm
  • 헤더: h-12 text-sm font-semibold bg-muted/50
  • 데이터 행: h-16 text-sm
  • Hover: hover:bg-muted/50

반응형

  • 모바일 우선 디자인
  • sm:, md:, lg: 브레이크포인트 사용
  • flex-col sm:flex-row 패턴

접근성

  • Label htmlFor 속성
  • Input id 속성
  • 버튼 aria-label
  • Switch aria-label

마이그레이션 절차

  1. 페이지 컴포넌트 수정 (page.tsx)

    • 레이아웃 구조 변경
    • 색상 CSS Variables로 변경
    • 페이지 헤더 표준화
  2. Toolbar 컴포넌트 수정

    • 검색 영역 스타일 통일
    • 버튼 스타일 표준화
    • 반응형 레이아웃 적용
  3. Table 컴포넌트 수정

    • 테이블 컨테이너 스타일 통일
    • 헤더/데이터 행 높이 표준화
    • 로딩/Empty State 표준화
  4. Form 컴포넌트 수정 (있는 경우)

    • 필드 구조 표준화
    • 라벨과 입력 필드 연결
    • 에러 메시지 스타일 통일
  5. Modal 컴포넌트 수정 (있는 경우)

    • Dialog 표준 패턴 적용
    • 반응형 크기 (max-w-[95vw] sm:max-w-[500px])
    • 버튼 스타일 표준화
  6. 린트 에러 확인

    # 수정한 파일들 확인
    npm run lint
    
  7. 테스트

    • 기능 동작 확인
    • 반응형 확인 (모바일/태블릿/데스크톱)
    • 다크모드 확인 (있는 경우)

참고 파일

완성된 예시

  • frontend/app/(main)/admin/userMng/page.tsx
  • frontend/components/admin/UserToolbar.tsx
  • frontend/components/admin/UserTable.tsx
  • frontend/components/admin/UserManagement.tsx

스타일 가이드

  • .cursorrules - 전체 스타일 규칙
  • Section 1-21: 각 스타일 요소별 상세 가이드