WCAG 2.2 · 4. 견고성 · 4.1 호환성
4.1.2 이름, 역할, 값
Name, Role, Value
모든 사용자 인터페이스 구성 요소는 이름과 역할을 프로그램이 알 수 있어야 하고, 사용자가 바꾸는 상태·속성·값과 그 변화도 보조 기술에 전달되어야 합니다. ARIA가 해결하려는 문제의 핵심입니다.
한눈에 보기
- 성공 기준
- 4.1.2 이름, 역할, 값
- 수준
- 수준 A
- 원칙
- 4. 견고성
- 지침
- 4.1 호환성
- 도입
- WCAG 2.0
요구 사항
폼 요소, 링크, 스크립트로 만든 구성 요소를 포함한 모든 사용자 인터페이스 구성 요소에 대해 다음이 성립해야 합니다.
- 이름(name)과 역할(role)을 프로그램이 판별할 수 있습니다. — "무엇이라고 부르는가", "무엇인가(버튼, 체크박스, 탭…)"
- 사용자가 설정할 수 있는 상태(state), 속성(property), 값(value)을 프로그램이 설정할 수 있습니다. — 체크됨, 펼쳐짐, 선택됨, 슬라이더 값 등
- 이 항목들이 바뀌었다는 알림이 보조 기술을 포함한 사용자 에이전트에 전달됩니다.
원문 주석에 따르면 이 기준은 주로 직접 사용자 인터페이스 구성 요소를 개발하거나 스크립트로 만드는 작성자를 위한 것입니다. 표준 HTML 컨트롤(<button>, <input>, <select>, <a href>)을 명세대로 쓰면 브라우저가 이름·역할·상태를 자동으로 제공하므로 대부분 충족됩니다. 문제는 <div>, <span>으로 만든 커스텀 위젯입니다. 이때 role, aria-* 속성으로 정보를 직접 제공해야 합니다.
왜 필요한가요
화면낭독기, 음성 인식, 스위치 제어 같은 보조 기술은 화면의 모양을 보지 않습니다. 브라우저가 운영체제 접근성 API로 넘겨 주는 정보(접근성 트리)만 사용합니다. 겉모습이 버튼이어도 <div>라면 보조 기술에는 "그냥 텍스트"이고, 펼침 메뉴가 열려도 aria-expanded가 바뀌지 않으면 열렸는지 알 수 없습니다.
- 이름이 없으면: 아이콘 버튼이 "버튼"이라고만 읽혀 무슨 기능인지 모릅니다.
- 역할이 없으면: 누를 수 있는 요소인지 몰라 지나치며, 음성 인식 사용자는 "버튼 클릭"으로 실행할 수 없습니다.
- 상태가 없으면: 체크박스가 선택됐는지, 탭이 선택됐는지, 메뉴가 펼쳐졌는지 알 수 없습니다.
도움받는 사용자
- 시각장애인(화면낭독기 사용자)
- 음성 인식 사용자(이름으로 컨트롤을 호출)
- 스위치·대체 입력 장치 사용자
- 점자 단말기 사용자
적용 방법
1. 가능하면 네이티브 HTML 요소를 씁니다
ARIA의 첫 번째 규칙은 "같은 의미의 HTML 요소가 있으면 그것을 쓴다"입니다. <button>은 이름(콘텐츠), 역할(button), 키보드 동작, 포커스를 모두 기본으로 갖습니다.
<div class="btn" onclick="save()">저장</div><button type="button" onclick="save()">저장</button>2. 커스텀 위젯에는 역할·이름·상태를 모두 제공합니다
어쩔 수 없이 커스텀 요소를 쓴다면 role, 접근 가능한 이름, 필요한 상태 속성, tabindex, 키보드 동작을 모두 구현해야 합니다. 역할만 붙이면 키보드 동작이 따라오지 않습니다.
<span role="checkbox" tabindex="0" aria-checked="false"
aria-labelledby="agree-label" id="agree"></span>
<span id="agree-label">이용 약관에 동의합니다</span>var box = document.getElementById('agree');
function toggle() {
var on = box.getAttribute('aria-checked') === 'true';
box.setAttribute('aria-checked', String(!on)); // 상태 변화 → 보조 기술에 전달
}
box.addEventListener('click', toggle);
box.addEventListener('keydown', function (e) {
if (e.key === ' ') { e.preventDefault(); toggle(); }
});자세한 구현은 체크박스 패턴을 참고하세요. 네이티브 <input type="checkbox">를 쓰면 이 코드가 전부 필요 없습니다.
3. 아이콘만 있는 컨트롤에 이름을 줍니다
<button type="button"><svg>...</svg></button><button type="button" aria-label="검색">
<svg aria-hidden="true" focusable="false">...</svg>
</button>4. 상태가 바뀌면 속성도 함께 바꿉니다
화면 상태와 ARIA 상태가 항상 같아야 합니다. 보이는 모양만 바꾸고 속성을 갱신하지 않는 것이 가장 흔한 실패입니다.
<!-- 펼침 버튼 (Disclosure) -->
<button type="button" aria-expanded="false" aria-controls="faq1">배송은 얼마나 걸리나요?</button>
<div id="faq1" hidden>주문 후 2~3일 안에 도착합니다.</div>
<!-- 토글 버튼 -->
<button type="button" aria-pressed="false">음소거</button>
<!-- 탭 -->
<div role="tablist" aria-label="상품 정보">
<button role="tab" id="t1" aria-selected="true" aria-controls="p1">상세 정보</button>
<button role="tab" id="t2" aria-selected="false" aria-controls="p2" tabindex="-1">리뷰</button>
</div>
<div role="tabpanel" id="p1" aria-labelledby="t1">...</div>btn.addEventListener('click', function () {
var open = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!open));
panel.hidden = open;
});5. 값을 가진 위젯은 값을 노출합니다
<div role="slider" tabindex="0" aria-label="음량"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="40"
aria-valuetext="40퍼센트"></div>가능하면 <input type="range">를 쓰고, 커스텀 구현은 슬라이더 패턴을 참고합니다.
사례
span으로 만든 링크
<span class="link" onclick="location.href='/notice'">공지사항</span>역할이 없어 링크로 인식되지 않고, 포커스도 받지 못합니다. <a href="/notice">를 씁니다.
포커스 가능한 요소를 aria-hidden으로 숨김
<div aria-hidden="true">
<button type="button">닫기</button>
</div>키보드로 포커스는 가지만 화면낭독기에는 이름·역할이 전달되지 않습니다. 콘텐츠 숨기기 가이드를 참고하세요.
모양만 바뀌는 선택 상태
<li class="tab is-active">상세 정보</li>
<li class="tab">리뷰</li>탭 역할과 aria-selected가 없어 어떤 탭이 선택됐는지 알 수 없습니다.
보이는 이름과 접근 가능한 이름 일치
<button type="button" aria-describedby="del-hint">삭제</button>
<p id="del-hint">삭제한 항목은 복구할 수 없습니다.</p>이름은 보이는 텍스트 "삭제"를 그대로 쓰고, 추가 정보는 설명으로 연결합니다(2.5.3 레이블과 이름도 함께 충족).
자주 하는 실수
<div>,<span>에 클릭 이벤트만 붙여 버튼·링크를 만들고 역할을 주지 않습니다.- 아이콘 버튼, 이미지 링크, 레이블 없는 입력 필드처럼 접근 가능한 이름이 비어 있습니다.
- 펼침·선택·체크 상태가 화면에서는 바뀌는데
aria-expanded,aria-selected,aria-checked는 그대로입니다. - 포커스를 받을 수 있는 요소를
aria-hidden="true"영역 안에 두거나,role="presentation"으로 의미를 지웁니다.
검사 방법
- 브라우저 개발자 도구의 접근성 패널(Chrome Accessibility, Firefox 접근성 검사기)에서 각 컨트롤의 이름(Name)과 역할(Role)을 확인합니다.
- 커스텀 위젯을 조작하며 상태 속성(
aria-expanded,aria-checked,aria-selected,aria-valuenow등)이 화면 상태와 함께 바뀌는지 확인합니다. - 화면낭독기(NVDA 등)로 각 컨트롤에 포커스해 "이름, 역할, 상태"가 읽히고, 조작 후 바뀐 상태가 안내되는지 확인합니다.
- axe 같은 자동 검사 도구로 이름 없는 버튼·링크·폼 컨트롤, 잘못된 ARIA 속성을 찾습니다.
관련 ARIA
aria-labelaria-labelledbyaria-describedbyaria-expandedaria-pressedaria-checkedaria-selectedaria-currentaria-disabledaria-haspopuparia-controlsaria-valuenowaria-valueminaria-valuemaxaria-valuetextaria-hiddenaria-invalidaria-requiredbuttonlinkcheckboxradioswitchtabtablisttabpanelslidercomboboxlistboxoptionmenumenuitemdialog