본문으로 건너뛰기
Dot Design System
v0.3.1

피드백과 복구

모든 상태 변화가 이해되고 다음 행동으로 이어지게 합니다.

목적

피드백은 시스템이 사용자의 행동을 받았는지, 무엇이 달라졌는지, 다음에 무엇을 할 수 있는지 알려준다. Dot은 성공만 축하하지 않는다. 진행, 빈 상태, 오류, 부분 성공, 복구까지 하나의 연속된 고리로 설명한다.

좋은 피드백은 사용자가 시스템을 추측하지 않게 하며, 실패했을 때도 작업과 자신감을 보존한다.

피드백의 위치

종류사용 조건위치
inline특정 필드·행·검증 결과에 고정된 상태해당 대상 바로 가까이
toast짧고 비차단적인 완료·변경 결과overlay 영역
dialog데이터 손실, 되돌릴 수 없음, 현재 흐름 중단focus가 제한된 overlay
page state주 데이터를 사용할 수 없는 loading·empty·error원래 콘텐츠 frame
persistent status장시간 작업, 저장·검증·발행 단계PageHeader meta 또는 WorkflowBar

중요한 결과를 toast에만 두지 않는다. 다음 판단에 필요한 상태는 콘텐츠 안에 지속적으로 남긴다.

상태의 전체 흐름

모든 비동기 작업은 필요한 범위에서 다음 상태를 정의한다.

  1. idle: 실행 전 조건과 행동을 이해할 수 있다.
  2. pending: 어떤 작업이 진행 중이고 중복 실행이 막혔는지 알 수 있다.
  3. success: 무엇이 완료됐고 화면의 어떤 값이 바뀌었는지 알 수 있다.
  4. partial success: 성공·실패 범위와 다음 조치를 구분한다.
  5. error: 끝내지 못한 일, 영향, 복구 행동을 제공한다.
  6. stale 또는 interrupted: 결과가 오래됐거나 연결이 끊긴 상태를 숨기지 않는다.

상태 전환 때 콘텐츠 높이와 위치를 불필요하게 크게 바꾸지 않는다.

로딩

  • 즉시 끝나는 작업에는 불필요한 화면 전환이나 장식적 로딩을 만들지 않는다.
  • 목록·카드가 처음 로드될 때는 최종 구조와 닮은 Skeleton을 사용한다.
  • 사용자가 시작한 저장·검증은 trigger 레이블과 persistent status에서 진행 중임을 보여준다.
  • 화면 전체를 사용할 수 없는 경우에만 전체 loading state를 쓴다.
  • 이미 보이는 데이터를 갱신할 때는 기존 내용을 지우지 않고 갱신 상태와 마지막 갱신 시각을 표시한다.
  • 장시간 AI 처리에는 DotMotionprocessing을 사용할 수 있지만 텍스트 상태, 취소 가능 여부, 실패 fallback을 함께 제공한다.
  • 정확한 진행률을 알 수 없는데 임의의 percent를 보여주지 않는다.

빈 상태

EmptyState는 다음 순서로 작성한다.

  1. 무엇이 없는지
  2. 왜 비어 있거나 어떤 가치를 만들 수 있는지
  3. 사용자가 할 수 있는 다음 행동

빈 상태의 종류를 구분한다.

  • 처음 시작: 아직 만든 항목이 없음 → 생성 행동 제공
  • 필터 결과 없음: 원본은 있지만 조건에 맞지 않음 → 필터 해제 또는 수정
  • 권한·범위 없음: 접근 가능한 데이터가 없음 → 이유와 요청 경로
  • 완료된 상태: 처리할 예외가 없음 → 정상임을 알려주고 다음 확인 시점 제공

캐릭터는 넓고 드문 처음 시작이나 의미 있는 완료 상태에서만 사용할 수 있다. 반복되는 필터 결과 없음에는 사용하지 않는다.

오류 문장

오류는 다음 세 부분으로 쓴다.

  1. 무엇을 끝내지 못했는지
  2. 현재 데이터나 작업에 어떤 영향이 있는지
  3. 사용자가 지금 할 수 있는 복구 행동

예:

커리큘럼을 저장하지 못했어요. 입력한 내용은 이 화면에 남아 있어요. 연결 상태를 확인한 뒤 다시 저장해주세요.

학습 알림 24건 중 3건을 보내지 못했어요. 실패한 대상만 확인해 다시 발송할 수 있어요.

기술 코드와 요청 ID는 지원에 필요할 때만 보조 정보로 제공한다. 사용자가 해결할 수 없는 내부 오류를 행동 지시처럼 쓰지 않는다.

