접근성 (WCAG 2.2)은(는) 무엇을 하나요?
이 스킬은 디지털 인터페이스가 모든 사용자(스크린 리더, 스위치 제어 또는 키보드 탐색 사용자 포함)에게 인지 가능(Perceivable), 작동 가능(Operable), 이해 가능(Understandable), 견고(Robust)하게 동작하도록 보장합니다. 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