11 KiB
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
마이그레이션 절차
-
페이지 컴포넌트 수정 (
page.tsx)- 레이아웃 구조 변경
- 색상 CSS Variables로 변경
- 페이지 헤더 표준화
-
Toolbar 컴포넌트 수정
- 검색 영역 스타일 통일
- 버튼 스타일 표준화
- 반응형 레이아웃 적용
-
Table 컴포넌트 수정
- 테이블 컨테이너 스타일 통일
- 헤더/데이터 행 높이 표준화
- 로딩/Empty State 표준화
-
Form 컴포넌트 수정 (있는 경우)
- 필드 구조 표준화
- 라벨과 입력 필드 연결
- 에러 메시지 스타일 통일
-
Modal 컴포넌트 수정 (있는 경우)
- Dialog 표준 패턴 적용
- 반응형 크기 (
max-w-[95vw] sm:max-w-[500px]) - 버튼 스타일 표준화
-
린트 에러 확인
# 수정한 파일들 확인 npm run lint -
테스트
- 기능 동작 확인
- 반응형 확인 (모바일/태블릿/데스크톱)
- 다크모드 확인 (있는 경우)
참고 파일
완성된 예시
frontend/app/(main)/admin/userMng/page.tsxfrontend/components/admin/UserToolbar.tsxfrontend/components/admin/UserTable.tsxfrontend/components/admin/UserManagement.tsx
스타일 가이드
.cursorrules- 전체 스타일 규칙- Section 1-21: 각 스타일 요소별 상세 가이드