복구 행동

  • 입력·선택·scroll을 가능한 한 보존한다.
  • 재시도가 안전하면 실패한 범위만 다시 실행한다.
  • 자동 재시도 중이라면 횟수보다 현재 상태와 수동 행동 가능 시점을 알려준다.
  • 충돌이 생기면 조용히 덮어쓰지 않고 내 변경 유지, 최신 내용 불러오기, 변경 비교처럼 이해 가능한 선택을 제공한다.
  • 권한 문제는 무한 재시도 대신 필요한 권한과 요청 경로를 알려준다.
  • 삭제된 대상은 돌아갈 목록과 대체 대상을 제안할 수 있다.
  • 복구할 수 없는 경우에도 사용자의 다음 안전한 목적지를 제공한다.

부분 성공

일괄 작업과 AI 처리에서는 부분 성공을 독립 상태로 다룬다.

  • 성공·실패·건너뜀 수를 분리한다.
  • 실패 원인별로 대상을 찾을 수 있게 한다.
  • 성공한 항목을 다시 실행하지 않아도 되는지 명확히 한다.
  • 전체 성공처럼 오해하게 만드는 toast를 보내지 않는다.
  • 다음 행동은 실패한 3건 확인, 실패한 항목만 다시 시도처럼 범위를 말한다.

완료와 다음 방향

완료 피드백은 한 고리가 끝났음을 알리고 다음 배움이나 운영 행동을 밝힌다.

  • 저장 완료 뒤에는 검증이 필요하면 다음 행동을 연결한다.
  • 발행 완료 뒤에는 적용 시점과 영향을 확인하게 한다.
  • 학습 완료 뒤에는 다음 학습의 시점 또는 돌아갈 위치를 제안한다.
  • AI 검토 완료 뒤에는 확정·적용 상태와 남은 미검토 항목을 보여준다.

완료를 과도한 애니메이션으로 축하하지 않는다. 사용자의 실제 성취와 다음 방향을 짧고 구체적으로 보여준다.

  • Flexible: 오류 종류, 사용자 권한, 작업 규모에 따라 복구 행동을 조정하되 메시지 구조는 유지한다.
  • Link: 사용자의 원래 행동, 진행 상태, 결과, 복구, 다음 단계를 끊지 않는다.
  • Glow: 불확실한 순간에 다음 안전한 행동을 은은하게 안내하거나 의미 있는 완료를 표시할 때만 쓴다.

예외와 피해야 할 사용

  • 모든 성공에 toast를 쌓지 않는다.
  • 오류를 문제가 발생했습니다 한 문장으로 끝내지 않는다.
  • 실패 후 폼을 초기화하거나 dialog를 자동으로 닫지 않는다.
  • color, icon, 캐릭터만으로 상태를 설명하지 않는다.
  • 빈 상태와 오류 상태를 같은 문구와 그림으로 처리하지 않는다.
  • 이미 보이는 데이터를 background refresh 중이라는 이유로 skeleton으로 교체하지 않는다.
  • 시스템이 모르는 진행률이나 완료 시간을 약속하지 않는다.
  • 사용자가 해결할 수 없는 오류에 다시 시도만 무한히 제공하지 않는다.

상태와 접근성

  • 진행 중인 container에는 필요한 경우 aria-busy를 사용한다.
  • 짧은 상태 변화는 적절한 live region으로 알리되 중복 메시지를 피한다.
  • 긴 오류는 focus가 이동하지 않아도 heading과 관계를 통해 찾을 수 있어야 한다.
  • field error는 control의 accessible description 관계에 연결한다.
  • toast는 읽을 시간을 보장하고 중요한 행동을 시간 제한 toast에만 두지 않는다.
  • dialog는 focus trap, 초기 focus, trigger 복귀를 지킨다.
  • reduced motion에서도 성공·실패·진행 상태를 텍스트로 이해할 수 있어야 한다.
  • 오류 focus 이동은 제출 후 첫 오류처럼 사용자의 다음 행동을 실제로 돕는 경우에만 한다.

검토 질문

  • idle부터 success·error까지 필요한 상태가 모두 정의됐는가?
  • 사용자는 진행 중인 대상과 행동을 알 수 있는가?
  • 오류 문장이 실패한 일, 영향, 복구 행동을 포함하는가?
  • 실패 후 입력과 선택이 보존되는가?
  • 부분 성공을 전체 성공처럼 오해할 가능성이 없는가?
  • toast에만 남아 사라지는 중요한 상태는 없는가?
  • empty, filtered empty, permission empty, error를 구분했는가?
  • 완료가 다음 배움 또는 관리 행동과 연결되는가?
  • keyboard와 screen reader에서도 상태 변화와 오류 관계가 전달되는가?
  • 캐릭터와 Glow가 상태 설명을 대체하지 않고 의미 있는 안내만 하는가?