피드백 원칙
사용자의 모든 행동에는 반응이 따라야 합니다. 반응이 없으면 사용자는 자신의 행동이 전달되었는지 확신하지 못합니다. 피드백 원칙은 어떤 반응을, 언제, 어떤 방식으로 전달할지 정의하는 기준입니다.
피드백 원칙의 개념
섹션 제목: “피드백 원칙의 개념”피드백은 사용자의 행동과 시스템의 상태를 연결하는 응답입니다.
- 모든 행동은 결과를 눈에 보이게 만들어야 합니다.
- 반응은 행동 직후 즉시 전달되어야 합니다.
- 반응의 무게는 상황의 중요도에 맞춰야 합니다.
피드백은 선택 사항이 아니라 행동의 완결 요소입니다.
피드백 방식의 선택
섹션 제목: “피드백 방식의 선택”피드백은 상황에 따라 전달 방식을 구분합니다. 같은 반응이라도 방식이 어긋나면 방해가 됩니다.
- 인라인(Inline) — 특정 요소에 대한 반응. 해당 위치에서 표현합니다. (입력 오류, 유효성 결과)
- 토스트(Toast) — 흐름을 끊지 않는 짧은 알림. 잠시 뒤 사라집니다. (저장 완료, 복사됨)
- 모달(Modal) — 사용자의 확인이나 결정이 필요한 반응. 흐름을 멈춥니다. (삭제 확인, 중요한 경고)
기준은 단순합니다. 흐름을 멈춰야 하는가에 따라 방식을 고릅니다.
토스트는 toast_message 컴포넌트로 만들고, 노출 여부는 data-state로 제어합니다. 닫기 버튼은 대부분 모달 닫기와 스타일이 달라 내부 요소 i_close로 둡니다.
<div class="toast_message" data-state="show" role="status"> <p class="i_text">저장되었습니다.</p> <button class="i_close" type="button" aria-label="닫기"></button></div>알림 강도는 둘로 구분합니다.
기본은 role="status" — 조용히 읽히는 알림이며 자동 소멸을 허용합니다.
끼어들어야 하는 실패·세션 만료만 role="alert" — 즉시 읽히며 자동으로 사라지게 하지 않습니다.
어느 쪽이든 알림은 포커스를 옮기지 않고,
컨테이너는 미리 DOM에 있어야 보조 기술이 읽습니다.
위치는 한 곳입니다 — 강도에 따라 자리를 바꾸지 않습니다(알림 자리가 일정해야 찾습니다).
크게 오래 보여야 하는 메시지는 토스트가 아니라 배너(alert.m_banner)로 둡니다.
그래서 토스트는 동적으로 만들지 않고, 빈 컨테이너를 페이지 블록 밖에 미리 두고 텍스트만 바꿉니다.
큐·자동 소멸·닫기는 동작 층(slur.js)의 slur.toast(text, { level })가 담당합니다 —
한 번에 하나, 닫힌 뒤 텍스트를 비워 같은 문장이 다시 읽히게 합니다.
모달이 열려 있으면 큐에 두었다가 닫힌 뒤 보여줍니다(아래 규칙).
모달이 열려 있는 동안에는 토스트를 띄우지 않습니다.
모달 안에서 생긴 상태 변화는 모달 안에서 알립니다 —
버튼의 글자·아이콘 변화(“복사” → “복사됨”), alert.m_inline, 인라인 오류.
아이콘만 바꾸면 보조 기술이 알 수 없으므로 글자나 aria-label도 함께 바꿉니다.
모달과 무관한 알림은 모달이 닫힌 뒤에 띄우고,
끼어들어야 하는 알림(세션 만료)은 토스트 대신 모달을 닫고 경고 모달로 대체합니다.
이유는 둘입니다.
첫째, 정의상 모순입니다 — 토스트는 흐름을 끊지 않는 알림이고, 모달은 흐름을 멈춘 상태입니다.
둘째, 기술적 한계입니다 — 네이티브 <dialog>가 열리면 dialog 바깥은 전부 inert가 됩니다.
토스트를 popover로 최상위 레이어에 올려도 눈에만 모달 위에 보일 뿐,
닫기 버튼이 동작하지 않고 키보드와 보조 기술이 닿지 않습니다(HTML 표준의 현재 규정, 개정 논의 중).
--z-toast는 드롭다운·스티키처럼 모달이 아닌 레이어 위에 뜨는 용도로 유지합니다.
인라인 오류는 입력 요소 옆 i_error로 표현하고, 오류 상태는 클래스가 아니라 data-state="error"로 나타냅니다.
<div class="form_group" data-state="error"> <label for="user_email">이메일</label> <input type="email" id="user_email" class="input_text" aria-describedby="user_email_error"> <p class="i_error" id="user_email_error">올바른 이메일 형식이 아닙니다.</p></div>모달은 흐름을 멈추는 반응이며, 구조는 팝업/모달 패턴을 따릅니다.
파괴적 행동의 확인
섹션 제목: “파괴적 행동의 확인”되돌릴 수 없는 행동은 즉시 실행하지 않습니다.
- 삭제, 초기화, 전송처럼 복구가 어려운 행동은 확인을 요구합니다.
- 확인 문구는 행동의 결과를 분명히 밝힙니다.
- 실행 버튼과 취소 버튼의 역할을 명확히 구분합니다.
확인 단계는 사용자를 번거롭게 하는 절차가 아니라 실수를 되돌릴 수 있게 하는 안전장치입니다. 확인창 자체의 구조는 팝업/모달 패턴을 따릅니다.
즉각성과 상태 연결
섹션 제목: “즉각성과 상태 연결”피드백은 행동과 같은 순간에 일어나야 합니다.
- 처리에 시간이 걸리면 로딩 상태로 진행 중임을 알립니다.
- 결과가 나오면 성공 또는 실패를 분명히 표현합니다.
- 상태 변화는 상태 기반 UI의
data-state로 표현합니다.
반응이 지연되면 사용자는 같은 행동을 반복하거나 실패로 오해합니다.
피드백 원칙의 목적
섹션 제목: “피드백 원칙의 목적”피드백 원칙은 사용자가 자신의 행동이 어떻게 처리되었는지 항상 확인할 수 있도록 만들기 위한 기준입니다.
반응이 분명할수록 사용자는 다음 행동을 확신을 가지고 이어갑니다.