암묵적 역할(implicit role)과 암묵적 상태는 개발자가 적지 않아도 브라우저가 계산해서 접근성 트리에 올린다. 아래 표는 HTML-AAM 기준이며, 브라우저별 소소한 차이가 있다. 모든 표를 보기 전 항상 적용되는 원칙은 다음과 같다.
<input required aria-required="true"> 에서 required 로 input의 속성을 넣으면, 암묵적으로 aria-required=”true” 또한 알아서 작성되기에 중복이며, 이는 비권장 되는 패턴이다.role과 aria-*는 의미(역할·이름·상태·관계)만 바꾼다. 포커스, 키보드, 폼 제출 같은 동작은 태그가 준다.<div>, <span>, <b>, <i> 등)는 generic이며 아무 의미도 전달하지 않는다.시각 사용자(우리와 같은 일반인)는 페이지를 한눈에 훑고 원하는 곳으로 바로 갑니다. 스크린 리더 사용자는 그게 안 됩니다. 기본 동작은 문서를 위에서 아래로 한 요소씩 순서대로 읽는 것이라, 아무 장치가 없으면 본문에 가기 위해 헤더의 로고, 메뉴 30개, 검색창을 다 지나야 합니다.
그래서 스크린 리더는 특정 종류의 요소로 바로 건너뛰는 단축키를 제공합니다. NVDA에서 H를 누르면 다음 헤딩으로, K를 누르면 다음 링크로, D를 누르면 다음 랜드마크로 이동합니다. VoiceOver는 로터(VO+U)를 돌려 "랜드마크" 목록을 띄우고 그중 하나를 고릅니다. "점프 대상"이라는 건 이 목록에 등재된다는 뜻입니다.
랜드마크가 페이지의 큰 구역을 나타내니, 이 단축키 하나로 "헤더 → 내비게이션 → 본문 → 사이드바 → 푸터"를 순식간에 오갈 수 있습니다. 시각 사용자가 눈으로 레이아웃을 파악하는 것과 같은 일을 D키 몇 번으로 하는 겁니다. <main>이 있으면 D 한 번에 본문으로 갑니다. 그러나 항상 section이나, header 와 같은 랜드마크를 사용한다고 해서 바로 넘어가지는 않습니다.
<section>, <form>은 이름이 있을 때만
로터에 랜드마크 목록이 뜰 때 각 항목은 이름으로 표시됩니다. "내비게이션", "본문", "검색"처럼요.
<section>이 무조건 랜드마크가 되면 페이지에 있는<section>열 개가 전부 "영역, 영역, 영역, 영역…"으로 뜹니다. 이는div를 굳이 전부 다 읽지 않는 것처럼, 브라우저는aria-label이나aria-labelledby로 이름을 준<section>만 region 랜드마크로 올리고, 이름 없는 건div취급합니다.<form>도 마찬가지로 "로그인", "검색"처럼 이름이 있어야 form 랜드마크가 됩니다.
<header>, <footer>, <aside>는 섹셔닝 요소 안에서 강등
<header>의 랜드마크 역할은 banner, 즉 "페이지 전체의 머리"입니다. 그런데<article>안에도<header>를 씁니다. 글 제목과 작성일을 묶는 용도로요. 이걸 전부 banner로 올리면 블로그 목록 페이지에서 "배너"가 스무 개 뜹니다. 그래서<header>가<article>,<section>,<main>,<nav>,<aside>안에 있으면 브라우저가 랜드마크가 아닌 generic으로 처리합니다. 페이지 최상위(<body>바로 아래)에 있는 것만 banner입니다.<footer>와<aside>도 같은 논리입니다.
요약하면, 랜드마크는 "페이지 지도의 항목"이고, 지도가 쓸모 있으려면 항목 수가 적고 이름이 있어야 하기 때문에 두 조건이 붙는 겁니다.
| 태그 | 암묵적 역할 | 조건·작용 |
|---|---|---|
<main> |
main | "본문으로 건너뛰기" 대상. 페이지에 하나 |
<nav> |
navigation | 여러 개면 aria-label로 구분 ("주 메뉴", "푸터") |
<header> |
banner | <article>·<section>·<main> 등 안에 있으면 generic |
<footer> |
contentinfo | 같은 조건으로 generic |
<aside> |
complementary | 최신 초안에서는 섹셔닝 요소 안에 있으면 generic |
<section> |
region | aria-label/aria-labelledby가 있을 때만. 없으면 generic |
<form> |
form | 이름이 있을 때만 랜드마크로 노출 |
<search> |
search | 최근 추가된 태그. 검색 영역 |
<article> |
article | 랜드마크는 아니지만 독립 콘텐츠 단위로 탐색 가능 |
헤딩은 aria-level을 자동으로 갖고 H키·숫자키로 점프된다. <strong>, <em>, <code>는 트리에 올라가지만 대부분의 스크린 리더가 기본 설정에서 읽지 않는다.
| 태그 | 암묵적 역할 | 암묵적 속성·작용 |
|---|---|---|
<h1>~<h6> |
heading | aria-level = 1~6. H키로 점프, 1~6키로 레벨별 점프 |
<p> |
paragraph | 단락 단위 이동 |
<blockquote> |
blockquote | "인용" 컨텍스트 |
<hr> |
separator | aria-orientation="horizontal" 기본 |
<strong> / <em> |
strong / emphasis | 기본 설정에서 대부분 읽지 않음 |
<code> |
code | 위와 같음 |
<del> / <ins> |
deletion / insertion | 편집 표시 |
<time> |
time | datetime 값은 전달 안 됨, 텍스트만 |
<div> / <span> |
generic | 역할 없음. 레이아웃용은 트리에서 대부분 잘려 나감 |