디자이너가 자주 빠뜨리는 컴포넌트 상태들 — hover부터 skeleton까지 실무 체크리스트
디자이너 동료에게서 받은 컴포넌트 파일을 열었는데 버튼이 딱 하나예요. 기본(Default) 상태 하나. 개발자가 "hover는요? disabled는요? 로딩 중엔 어떻게 보여요?" 물어보면 "아 그건 알아서 해주세요~"가 돌아오는 그 상황. 😅 반대로 디자이너 입장에서도 억울해요. 솔직히 처음에 뭘 챙겨야 하는지 아무도 알려주지 않았거든요.
이 글은 디자이너를 탓하려는 게 아니에요. 실무에서 정말 자주 누락되는 상태들이 있고, 그게 빠졌을 때 개발 과정에서 어떤 일이 일어나는지, 그리고 앞으로 어떤 기준으로 체크하면 되는지를 같이 정리해 보려고 해요. 이 글 한 번만 읽으면 "디자인엔 없는데요?"라는 말을 훨씬 덜 들을 수 있을 거예요!
왜 상태(State)가 이렇게 중요한가요? 🤔
UI 컴포넌트는 언제나 딱 한 가지 모습만 가지지 않아요. 같은 버튼이라도 사용자가 마우스를 올리는 순간, 클릭하는 순간, 비활성화된 순간, 로딩 중인 순간에 모두 다르게 보여야 해요. 이 각각의 모습이 바로 "상태(State)"예요.
상태 디자인이 누락됐을 때 벌어지는 일은 크게 세 가지예요. 첫째, 개발자가 임의로 스타일을 만들어 넣어요. 그 결과는 브랜드 가이드와 전혀 다른 UI가 될 수 있어요. 둘째, 개발자가 기획자나 디자이너에게 다시 확인을 요청하면서 피드백 루프가 길어지고 일정이 지연돼요. 셋째, 그냥 아무 처리도 안 한 채로 배포됐다가 사용자가 이상한 화면을 만나는 최악의 상황이 오기도 해요.
컴포넌트 하나를 완성도 있게 디자인한다는 건 "이 컴포넌트가 가질 수 있는 모든 상태를 커버했는가"를 뜻해요. Default 하나만 있는 컴포넌트는 사실 30% 정도만 완성된 거예요.
자주 누락되는 상태 목록 — 카테고리별 정리 📋
실무에서 가장 자주 빠지는 상태들을 인터랙션 상태, 기능 상태, 데이터 상태 세 카테고리로 나눠서 정리해 드릴게요.
① 인터랙션 상태 (Interaction States)
사용자의 마우스·터치·키보드 동작에 반응하는 상태들이에요. 이 중 hover와 focus가 가장 자주 빠져요.
| 상태 | 발생 시점 | 빠졌을 때 발생하는 일 |
|---|---|---|
| Hover | 마우스 오버 시 | 개발자가 opacity 70% 같은 임시 처리를 넣거나 아무 반응 없이 배포됨 |
| Active / Pressed | 클릭·탭 누르는 순간 | 클릭 피드백 없음 → 사용자가 "버튼이 눌렸나?" 혼란 |
| Focus | 키보드 Tab 포커스 시 | 접근성(A11y) 심각 문제. 키보드 사용자가 현재 위치를 알 수 없음 |
| Focus-visible | 키보드 포커스 (마우스 제외) | 마우스 클릭 시에도 포커스 링이 보여 시각적으로 지저분해짐 |
| Visited | 링크 방문 후 | 브라우저 기본 보라색으로 바뀌어 브랜드 색상 깨짐 |
② 기능 상태 (Functional States)
컴포넌트의 기능적 조건에 따라 달라지는 상태들이에요. disabled와 loading이 압도적으로 많이 빠져요.
| 상태 | 발생 시점 | 빠졌을 때 발생하는 일 |
|---|---|---|
| Disabled | 비활성화 조건 충족 시 | 개발자가 opacity 40% 처리. hover도 함께 꺼야 하는데 놓치는 경우 많음 |
| Loading / Pending | API 요청·처리 대기 중 | 스피너 위치·크기를 개발자가 임의로 결정. 버튼 너비가 갑자기 바뀌는 레이아웃 쉬프트 발생 |
| Selected / Checked | 선택된 상태 | 라디오·체크박스·탭 선택 시 시각적 구분 없음 |
| Readonly | 수정 불가 입력 필드 | disabled와 구분 없이 처리됨 → 복사 가능 여부 UI 혼동 |
| Indeterminate | 체크박스 부분 선택 | "전체 선택" 체크박스에서 일부만 선택됐을 때의 상태 누락 |
③ 데이터 상태 (Data States)
데이터의 존재 여부·유효성에 따른 상태들이에요. empty, error, skeleton이 3대 누락 단골이에요.
| 상태 | 발생 시점 | 빠졌을 때 발생하는 일 |
|---|---|---|
| Empty State | 데이터가 0건일 때 | 빈 컨테이너만 덩그러니. 개발자가 "데이터 없음" 텍스트를 임의 삽입 |
| Error State | API 실패·유효성 오류 | 빨간 테두리만 추가. 에러 메시지 위치·폰트·색상이 컴포넌트마다 제각각 |
| Skeleton | 데이터 로딩 전 | 데이터 로드 완료 후 레이아웃 쉬프트 발생. 혹은 스피너로 대체되어 UX 저하 |
| Partial / Truncated | 텍스트 넘침·말줄임 | 실제 긴 데이터 입력 시 레이아웃 깨짐. "짧은 텍스트"로만 디자인된 경우 빈번 |
| Success | 작업 완료 직후 | 제출 완료·저장 후 피드백 없음 → 사용자가 완료 여부를 모름 |
실무 경험상 개발 일정에 가장 큰 영향을 주는 누락 상태는 ① Loading (버튼·폼 전반), ② Empty State (리스트·테이블), ③ Error State (인풋 필드) 순이에요. 이 세 가지만 챙겨도 개발자와의 마찰이 절반 이상 줄어요.
빠뜨렸을 때 개발에서 벌어지는 일 🔥
상태가 빠졌다는 걸 개발자가 처음 인지하는 시점은 보통 구현 도중이에요. 이때 선택지는 세 가지예요.
📌 시나리오 A — 개발자가 임의로 처리한다
일정이 촉박하면 개발자가 "그냥 opacity 낮출게요" 하고 처리해버려요. 이 판단이 나쁜 게 아니에요. 하지만 결과적으로 브랜드 일관성이 깨지고, 나중에 디자이너가 보고 "이게 뭐예요?"가 되는 상황이 와요.
📌 시나리오 B — 디자이너에게 다시 요청한다
더 좋은 선택이지만 시간이 들어요. 디자이너가 해당 파일을 다시 열어서 상태를 추가하고, 검토 받고, 개발에 전달하는 루프가 돌아요. 규모가 작으면 하루, 크면 며칠이 날아가요. 스프린트 계획 전체가 흔들리기도 해요.
📌 시나리오 C — 그냥 배포한다
가장 무서운 케이스예요. "일단 베타니까"로 넘어갔다가 그게 그대로 프로덕션에 가는 일이 생각보다 자주 일어나요. 사용자가 아무 반응 없는 버튼을 보거나, 에러 후 빈 화면을 마주하면 이탈률이 올라가요.
결국 상태 하나를 빠뜨리는 건 단순히 "UI 누락"이 아니라 팀 전체의 시간과 제품 품질에 직접 영향을 미치는 문제예요. 디자이너가 미리 챙기는 게 가장 저렴한 해결책이에요.
컴포넌트별 상태 체크리스트 ✅
컴포넌트 유형별로 챙겨야 할 상태 목록을 체크리스트로 정리했어요. Figma에서 컴포넌트 작업 마칠 때 이 리스트를 한 번씩 훑어보세요!
🔘 Button
- ☐ Default
- ☐ Hover
- ☐ Active (Pressed)
- ☐ Focus
- ☐ Disabled — hover도 비활성화되어야 함
- ☐ Loading — 스피너 위치, 버튼 너비 고정 여부 명시 필수
- ☐ Success (필요한 경우) — 완료 아이콘·텍스트 변경 등
📝 Input / Form Field
- ☐ Default (Empty)
- ☐ Placeholder
- ☐ Focus
- ☐ Filled (값 입력된 상태)
- ☐ Error — 에러 메시지 공간, 아이콘, 색상 포함
- ☐ Success / Valid
- ☐ Disabled
- ☐ Readonly — disabled와 시각적으로 구분돼야 함
- ☐ Long text (텍스트 넘침 처리)
📋 List / Table / Card
- ☐ Default (데이터 있음)
- ☐ Loading / Skeleton — 레이아웃 쉬프트 없도록 실제 크기와 동일하게
- ☐ Empty State — 일러스트·메시지·CTA 버튼 포함 여부 결정
- ☐ Error State — 재시도 버튼 포함 권장
- ☐ Row hover (테이블)
- ☐ Partial load / Pagination (더 보기 상태)
☑️ Checkbox / Radio / Toggle
- ☐ Default (Unchecked)
- ☐ Hover
- ☐ Focus
- ☐ Checked / On
- ☐ Indeterminate — 체크박스만 해당. 부분 선택 상태
- ☐ Disabled Unchecked
- ☐ Disabled Checked — 이미 선택된 항목이 비활성화된 경우
🧭 Navigation / Tab
- ☐ Default
- ☐ Hover
- ☐ Active / Current (현재 페이지)
- ☐ Focus
- ☐ Disabled (비활성 메뉴 항목)
Skeleton은 실제 컨텐츠와 동일한 크기와 레이아웃으로 만들어야 해요. 높이가 다르면 데이터 로드 후 레이아웃 쉬프트(CLS)가 발생해요. Figma에서 실제 카드 컴포넌트 위에 Skeleton 레이어를 올려 크기를 맞춰보는 습관을 들이면 좋아요.
핵심 내용 정리 📝
오늘 다룬 내용을 마지막으로 정리할게요!
- 상태는 3가지 카테고리: 인터랙션(hover, active, focus), 기능(disabled, loading, selected), 데이터(empty, error, skeleton)로 분류해서 생각하면 누락이 줄어요.
- 3대 치명 누락: Loading·Empty State·Error State — 이 세 가지는 무조건 챙기세요.
- 누락의 결과: 개발자 임의 처리 → 브랜드 깨짐 / 재요청 루프 → 일정 지연 / 그냥 배포 → 사용자 이탈. 모두 미리 챙기는 것보다 비쌀 수밖에 없어요.
- 체크리스트 활용: 컴포넌트 완성 후 오늘 정리한 리스트를 한 번씩 훑어보는 습관만으로 커뮤니케이션 비용이 크게 줄어요.
- Skeleton은 실제 크기 기준: 레이아웃 쉬프트 방지를 위해 컨텐츠 컴포넌트와 동일한 크기로 설계하는 게 핵심이에요.
컴포넌트 상태 체크 요약 카드
자주 묻는 질문 ❓
디자이너를 오래 하신 분들은 이 리스트를 보면 "맞아, 이거 나도 빠뜨린 적 있지" 하고 공감하실 거예요. 처음엔 이걸 다 챙기려면 시간이 더 걸리는 것 같아도, 결과적으로는 개발자와 핑퐁하는 시간, 다시 수정하는 시간, 버그 리포트 받는 시간이 훨씬 줄어요. 오늘 체크리스트, 바탕화면에 저장해두고 컴포넌트 작업 마칠 때마다 꺼내 보세요! 더 추가하고 싶은 상태나 팀에서 겪은 사례가 있다면 댓글로 공유해 주세요 😊