대시보드 디자인
규칙
- 사이드바 + 메인 콘텐츠 레이아웃: 고정 사이드바(w-64), 유동적인 메인 영역에 패딩 적용
- 사이드바 내비게이션: 아이콘 + 레이블 링크, 활성 상태 강조, 모바일에서 접이식
- 상단 KPI 카드 행: 반응형 그리드에 3-4개의 카드 — 메트릭 이름, 값, 추세(증감 %), 스파크라인(선택 사항)
- 데이터 테이블: 정렬 가능한 열, 검색/상태로 필터링, 페이지네이션 (기본 10-25행)
@tanstack/react-table을 헤드리스 테이블 로직에 사용 — shadcn/ui Table 컴포넌트와 함께 사용
- 반응형:
md 중단점에서 사이드바가 햄버거 메뉴로 축소, 카드는 1-2열로 쌓임
- 로딩 상태: 카드/테이블 모양과 일치하는 스켈레톤 플레이스홀더 — 레이아웃 이동 없음
- 대시보드 데이터 필터링을 위한 날짜 범위 선택기 — 기본값 지난 30일
레이아웃 구조
┌──────────┬────────────────────────────┐
│ 사이드바 │ 헤더 / 이동 경로 │
│ ├────────────────────────────┤
│ 내비 │ KPI 카드 (3-4 그리드) │
│ 링크 ├────────────────────────────┤
│ │ 차트 / 그래프 │
│ ├────────────────────────────┤
│ │ 데이터 테이블 │
└──────────┴────────────────────────────┘
패턴
function KPICard({ title, value, change }: { title: string; value: string; change: number }) {
return (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">{title}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{value}</div>
<p className={cn("text-xs", change >= 0 ? "text-green-600" : "text-red-600")}>
{change >= 0 ? "+" : ""}{change}% 이전 기간 대비
</p>
</CardContent>
</Card>
);
}
피해야 할 사항
- 고정 너비 메인 콘텐츠 — 항상 사용 가능한 공간을 채우는 유동 레이아웃 사용
- 페이지네이션이 없는 테이블 — 대규모 데이터셋은 성능과 사용성을 저하시킴
- 로딩/빈 상태 누락 — 항상 스켈레톤이나 "데이터 없음" 메시지 표시
- 축소할 수 없는 사이드바 — 모바일 사용자는 전체 뷰포트 너비가 필요함
- 부분 페이지 업데이트에 로딩 스피너 사용 — 특정 섹션에는 스켈레톤 사용
- 너무 많은 KPI 표시 — 3-5개의 주요 메트릭을 강조하고 나머지는 확장 가능한 섹션에 배치
- 처음부터 사이드바를 커스텀 제작 — shadcn의 사이드바 컴포넌트 사용
- 액션이 없는 빈 상태 — 항상 CTA 포함 ("아직 캠페인이 없습니다. 첫 번째 캠페인을 만들어보세요 →")