436 lines
11 KiB
Markdown
436 lines
11 KiB
Markdown
# 관리자 페이지 스타일 가이드 적용 예시
|
|
|
|
## 개요
|
|
|
|
사용자 관리 페이지를 예시로 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: 각 스타일 요소별 상세 가이드
|
|
|