접근성 (WCAG 2.2)은(는) 무엇을 하나요?
이 스킬은 스크린리더, 스위치 제어, 키보드 탐색을 사용하는 사용자를 포함한 모든 사용자가 디지털 인터페이스를 인지 가능하고(Perceivable), 운용 가능하며(Operable), 이해 가능하고(Understandable), 견고하게(Robust) (POUR) 제작할 수 있도록 보장합니다. WCAG 2.2 성공 기준의 기술적 구현에 중점을 둡니다.
사용 시기
- 웹, iOS 또는 Android용 UI 구성 요소 사양 정의 시
- 접근성 장벽 또는 준수 격차에 대한 기존 코드 감사 시
- 목표 크기(최소) 및 포커스 모양과 같은 새로운 WCAG 2.2 표준 구현 시
- 높은 수준의 디자인 요구 사항을 기술적 속성(ARIA 역할, 특성, 힌트)에 매핑 시
핵심 개념
- POUR 원칙: WCAG의 기초 (인지 가능, 운용 가능, 이해 가능, 견고)
- 의미론적 매핑: 일반 컨테이너보다 기본 요소를 사용하여 내장 접근성 제공
- 접근성 트리: 보조 기술이 실제로 "읽는" UI 표현
- 포커스 관리: 키보드/스크린리더 커서의 순서와 가시성 제어
- 라벨링 및 힌트:
aria-label,accessibilityLabel,contentDescription을 통해 컨텍스트 제공
작동 방식
1단계: 구성 요소 역할 식별
기능적 목적을 결정합니다(예: 버튼인가, 링크인가, 탭인가?). 사용자 정의 역할을 사용하기 전에 가장 의미 있는 기본 요소를 사용하십시오.
2단계: 인지 가능 속성 정의
- 텍스트 대비가 4.5:1(일반) 또는 3:1(큰 글꼴/UI)을 충족하는지 확인합니다.
- 비텍스트 콘텐츠(이미지, 아이콘)에 텍스트 대체 수단을 추가합니다.
- 반응형 리플로우 구현(기능 손실 없이 400%까지 확대 가능).
3단계: 운용 가능 컨트롤 구현
- 최소 24x24 CSS 픽셀 대상 크기(WCAG 2.2 SC 2.5.8)를 보장합니다.
- 모든 대화형 요소가 키보드로 도달 가능하고 가시적인 포커스 표시기가 있는지 확인합니다(SC 2.4.11).
- 드래그 동작에 대한 단일 포인터 대체 수단을 제공합니다.
4단계: 이해 가능한 로직 보장
- 일관된 탐색 패턴을 사용합니다.
- 설명적인 오류 메시지와 수정 제안을 제공합니다(SC 3.3.3).
- 동일한 데이터를 두 번 묻지 않도록 "중복 입력 방지"(SC 3.3.7)를 구현합니다.
5단계: 견고한 호환성 확인
- 올바른
Name, Role, Value패턴을 사용합니다. - 동적 상태 업데이트를 위해
aria-live또는 라이브 영역을 구현합니다.
접근성 아키텍처 다이어그램
flowchart TD
UI["UI 구성요소"] --> Platform{플랫폼?}
Platform -->|웹| ARIA["WAI-ARIA + HTML5"]
Platform -->|iOS| SwiftUI["접근성 특성 + 라벨"]
Platform -->|Android| Compose["시맨틱스 + 설명"]
ARIA --> AT["보조 기술 (스크린리더, 스위치)"]
SwiftUI --> AT
Compose --> AT
플랫폼 간 매핑
| 기능 | 웹 (HTML/ARIA) | iOS (SwiftUI) | Android (Compose) |
|---|---|---|---|
| 기본 라벨 | aria-label / <label> | .accessibilityLabel() | contentDescription |
| 보조 힌트 | aria-describedby | .accessibilityHint() | Modifier.semantics { stateDescription = ... } |
| 동작 역할 | role="button" | .accessibilityAddTraits(.isButton) | Modifier.semantics { role = Role.Button } |
| 실시간 업데이트 | aria-live="polite" | .accessibilityLiveRegion(.polite) | Modifier.semantics { liveRegion = LiveRegionMode.Polite } |
예제
웹: 접근 가능한 검색
<form role="search">
<label for="search-input" class="sr-only">제품 검색</label>
<input type="search" id="search-input" placeholder="검색..." />
<button type="submit" aria-label="검색 제출">
<svg aria-hidden="true">...</svg>
</button>
</form>
iOS: 접근 가능한 동작 버튼
Button(action: deleteItem) {
Image(systemName: "trash")
}
.accessibilityLabel("항목 삭제")
.accessibilityHint("이 항목을 목록에서 영구적으로 제거합니다")
.accessibilityAddTraits(.isButton)
Android: 접근 가능한 토글
Switch(
checked = isEnabled,
onCheckedChange = { onToggle() },
modifier = Modifier.semantics {
contentDescription = "알림 활성화"
}
)
피해야 할 반패턴
- Div-버튼: 역할과 키보드 지원을 추가하지 않고
<div>또는<span>을 클릭 이벤트에 사용. - 색상만으로 의미 전달: 색상 변경(예: 테두리를 빨간색으로 변경)만으로 오류나 상태를 표시.
- 포커스가 제한되지 않은 모달: 모달이 포커스를 가두지 않아 키보드 사용자가 모달이 열려 있는 동안 배경 콘텐츠로 이동할 수 있음. 포커스는
Escape키나 명시적인 닫기 버튼(WCAG SC 2.1.2)을 통해 가둬져야 하고 탈출 가능해야 합니다. - 중복 대체 텍스트: 대체 텍스트에 "이미지..." 또는 "그림..."을 사용 (스크린리더는 이미 "이미지" 역할을 이미 알려줍니다).
모범 사례 체크리스트
- 대화형 요소가 24x24px(웹) 또는 44x44pt(네이티브) 대상 크기를 충족하는지.
- 포커스 표시기가 명확하게 보이고 고대비인지.
- 모달이 열려 있는 동안 포커스를 가두고, 닫힐 때 깔끔하게 해제하는지 (
Escape키 또는 닫기 버튼). - 드롭다운과 메뉴가 닫힐 때 포커스를 트리거 요소로 복원하는지.
- 양식이 텍스트 기반 오류 제안을 제공하는지.
- 모든 아이콘 전용 버튼에 설명 텍스트 라벨이 있는지.
- 텍스트가 확대될 때 콘텐츠가 제대로 리플로우되는지.
참고 자료
관련 스킬
frontend-patternsdesign-systemliquid-glass-designswiftui-patterns