기본 개념
HTML 요소와 ARIA 매핑
대부분의 HTML 요소는 암묵적 역할을 가집니다. 요소별 기본 역할과, ARIA in HTML 명세가 정한 허용·금지 규칙, 중복 지정을 피하는 방법을 정리합니다.
암묵적 역할이란
암묵적 역할(implicit role)은 role 속성을 쓰지 않아도 HTML 요소가 기본으로 가지는 역할입니다. 예를 들어 <button>은 처음부터 button 역할을 가지고, <nav>는 navigation 랜드마크입니다. 이 대응 관계는 HTML-AAM이 브라우저 기준으로, ARIA in HTML이 작성자 기준으로 정합니다.
<nav role="navigation">
<ul role="list">
<li role="listitem"><a href="/" role="link">홈</a></li>
</ul>
</nav><nav>
<ul>
<li><a href="/">홈</a></li>
</ul>
</nav>일부 요소는 문맥에 따라 역할이 달라집니다. <header>와 <footer>는 페이지 전체에 속할 때만 banner, contentinfo 랜드마크가 되고, <article>이나 <section> 안에 있으면 generic이 됩니다. <section>은 이름(aria-label, aria-labelledby)이 있을 때만 region 랜드마크가 됩니다.
주요 요소의 암묵적 역할 표
아래 표는 ARIA in HTML 명세를 요약한 것입니다. “모든 역할”은 어떤 역할이든 지정할 수 있다는 뜻이고, “역할 지정 불가”는 role 속성을 쓰면 안 된다는 뜻입니다. “없음”은 대응하는 ARIA 역할이 없다는 뜻으로, 브라우저가 플랫폼 고유 역할로 노출하거나 노출하지 않습니다.
| HTML 요소 | 암묵적 역할 | 지정할 수 있는 역할 |
|---|---|---|
<a href> | link | button checkbox menuitem menuitemcheckbox menuitemradio option radio switch tab treeitem |
<a> (href 없음) | generic | 모든 역할 |
<abbr> | 없음 | 모든 역할 |
<address> | group | 모든 역할 |
<area href> | link | 역할 지정 불가 |
<article> | article | application document feed main none presentation region |
<aside> | complementary (body·main 바로 아래이거나 이름이 있을 때. 그 밖의 경우 generic) | feed none note presentation region search |
<audio>, <video> | 없음 | application |
<b>, <i>, <u>, <small> | generic | 모든 역할 |
<blockquote> | blockquote | 모든 역할 |
<body> | generic | 역할 지정 불가 |
<br> | 없음 | none presentation |
<button> | button | checkbox combobox gridcell link menuitem menuitemcheckbox menuitemradio option radio separator slider switch tab treeitem |
<caption> | caption | 역할 지정 불가 |
<code> | code | 모든 역할 |
<datalist> | listbox | 역할 지정 불가 |
<dd> | definition | 역할 지정 불가 |
<del>, <s> | deletion | 모든 역할 |
<details> | group | 역할 지정 불가 |
<dfn> | term | 모든 역할 |
<dialog> | dialog | alertdialog |
<div> | generic | 모든 역할 (dl의 자식이면 none·presentation만) |
<dl> | 없음 | group list none presentation |
<dt> | term | listitem |
<em> | emphasis | 모든 역할 |
<fieldset> | group | none presentation radiogroup |
<figure> | figure | figcaption이 없을 때 모든 역할 |
<footer> | contentinfo (body 범위일 때. article·aside·main·nav·section 안이면 generic) | group none presentation |
<form> | form (접근 가능한 이름이 있을 때 랜드마크로 노출) | none presentation search |
<h1> ~ <h6> | heading + aria-level | none presentation tab |
<header> | banner (body 범위일 때. 그 밖에는 generic) | group none presentation |
<hgroup> | group | 모든 역할 |
<hr> | separator | none presentation |
<html> | document | 역할 지정 불가 |
<iframe> | 없음 | application document img none presentation |
<img alt=""> | presentation | none presentation |
<img alt="텍스트"> | img | button checkbox link menuitem menuitemcheckbox menuitemradio meter option progressbar radio scrollbar separator slider switch tab treeitem |
<input type="button|submit|reset|image"> | button | 제한적 (type에 따라 다름) |
<input type="checkbox"> | checkbox | menuitemcheckbox option switch, button (aria-pressed와 함께) |
<input type="radio"> | radio | menuitemradio |
<input type="text"> (list 없음) | textbox | combobox searchbox spinbutton |
<input type="email|tel|url"> (list 없음) | textbox | 역할 지정 불가 |
<input type="search"> (list 없음) | searchbox | 역할 지정 불가 |
<input list="…"> (text·search·email·tel·url) | combobox | 역할 지정 불가 |
<input type="number"> | spinbutton | 역할 지정 불가 |
<input type="range"> | slider | 역할 지정 불가 |
<input type="password"> | 없음 | 역할 지정 불가 |
<ins> | insertion | 모든 역할 |
<label>, <legend> | 없음 | 역할 지정 불가 |
<li> | listitem (ol·ul·menu의 자식일 때) | 모든 역할 |
<main> | main | 역할 지정 불가 |
<math> | math | 역할 지정 불가 |
<menu>, <ol>, <ul> | list | group listbox menu menubar none presentation radiogroup tablist toolbar tree |
<meter> | meter | 역할 지정 불가 |
<nav> | navigation | menu menubar none presentation tablist |
<optgroup> | group | 역할 지정 불가 |
<option> | option | 역할 지정 불가 |
<output> | status | 모든 역할 |
<p> | paragraph | 모든 역할 |
<pre> | generic | 모든 역할 |
<progress> | progressbar | 역할 지정 불가 |
<search> | search | form group none presentation region |
<section> | region (접근 가능한 이름이 있을 때. 없으면 generic) | 여러 랜드마크·창·라이브 리전 역할 등 |
<select> (multiple·size 없음) | combobox | menu |
<select multiple> 또는 size > 1 | listbox | 역할 지정 불가 |
<span> | generic | 모든 역할 |
<strong> | strong | 모든 역할 |
<sub>, <sup> | subscript / superscript | 모든 역할 |
<summary> | 없음 (브라우저는 보통 펼침 버튼처럼 노출) | 역할 지정 불가 |
<svg> | graphics-document | 모든 역할 |
<table> | table | 모든 역할 |
<thead>, <tbody>, <tfoot> | rowgroup | 모든 역할 |
<tr> | row | 모든 역할 |
<td> | cell (grid·treegrid 안이면 gridcell) | 모든 역할 |
<th> | columnheader / rowheader (위치·scope에 따라) | 모든 역할 |
<textarea> | textbox (aria-multiline="true") | 역할 지정 불가 |
<time> | time | 모든 역할 |
표를 읽을 때
DPub-ARIA(doc-*) 역할과 일부 세부 조건은 생략했습니다. 허용 역할이 “모든 역할”이라도 규칙 2에 따라 꼭 필요할 때만 바꾸세요. 최신·전체 목록은 ARIA in HTML 원문을 확인하세요.
허용되는 역할과 금지되는 역할
ARIA in HTML은 요소마다 지정할 수 있는 역할을 제한합니다. 원래 의미와 동작이 너무 다른 역할로 바꾸면 사용자 기대와 실제 동작이 어긋나기 때문입니다.
<button role="heading">공지사항</button>
<input type="checkbox" role="button">
<main role="navigation">…</main>
<label role="button">파일 선택</label><button role="tab" aria-selected="true">공지사항</button>
<input type="checkbox" role="switch">
<nav aria-label="주 메뉴">…</nav>
<button type="button">파일 선택</button><main>,<label>,<input type="number">,<textarea>,<select multiple>,<progress>처럼 역할을 지정할 수 없는 요소가 있습니다.<input type="checkbox">에는switch,menuitemcheckbox,option처럼 의미가 가까운 역할만 허용됩니다.<img alt="">는 장식 이미지로 간주되어none/presentation외의 역할을 쓸 수 없습니다.
중복 지정 금지
ARIA in HTML은 작성자가 암묵적 의미와 같은 role이나 aria-* 값을 다시 지정하지 말라고 권고합니다. 명세 예시는 <button role="button">을 “피해야 할 코드”로 듭니다. 중복 지정은 동작상 큰 문제는 없지만 코드를 읽기 어렵게 하고, 요소를 바꿀 때 잘못된 역할이 남는 원인이 됩니다.
<button role="button">저장</button>
<h2 role="heading" aria-level="2">공지</h2>
<input type="text" aria-required="true" required>
<main role="main">…</main><button>저장</button>
<h2>공지</h2>
<input type="text" required>
<main>…</main>예외: 오래된 브라우저 대응
과거에는 <main role="main">처럼 HTML5 요소를 지원하지 않는 브라우저를 위해 역할을 함께 쓰기도 했습니다. 현재 주요 브라우저는 모두 HTML 랜드마크 요소를 지원하므로 필요하지 않습니다. 단, CSS list-style: none을 적용한 목록을 Safari가 목록으로 노출하지 않는 문제 때문에 <ul role="list">를 쓰는 경우는 실무에서 흔히 허용됩니다.
네이티브 속성과 ARIA 속성의 충돌
HTML에 이미 같은 기능의 속성이 있으면 네이티브 속성을 씁니다. 두 가지를 함께 쓰면서 값이 다르면 보조기술이 엇갈린 정보를 받습니다. ARIA in HTML은 <input type="checkbox">에 aria-checked를 쓰는 것을 금지합니다.
<input type="checkbox" checked aria-checked="false">
<button disabled aria-disabled="false">전송</button>
<input type="text" required aria-required="false"><input type="checkbox" checked>
<button disabled>전송</button>
<input type="text" required>| ARIA 속성 | 먼저 쓸 HTML 속성 |
|---|---|
aria-checked | checked (체크박스·라디오) |
aria-disabled | disabled |
aria-required | required |
aria-readonly | readonly |
aria-hidden | hidden (화면과 보조기술 모두에서 숨길 때) |
aria-placeholder | placeholder |
aria-valuemin / aria-valuemax / aria-valuenow | min / max / value |
aria-colspan / aria-rowspan | colspan / rowspan |
aria-multiselectable | multiple (<select>) |
aria-disabled가 더 나은 경우
disabled 버튼은 포커스를 받지 못해 화면낭독기 사용자가 존재를 알기 어렵습니다. 비활성 이유를 알려야 하거나 포커스를 유지해야 할 때는 disabled 대신 aria-disabled="true"를 쓰고, 클릭 동작을 스크립트로 막는 방법도 씁니다. 이때는 두 속성을 함께 쓰지 않습니다.
이름을 붙일 수 없는 요소
generic 역할로 노출되는 <div>, <span>처럼 이름이 금지된(naming prohibited) 요소에는 aria-label과 aria-labelledby를 쓰면 안 됩니다. 브라우저·화면낭독기에 따라 무시되거나 일관되지 않게 읽힙니다. paragraph, code, strong, emphasis, presentation, none 등도 이름이 금지된 역할입니다.
<div aria-label="공지 영역">…</div>
<span aria-label="필수">*</span><section aria-label="공지">…</section>
<span aria-hidden="true">*</span><span class="sr-only">필수</span>매핑 확인 방법
- 브라우저 개발자 도구 접근성 패널에서 계산된 역할을 확인합니다(접근성 트리 보기).
- Nu HTML Checker는 ARIA in HTML 규칙 위반(허용되지 않는 역할, 중복 역할)을 경고합니다.
- axe 같은 자동 검사 도구로
aria-allowed-role,aria-prohibited-attr규칙 위반을 찾을 수 있습니다(검사 도구).