ERP-node/docs/ADMIN_STYLE_GUIDE_EXAMPLE.md

436 lines
11 KiB
Markdown
Raw Permalink Normal View History

2025-10-22 14:52:13 +09:00
# 관리자 페이지 스타일 가이드 적용 예시
## 개요
사용자 관리 페이지를 예시로 shadcn/ui 스타일 가이드에 맞춰 재작성했습니다.
이 예시를 기준으로 다른 관리자 페이지들도 일관된 스타일로 통일할 수 있습니다.
## 적용된 주요 원칙
### 1. Color System (색상 시스템)
**CSS Variables 사용 (하드코딩된 색상 금지)**
```tsx
// ❌ 잘못된 예시
<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 (타이포그래피)
**일관된 폰트 크기와 가중치**
```tsx
// 페이지 제목
<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 기준)**
```tsx
// 컴포넌트 간 간격
<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 사용**
```tsx
// 카드/패널
<div className="rounded-lg border bg-card">
// 입력 필드
<Input className="rounded-md">
// 버튼
<Button className="rounded-md">
```
### 5. Button Variants (버튼 스타일)
**표준 variants 사용**
```tsx
// 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 스타일**
```tsx
// 기본
<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 (폼 구조)
**표준 필드 구조**
```tsx
<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 (테이블 구조)
**표준 테이블 스타일**
```tsx
<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**
```tsx
<div className="h-4 animate-pulse rounded bg-muted"></div>
```
### 10. Empty States (빈 상태)
**표준 Empty State**
```tsx
<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 (에러 상태)
**표준 에러 메시지**
```tsx
<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 (반응형)
**모바일 우선 접근**
```tsx
// 레이아웃
<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 (접근성)
**필수 적용 사항**
```tsx
// 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
```tsx
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
```tsx
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. **린트 에러 확인**
```bash
# 수정한 파일들 확인
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: 각 스타일 요소별 상세 가이드