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

오류와 복구

문제의 상태와 사용자가 할 수 있는 복구 행동을 함께 제공합니다.

목표

오류를 기술 예외의 출력이 아니라 사용자가 원래 목표로 돌아가도록 돕는 경로로 설계한다. 오류를 예방할 수 있으면 제거하고, 발생하면 실패한 범위, 보존된 상태와 실제 다음 행동을 설명한다.

오류를 쓰기 전에 확인한다

  1. 애초에 선택할 수 없는 option을 제거하거나 제약할 수 있는가?
  2. 시스템이 값을 자동으로 보정하거나 안전한 기본값을 쓸 수 있는가?
  3. 입력 전에 형식과 제한을 알려 예방할 수 있는가?
  4. 더 적절한 component나 flow로 오류 자체를 없앨 수 있는가?
  5. 사용자가 지금 해결할 수 있는 문제인가?

문구를 고치는 것으로 구조 문제를 덮지 않는다.

오류 메시지의 네 요소

1. 실패한 대상

오류가 발생했어요가 아니라 무엇을 끝내지 못했는지 말한다.

2. 현재 상태

입력, 저장된 값, 이미 완료된 일부 작업이 유지되는지 설명한다.

3. 복구 행동

사용자가 지금 할 수 있는 가장 직접적인 행동을 제공한다.

4. 필요한 이유

안전하고 도움이 될 때만 원인을 설명한다. 보안 정보나 내부 stack을 그대로 노출하지 않는다.

사용 코드 · Text
초안을 저장하지 못했어요.
입력한 내용은 이 화면에 남아 있어요.
연결 상태를 확인한 뒤 다시 저장해주세요.

범위에 맞는 표현

Field 오류

  • 해당 control 가까이에 표시한다.
  • 어떤 값이 필요한지와 수정 방법을 말한다.
  • input과 programmatically 연결한다.

Section 오류

  • 화면 나머지를 사용할 수 있으면 실패한 section만 상태를 바꾼다.
  • 재시도도 같은 section 범위로 제한한다.

Toast 오류

  • 사용자가 현재 화면에서 바로 다시 행동할 수 있고 긴 설명이 필요 없을 때 사용한다.
  • 사라지기 전에 읽고 복구할 수 없는 중요한 오류에는 사용하지 않는다.

Dialog 오류

  • 작업 손실, 중요한 정책, 사용자의 결정이 필요할 때 사용한다.
  • 단순 network 실패마다 dialog로 흐름을 막지 않는다.

Page 오류

  • 주 데이터 전체를 사용할 수 없을 때 같은 content frame에 보여준다.
  • navigation과 돌아갈 경로를 유지한다.

입력과 저장 오류

  • submit 후 입력값을 지우지 않는다.
  • 여러 오류가 있으면 summary에서 개수와 field link를 제공한다.
  • 첫 오류 field로 focus를 이동한다.
  • 서버 validation을 field 오류와 form 수준 오류로 분류한다.
  • 자동 저장 실패는 저장됨 상태로 남기지 않는다.
  • 충돌은 일반 실패가 아니다. 최신본, 현재 변경, 선택 가능한 해결 방법을 제공한다.

비동기·부분 오류

  • 작업 요청 실패와 작업 실행 중 실패를 구분한다.
  • 일부 성공이면 성공·실패·건너뜀 개수를 각각 말한다.
  • 재시도가 중복 결과를 만들지 않는지 확인한다.
  • 실패 record만 filter하거나 다운로드할 경로를 제공한다.
  • 최신 상태를 확인할 수 없으면 마지막 확인 시각과 stale 상태를 말한다.

보안과 권한 오류

  • 계정 존재, 인증 정보, 내부 권한 구조를 과도하게 노출하지 않는다.
  • 자세한 원인을 말할 수 없어도 사용자가 값을 수정해야 하는지, 다시 인증해야 하는지, 기다리거나 문의해야 하는지는 구분한다.
  • 권한이 없으면 일반 network 오류로 숨기지 않는다.
  • 문의가 필요하면 복사 가능한 오류 ID, 발생 시각과 문의 경로를 제공한다.
  • 기술 정보는 핵심 문장 뒤의 보조 영역에 둔다.

어조

  • 사용자를 주어로 비난하지 않는다.
  • 안 돼요만 말하지 않고 가능한 다음 행동을 말한다.
  • 해결할 수 없는 문제를 사용자가 해결할 수 있는 것처럼 약속하지 않는다.
  • 심각한 오류에서 농담, 이모지, character 감정 표현을 피한다.
  • 실제 손실과 영향은 긍정형으로 돌려 모호하게 만들지 않는다.

접근성

  • field 오류에 aria-invalidaria-errormessage 또는 aria-describedby를 연결한다.
  • submit 실패 summary는 heading과 오류 link를 가진다.
  • 새로운 오류는 필요한 경우 role="alert"로 알리되 입력마다 반복하지 않는다.
  • 색, icon, border만으로 오류를 전달하지 않는다.
  • retry button의 이름에 실패 대상을 포함한다.
  • 오류가 사라진 뒤 focus를 갑자기 이동하지 않는다.
  • toast만 사용하는 경우 충분한 노출 시간과 keyboard 접근 가능한 action을 보장한다.

예시

피한다사용한다
오류가 발생했습니다.실행 기록을 불러오지 못했어요.
잘못 입력하셨습니다.이메일 주소 형식을 확인해주세요.
권한이 없습니다.발행 권한이 필요해요. 워크스페이스 소유자에게 요청할 수 있어요.
처리에 실패했습니다. 다시 시도해주세요.12건 중 3건을 발송하지 못했어요. 실패한 대상만 다시 발송할 수 있어요.
저장할 수 없습니다.최신 변경과 충돌해 저장하지 않았어요. 입력한 내용은 유지했어요.
사용 코드 · TSX
<FormField id="email" label="이메일" error="@ 뒤에 도메인을 포함한 이메일 주소를 입력해주세요.">
  <Input type="email" />
</FormField>

피해야 할 사용

  • 구조로 예방할 수 있는 오류를 문구만 고쳐 유지
  • 모든 오류를 같은 toast로 표현
  • 서버 오류 시 입력과 필터 초기화
  • 사용자가 해결할 수 없는 문제에 무한 재시도 제공
  • 부분 성공을 전체 실패로 표시
  • 기술 stack과 내부 코드만 노출
  • 색상과 느낌표만으로 심각도 전달
  • 실패를 character의 감정이나 사용자 탓으로 표현

검토 체크

  • 오류 자체를 예방하거나 제거할 방법을 먼저 검토했다.
  • 실패한 대상과 범위가 첫 문장에 있다.
  • 입력과 이미 완료된 작업이 유지되는지 말한다.
  • 실제로 실행 가능한 복구 행동을 제공한다.
  • field, section, toast, dialog, page 중 범위에 맞는 표현을 쓴다.
  • 부분 성공, 충돌, 권한, stale을 일반 오류와 구분한다.
  • 보안 정보를 노출하지 않으면서 다음 행동은 명확하다.
  • 오류와 control이 programmatically 연결돼 있다.
  • 색과 icon 없이도 오류를 이해할 수 있다.

관련 항목