토스트 및 스낵바 시스템
목적
토스트 및 스낵바 시스템은 일시적이고 방해가 되지 않는 알림 레이어를 설계하기 위한 방법론을 제공합니다. 이는 기본 인터페이스 위의 전용 화면 레이어에 위치하는 간결하고, 자동 또는 수동으로 닫을 수 있는 UI 구성 요소입니다. 모달 오버레이와 달리 포커스를 가로채거나 사용자의 흐름을 중단하지 않습니다. 대신 백그라운드 또는 즉시 작업이 성공, 실패했거나 약간의 주의가 필요함을 확인시켜 주는 수동적이지만 가시성이 높은 '확인 루프' 역할을 합니다. 이 시스템은 토스트가 시각적으로 통일되고, 중요한 컨트롤을 차단하지 않도록 배치되며, 마우스, 터치 및 보조 기술 사용자 모두가 완전히 접근할 수 있도록 보장합니다.
사용 사례
- 비동기 작업: 파일 업로드, 임시 저장 자동 저장, 레코드 삭제 등의 백그라운드 작업 완료 확인.
- 소액 약정 확인: 장바구니에 상품 추가, 링크 클립보드 복사, 로컬 환경 설정 전환 등의 작업 확인.
- 되돌릴 수 있는 파괴적 작업: 항목이 보관 또는 삭제되었음을 알리고 스낵바 내에서 즉시 '실행 취소' 액션 제공.
- 일시적 상태 업데이트: '오프라인' 또는 '온라인' 상태 전환과 같은 간단한 자동 시스템 알림 표시.
사용하지 말아야 할 경우
- 중대한 시스템 차단: 만료된 세션, 결제 실패 등 사용자의 진행을 막는 중요한 오류가 발생한 경우
overlay-and-dialog-system(모달)을 사용하세요. - 지속적인 섹션 경고: 특정 섹션, 페이지 또는 양식 컨텍스트와 관련된 경고나 오류가 해결될 때까지 계속 표시되어야 하는 경우
banner-and-alert-system(인라인 알림)을 사용하세요. - 양식 유효성 검사 메시지: 특정 입력 필드 내에서 사용자가 오류를 범한 경우
form-design-system(필드 수준 유효성 검사)을 사용하세요. - 기본 콘텐츠 발견: 토스트를 기본 콘텐츠, 마케팅 공지 또는 탐색 옵션을 제시하는 데 사용하지 마십시오.
입력
- 메시지 중대성 / 유형: 성공 (확인), 정보 (중립적 업데이트), 경고 (비차단 우려사항) 또는 오류 (작업 실패).
- 액션 요구 사항: 피드백이 수동적인지(읽기 전용) 아니면 단일 마이크로 액션(예: '실행 취소', '보기', '재시도')을 포함하는지 여부.
- 화면 공간 및 기기 종류: 대상 뷰포트 (데스크톱, 태블릿, 모바일) 및 주요 입력 방식 (마우스 호버 vs. 엄지손가락 닿는 범위).
- Z-인덱스 및 레이어링 전략: 헤더 내비게이션, 고정 푸터 또는 활성 오버레이와의 중복을 방지하기 위한 스태킹 컨텍스트 규칙.
출력
- 구성 요소 해부도 사양: 컨테이너, 아이콘 슬롯, 메시지 문자열, 액션 CTA 및 수동 닫기 버튼의 그리드 기반 청사진.
- 공간 정렬 및 배치 규칙: 데스크톱(예: 오른쪽 상단 또는 오른쪽 하단 스택) 및 모바일(예: 아래쪽 전체 너비 슬라이드 업)을 위한 적응형 좌표.
- 대기열 및 스태킹 로직: 동시 알림 처리, 최대 표시 제한 및 만료 순서를 위한 시스템 규칙.
- 상호작용 타임라인 및 만료 사양: 자동 종료 시간 초과, 호버 시 일시 중지 동작 및 스와이프 제스처를 관장하는 규칙.
- 접근성 / ARIA 청사진: 라이브 리전의 시맨틱 매핑, 상호작용 가능한 토스트를 위한 포커스 처리 및 화면 판독기 알림.
워크플로우
1. 구성 요소 해부도 구조화
표준 공간 토큰을 사용하여 토스트 컨테이너의 정확한 간격 및 레이아웃 그리드를 정의합니다.
- 아이콘 슬롯: 고정 너비(예: 20px 또는 24px)로 가장 왼쪽에 배치합니다. 시맨틱하고 대비가 높은 상태 아이콘(성공 시 체크 표시, 경고/오류 시 느낌표 삼각형, 정보 시 정보 원)을 사용합니다.
- 텍스트 영역: 왼쪽 정렬된 줄 바꿈 텍스트로, 간결한 제목(굵게, 선택 사항)과 설명으로 구성됩니다. 텍스트를 줄임표로 자르지 말고 최대 3줄까지 줄 바꿈합니다.
- 액션 슬롯 (선택 사항): 메시지 오른쪽에 배치되는 단일의 가시성이 높은 텍스트 버튼(예: '실행 취소')입니다. 모바일에서 긴 텍스트의 경우 액션을 새 줄로 오른쪽 정렬하여 배치합니다.
- 닫기 트리거: 가장 오른쪽에 배치되는 명확한 'X' 닫기 버튼입니다. 최소 24x24px의 히트 영역을 가져야 하며 (터치 대상은 44x44px 권장).
2. 뷰포트별 공간 배치 결정
- 데스크톱 배치: 토스트 컨테이너 스택을 화면의 오른쪽 상단 또는 오른쪽 하단 모서리에 배치합니다. 뷰포트 가장자리에서 일관된
24px오프셋을 유지합니다.- 오른쪽 상단 스택: 기본 작업 흐름이 페이지 하단에서 발생할 때 가장 좋습니다.
- 오른쪽 하단 스택: 상단에 장착된 내비게이션 또는 유틸리티 모음이 위쪽 여백을 차지하여 중복을 방지해야 할 때 가장 좋습니다.
- 모바일 배치: 데스크톱 스택을 하단에 고정된 전체 너비의 스낵바로 변환합니다(왼쪽, 오른쪽 및 하단 가장자리에서
12px~16px여백). 이렇게 하면 상호작용이 최적의 '엄지손가락 닿는 영역' 내에 유지됩니다. - Z-인덱스 규칙: 표준 고정 헤더(
z-index: 1000) 위에 있지만 활성 전체화면 오버레이(z-index: 10000) 아래에 토스트를 배치하는 전용 z-인덱스 토큰(예:z-index: 5000이상)을 항상 할당합니다.
3. 스태킹 및 대기열 로직 설정
레이아웃 변경이나 인지적 과부하를 유발하지 않고 높은 볼륨의 트리거 환경을 관리합니다.
- 최대 표시 제한: 활성 대기열을 최대 3개의 가시 토스트로 수직 스택 제한합니다.
- 스태킹 방향:
- 화면 상단에 배치된 경우 새 토스트가 위에서 슬라이드 인하여 이전 토스트를 아래로 밀어냅니다.
- 화면 하단에 배치된 경우 새 토스트가 아래에서 슬라이드 업하여 이전 토스트를 위로 밀어냅니다.
- 대기열 버퍼: 3개의 토스트가 활성화된 상태에서 4번째 토스트가 트리거되면 새 토스트를 메모리에 버퍼링합니다. 가장 오래된 가시 토스트가 자연스럽게 만료되어 사라지면 즉시 렌더링합니다.
4. 만료 및 호버 시 일시 중지 타임라인 코딩
토스트는 읽을 수 있을 만큼 충분히 오래 존재해야 하지만 화면을 비우기 위해 신속하게 사라져야 합니다.
- 동적 TTL(Time-to-Live): 콘텐츠 길이에 따라 만료 시간을 계산합니다.
- 짧은 수동 토스트 (40자 미만): 5초 후에 사라집니다.
- 더 길거나 액션이 있는 토스트: 화면 판독기가 완전히 알리고 사용자가 읽고 행동할 시간을 확보하기 위해 7~10초 후에 사라집니다.
- 오류/실패 토스트: 자동 사라지지 않습니다. 사용자가 'X' 버튼을 수동으로 클릭할 때까지 계속 표시되어 중요한 피드백이 손실되지 않도록 합니다.
- '호버 시 일시 중지' 상호작용:
- 마우스 사용자가 토스트 대기열의 일부 위에 마우스를 올리면 모든 활성 TTL 카운트다운을 중지합니다. 마우스가 토스트 경계를 벗어난 후에만 타이머를 재설정하고 다시 시작합니다.
- 키보드 사용자가 토스트 내부의 요소에 포커스를 맞추면 타이머를 무기한 중지합니다. 포커스가 기본 문서로 다시 이동할 때만 카운트다운을 다시 시작합니다.
5. 닫기 및 제스처 동작 정의
- 터치 스와이프: 모바일 장치에서 사용자가 개별 스낵바를 화면 밖으로 수평으로 스와이프(왼쪽 또는 오른쪽)하여 즉시 해제할 수 있도록 합니다. 드래그 임계값을 뷰포트 너비의 30%로 유지합니다.
- 애니메이션: 부드럽고 하드웨어 가속화된 전환(예:
transform및opacity)을 사용하며, 진입 시200ms~300ms및cubic-bezier(0.16, 1, 0.3, 1)(ease-out-expo) 지속 시간을 사용하고, 퇴장 시 단순opacity페이드 아웃을 사용합니다.
결정 규칙
스태킹 정렬 매트릭스
| 뷰포트 | 기본 내비게이션 레이아웃 | 권장 토스트 배치 | 애니메이션 방향 |
|---|---|---|---|
| 데스크톱 | 왼쪽 사이드바 / 대시보드 | 오른쪽 하단 (주 작업 영역 유지) | 화면 밖에서 왼쪽으로 슬라이드 |
| 데스크톱 | 고정 상단 헤더 | 오른쪽 하단 (내비게이션 가림 방지) | 왼쪽 또는 위로 슬라이드 |
| 데스크톱 | 미니멀 / 푸터 중심 | 오른쪽 상단 | 왼쪽 또는 아래로 슬라이드 |
| 모바일 | 모든 경우 | 하단 중앙 / 전체 너비 | 아래쪽 가장자리에서 위로 슬라이드 |
만료 로직 매트릭스
| 토스트 중대성 / 유형 | 액션 버튼 포함? | 권장 만료 시간 | 해제 유형 |
|---|---|---|---|
| 성공 / 정보 | 아니오 | 5초 (고정) | 자동 해제 + 수동 닫기 |
| 성공 / 정보 | 예 ('실행 취소' / '보기') | 8 - 10초 | 자동 해제 + 수동 닫기 |
| 경고 | 아니오 | 7초 | 자동 해제 + 수동 닫기 |
| 오류 / 실패 | 예 또는 아니오 | 무한 (계속 표시) | 수동 닫기 전용 |
제약 조건
- 접근성 (WCAG 2.2 준수):
- ARIA 라이브 리전: 수동 토스트를
role="status"(기본값aria-live="polite"및aria-atomic="true")에 매핑합니다. 시스템 오류(예: '인터넷 연결 끊김')를 전달하지 않는 한role="alert"(assertive) 사용을 피하십시오. assertive 알림은 화면 판독기를 문장 중간에 즉시 중단시키기 때문입니다. - 키보드 길 찾기 (WCAG 2.2 SC 2.1.1): 토스트에 상호작용 가능한 액션(예: '실행 취소' 또는 '보기')이 포함된 경우 키보드로 접근 가능해야 합니다. 키보드 탭 루프는 느릴 수 있으므로 전역 우회 단축키(예:
Escape는 활성 토스트를 닫거나F6는 포커스를 토스트 대기열 컨테이너로 직접 이동)를 제공하거나 DOM 탭 순서에서 활성 트리거 바로 뒤에 토스트 컨테이너를 배치합니다. - 포커스 트랩 없음: 토스트 대기열 내에 키보드 포커스를 가두지 마십시오. 사용자는 토스트에서 페이지 콘텐츠로 자유롭게 Tab 이동할 수 있어야 합니다.
- ARIA 라이브 리전: 수동 토스트를
- 대비 (WCAG 2.2 SC 1.4.3):
- 모든 텍스트, 상태 아이콘 및 버튼은 토스트 배경에 대해 최소 대비를 충족해야 합니다.
- 일반 텍스트: 4.5:1 최소 대비.
- 아이콘 및 활성 컨트롤 테두리: 3:1 최소 대비.
- 모든 텍스트, 상태 아이콘 및 버튼은 토스트 배경에 대해 최소 대비를 충족해야 합니다.
- 반응형:
- 뷰포트
< 600px에서 토스트 컨테이너는 전체 너비(width: calc(100% - 32px))로 확장되고 중앙 수평 정렬되어 어색한 여백 열이 발생하지 않도록 해야 합니다.
- 뷰포트
일반적인 실패 패턴
- '액션 가리기' 함정: 데스크톱 토스트 대기열을 장바구니 헤더 버튼이나 테이블 필터링 드롭다운과 같은 빈번한 상호작용 요소 바로 위에 배치하여 사용자가 잘못 클릭하게 만드는 경우.
- '잠깐 보였다 사라지는' 깜빡임: 복잡하고 여러 단어로 구성된 오류나 경고를 2-3초 내에 자동 해제하는 경우. 이는 기본적인 접근성 읽기 임계값을 위반하고 컨텍스트를 놓친 사용자를 당황하게 합니다.
- 화면 판독기 침묵: ARIA 라이브 리전 래퍼 없이 토스트를 DOM에 동적으로 추가하여 시각 장애 사용자에게 완전히 보이지 않게 만드는 경우.
- 레이아웃 이동 스래싱: 진입 시 토스트 대기열의 높이를 갑자기 애니메이션하여 기본 페이지 콘텐츠가 위아래로 흔들리게 만드는 경우.
- 호버/포커스 만료 무시: 사용자가 긴 텍스트 메시지를 읽기 위해 마우스를 올리거나 '실행 취소' CTA 위에 마우스를 올려 놓은 상태에서 토스트가 자동 해제되어 사용자가 '빈 공간'을 클릭하고 원치 않는 작업을 트리거하게 만드는 경우.
검증 기준
- 토스트는 고유한 대비가 높은 시맨틱 표시기(색상 + 고유 아이콘)로 스타일링됩니다.
- 데스크톱에서 토스트는 기본 내비게이션 요소나 전역 액션 영역과 겹치지 않습니다.
- 모바일에서 토스트는 엄지손가락으로 쉽게 닿을 수 있는 하단 고정 전체 너비 구성 요소로 변환됩니다.
- 활성 타이머는 마우스로 가리키거나 키보드로 포커스할 때 즉시 일시 중지됩니다.
- 액션이 있는 토스트는 최소 8~10초 동안 표시됩니다. 오류 토스트는 자동으로 사라지지 않습니다.
- 시맨틱 화면 판독기 마크업(
role="status"또는role="alert")이 올바르게 지정됩니다. - 키보드 사용자는 포커스 트랩 장벽 없이 토스트 액션 버튼으로 이동하여 트리거할 수 있습니다.
- 모든 상호작용 요소(닫기 버튼, CTA)는 WCAG 2.2 최소 24x24px 터치 대상을 충족합니다(44x44px 권장).