설명
처음 들어온 사용자거나 검색 결과가 0건인 화면, 필터에 다 걸러진 화면, 권한이 없는 화면처럼 비어 있는 영역만 덜렁 보이면 사용자는 보통 화면이 잘못된 줄 알아요. 작은 일러스트나 아이콘과 짧은 한 줄, 다음 액션 버튼 하나만 채워 줘도 사용자가 무엇부터 하면 되는지 빠르게 감을 잡습니다. 검색 결과 0건 화면, 처음 진입한 빈 대시보드, 권한이 없는 화면, 에러로 막힌 화면은 모두 들어가는 카피와 액션이 달라야 해서, 한 컴포넌트로 모든 경우를 덮으려 하면 어떤 화면도 충분히 친절하지 못해요.
🖼️ 미니어처
💬 AI에게 이렇게 말하세요
- 검색 결과 0건일 때 보여줄 Empty State를 만들어 주세요. lucide 아이콘 1개 + 굵은 1줄 카피 + 작은 설명 + '필터 초기화' 버튼.
- 신규 사용자가 처음 들어온 빈 대시보드를 만들어 주세요. 작업 시작 가이드 카드 3개와 '첫 프로젝트 만들기' primary 버튼.
- 같은 EmptyState 컴포넌트가 케이스(no-results / first-time / no-permission / error)에 따라 props로 분기하도록 작성해 주세요.
4가지 케이스
- First-time: 신규 사용자가 처음 들어왔을 때 보여줘요. 가이드 카드와 첫 액션 CTA로 구성합니다.
- No-results: 검색이나 필터 결과가 0건일 때 띄웁니다. 검색어 변경이나 필터 초기화를 제안해요.
- No-permission: 권한이 없을 때 보여줍니다. 권한 요청이나 다른 화면 이동을 제안해요.
- Error-recovery: 데이터 로드에 실패했을 때 띄워요. '다시 시도' 버튼과 지원 채널 링크를 함께 둡니다.
재사용 컴포넌트 골격
type EmptyStateProps = {
icon: LucideIcon
title: string
description?: string
action?: React.ReactNode
}
export function EmptyState({ icon: Icon, title, description, action }: EmptyStateProps) {
return (
<div role="status" aria-live="polite" className="flex flex-col items-center gap-3 py-16 text-center">
<Icon className="h-14 w-14 text-muted-foreground/60" />
<p className="text-base font-semibold">{title}</p>
{description && <p className="text-sm text-muted-foreground">{description}</p>}
{action && <div className="mt-2">{action}</div>}
</div>
)
} ⚡ 사용 예 (한 줄)
<EmptyState icon={SearchX} title="결과가 없어요" description="검색어를 다르게 써 볼까요?" action={<Button>필터 초기화</Button>} /> 🧩 컴포넌트 매핑
자체 <EmptyState /> 컴포넌트를 만드는 방식이 가장 깔끔합니다. shadcn/ui에는 Empty 전용이 없어요. Tremor Empty, NextUI Empty, Mantine Empty가 참고하기 좋아요. 일러스트가 부담스러우면 lucide-react 아이콘과 Tailwind 조합만으로 가볍게 만들면 됩니다.
'데이터가 없습니다' 회색 텍스트만 띄워 두면 사용자에게 다음 행동을 못 알려 줘요. 0건 화면이 여러 곳에 있는데 모두 같은 일러스트와 같은 카피로 채우는 것도 피해 주세요. 화면마다 사용자가 떠올려야 하는 다음 행동이 다르기 때문이에요.
'결과가 없습니다'라고 마침표로 끝내기보다 '검색어를 조금 바꿔서 다시 찾아볼까요?'처럼 다음 행동 동사를 카피에 그대로 적어 주세요. 토스나 당근, 카카오의 Empty State는 일러스트가 작고(56~80px) 한국어 카피도 짧고 친근합니다. 영어권에서 자주 보이는 큰 일러스트와 긴 설명을 그대로 가져오면 한국 사용자에게는 무겁다는 인상을 줘요.
메시지 영역을 <div role="status">로 감싸고 aria-live="polite"를 두면 검색 결과가 바뀔 때 스크린리더가 자동으로 읽어 줘요. 액션 버튼이 있어도 자동 포커스는 검색창에 두는 게 좋습니다. 사용자가 곧바로 검색어를 다시 입력할 수 있어요.