# accessibility.md — 접근성 구현 계약
4단계 구현부터 참조하고, 5단계 프리플라이트의 접근성 표([preflight.md](preflight.md) §1)가 가리키는 정본이다. `preflight.md`는 체크리스트 행만 두고 여기를 가리킨다 — 이 문서는 체크리스트를 반복하지 않고 **왜 실패하는지, 어떤 코드로 고치는지, 무엇을 참조하는지**를 다룬다.
라벨은 셋 중 하나다. **하드 게이트**는 위반하면 통과시키지 않는다 — WCAG AA·키보드·포커스·대비·감소 모션·진실성처럼 규범 또는 기능에 근거한다. **프로젝트 계약**은 브리프·`design.md`·플랫폼이 그 조건을 선택했을 때만 적용된다 — AAA 기준, HIG·M3의 44/48px 같은 모바일 앱 수준 목표가 여기 속한다. **관찰 후보**는 스타일 휴리스틱의 시작값이며 실제 렌더에서 확인해 조정한다. 외부 스킬에서 가져온 수치는 "시작값"이라 적고, 근거가 약하면 "실측 조정"을 덧붙인다.
## 이 문서를 읽는 법
| 상황 | 읽을 곳 |
|---|---|
| AA와 AAA, 자동 점수와 실제 준수의 관계가 헷갈린다 | §0 |
| `
` 대신 뭘 써야 하는지, ARIA를 언제 쓰는지 | §1 |
| 아이콘 전용 버튼, 인라인 SVG의 이름을 어떻게 붙이는지 | §2 |
| 포커스 링 스타일·대비·가림 방지 | §3 |
| 탭·메뉴·콤보박스·리스트박스·다이얼로그의 키보드 계약, 모달, SPA 라우팅 | §4 |
| 스킵 링크·랜드마크·링크 텍스트 | §5 |
| 라벨·자동완성·입력 타입·비활성화 규칙·오류 처리 | §6 |
| 토스트·로딩 상태를 어떻게 알리는지 | §7 |
| 터치 타깃 크기와 히트 영역 확장 | §8 |
| 깜빡임·자동재생·호버 콘텐츠 | §9 |
| 드래그로만 되는 조작의 대안 | §10 |
| 비디오·오디오 자막 | §11 |
| `prefers-*` 미디어 쿼리 중 뭐가 하드 게이트고 뭐가 점진적 향상인지 | §12 |
| 감사를 어떤 순서로 돌리는지, MCP가 없을 때 뭘 쓰는지 | §13 |
| 발견한 문제를 어떤 형식으로 보고하는지 | §14 |
| 색·모션 단독 전달 금지(다른 문서가 이 문서를 정본으로 지목한 규칙) | 부록 A |
---
## 0. 판정 원칙
**하드 게이트.** WCAG 2.2는 A·AA·AAA 세 적합성 수준을 정의하며, 셋은 서로 다른 요구다 — AAA를 만족한다고 모두에게 접근 가능해지지는 않는다[WCAG-22]. designpaca는 **AA를 하드 게이트**로 삼는다. 이 문서의 모든 절은 별도 표기가 없는 한 AA 이하 기준을 하드 게이트로 취급한다.
**프로젝트 계약.** AAA 기준([WCAG-FOCUS-APPEAR] 2.4.13 등)과 HIG·M3의 44/48px 같은 플랫폼 권장은 브리프가 그 수준을 선택했을 때만 적용된다. "모바일 앱 수준"이라는 말이 브리프에 있으면 project contract로 올라간다(§8).
**자동 점수는 준수가 아니다.** Lighthouse 접근성 100점이나 axe 통과는 도구가 검출할 수 있는 하위 집합만 확인한 것이다. 100점이 WCAG 준수와 같지 않고, 낮은 점수도 그 자체로 이슈 증거를 대체하지 않는다[SKILL-WEB-A11Y]. 통과 판정은 점수가 아니라 §13의 감사 루프(키보드 조작·스크린리더 확인 포함)로 내린다.
**표준 기반 평가는 사용자 평가로 보완한다.** W3C 자신이 표준 기반 적합성 평가와 실제 사용자 평가를 함께 써야 한다고 설명한다 — 적은 표본이나 한 번의 평가를 모든 사용자에게 일반화하지 않는다[W3C-USER-EVAL]. 자동 검사·수동 APG 대조·스크린리더 확인을 전부 통과했더라도, 실사용자 피드백이 오면 그것으로 규칙을 다시 검토한다.
**APCA는 규범이 아니다.** 대비의 하드 게이트는 WCAG 2 비율이다. APCA는 2026년 기준으로도 WCAG 3 초안에 이름조차 실려 있지 않고 자체 문서가 스스로를 beta로 표시하는 평가 후보일 뿐이다[APCA-STATUS] — 상세는 [color.md](color.md) §6.
---
## 1. 시맨틱·네이티브 우선
**하드 게이트.** ARIA를 쓰기 전에 같은 의미·동작을 가진 네이티브 HTML 요소가 있는지 먼저 확인한다. 다섯 가지 ARIA 원칙이다[SKILL-BETTER-A11Y]:
1. 필요한 시맨틱·동작을 가진 네이티브 요소가 있으면 다른 요소를 ARIA로 흉내 내지 않고 그것을 쓴다.
2. 정말 필요하지 않으면 네이티브 시맨틱을 바꾸지 않는다.
3. 인터랙티브 ARIA 컨트롤은 반드시 키보드로 조작할 수 있어야 한다 — role은 그 위젯의 전체 키보드 모델을 지키겠다는 약속이다.
4. 포커스를 받는 요소에 `role="presentation"`이나 `aria-hidden="true"`를 걸지 않는다.
5. 모든 인터랙티브 요소는 접근 가능한 이름을 가져야 한다(§2).
나쁜 ARIA보다 ARIA가 없는 편이 낫다. 스크린리더는 role을 그대로 믿으므로, 틀린 role은 아무것도 없는 것보다 더 나쁘다.
| 요소 | 쓰는 곳 | 이유 |
|---|---|---|
| `` | 이동 — 어딘가로 가거나 URL이 바뀌는 모든 것 | Cmd/Ctrl/가운데 클릭, 우클릭으로 링크 복사, Enter로 활성화가 전부 공짜다 |
| `