ARIA 접근성 가이드

역할 · 복합 위젯

role="menu"

명령이나 설정을 고르는 메뉴 항목 목록입니다. 보통 메뉴 버튼이나 메뉴 막대에서 팝업으로 열립니다.

중급

한눈에 보기

분류
복합 위젯
대응 HTML
없음 (HTML <menu>는 목록 list 역할입니다)
이름 정하는 방법
작성자
이름 필수
아니요
필수 상위 요소
없음

설명

menu는 데스크톱 프로그램의 메뉴처럼 동작이나 설정을 고르는 목록입니다. 하위 요소는 menuitem, menuitemcheckbox, menuitemradio이며, 이 항목들을 묶는 group도 넣을 수 있습니다. 항목 사이 구분선은 separator를 씁니다. aria-orientation의 기본값은 세로입니다.

메뉴는 대개 button(메뉴 버튼, aria-haspopup="menu" + aria-expanded), menubar의 항목, 또는 오른쪽 클릭(컨텍스트 메뉴)으로 열립니다. 열리면 포커스가 메뉴 안 항목으로 이동하고, 닫히면 연 요소로 돌아가야 합니다. 이름은 필수는 아니지만 aria-labelledby로 메뉴를 연 버튼을 가리키면 좋습니다.

메뉴 역할이 필요 없는 경우가 많습니다

“메뉴”라고 부르는 UI 대부분은 ARIA menu가 아닙니다.

  • 사이트 내비게이션 드롭다운 → <nav> + 디스클로저 버튼(aria-expanded) + 링크 목록
  • 값 하나를 고르는 드롭다운 → <select> 또는 combobox/listbox
  • 버튼 몇 개를 묶은 막대 → toolbar

메뉴 역할을 쓰면 화면낭독기는 앱 메뉴 모드로 바뀌고 가상 커서 탐색이 제한됩니다. APG 키보드 규칙을 모두 구현할 수 있을 때만 씁니다.

테스터 관점

  • 메뉴가 열리면 첫 항목에 포커스가 가는지, Esc와 Tab으로 닫히는지 확인합니다.
  • 메뉴 버튼의 aria-expanded가 열림/닫힘과 일치하는지 확인합니다.
  • 메뉴 안에 메뉴 항목이 아닌 요소(일반 링크, 텍스트)가 섞여 있지 않은지 확인합니다.

함께 쓰는 속성

지원 속성

전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.

키보드 동작

키보드 동작
키동작
Enter(메뉴 버튼) 메뉴를 열고 첫 항목으로 이동합니다. (메뉴 항목) 실행하고 메뉴를 닫거나, 하위 메뉴를 엽니다.
Space(메뉴 버튼) 메뉴를 엽니다. (체크·라디오 항목) 상태를 바꿉니다.
↓(메뉴 버튼, 선택 사항) 메뉴를 열고 첫 항목으로 이동합니다. (메뉴 안) 다음 항목으로 이동하며, 끝에서 처음으로 순환할 수 있습니다.
↑(메뉴 버튼, 선택 사항) 메뉴를 열고 마지막 항목으로 이동합니다. (메뉴 안) 이전 항목으로 이동합니다.
→하위 메뉴가 있는 항목에서 하위 메뉴를 열고 첫 항목으로 이동합니다.
←하위 메뉴 안에서 하위 메뉴를 닫고 부모 항목으로 돌아갑니다.
Home첫 항목으로 이동합니다.
End마지막 항목으로 이동합니다.
글자 키(선택 사항) 그 글자로 시작하는 다음 항목으로 이동합니다.
Esc메뉴를 닫고 메뉴를 연 요소로 포커스를 돌려보냅니다.
Tab모든 메뉴를 닫고 다음 포커스 요소로 이동합니다.

사용 예

메뉴 버튼 + 메뉴

HTML
<button type="button" id="more" aria-haspopup="menu" aria-expanded="false" aria-controls="more-menu">더 보기</button>
<ul role="menu" id="more-menu" aria-labelledby="more" hidden>
  <li role="menuitem" tabindex="-1">공유</li>
  <li role="menuitem" tabindex="-1">신고</li>
  <li role="separator"></li>
  <li role="menuitem" tabindex="-1">삭제</li>
</ul>

열고 닫기

JavaScript
function openMenu() {
  menu.hidden = false;
  btn.setAttribute('aria-expanded', 'true');
  menu.querySelector('[role="menuitem"]').focus();
}
function closeMenu() {
  menu.hidden = true;
  btn.setAttribute('aria-expanded', 'false');
  btn.focus();
}

내비게이션 드롭다운을 menu로 만드는 실수

비권장비권장
<button aria-haspopup="menu">고객센터</button>
<ul role="menu">
  <li role="menuitem"><a href="/faq">자주 묻는 질문</a></li>
</ul>

링크로 이동하는 하위 메뉴라면 <nav> 안에 aria-expanded 버튼과 일반 링크 목록을 둡니다(APG Disclosure Navigation).

직접 해 보기

“편집” 버튼으로 메뉴를 열고 ↑ ↓ Home End로 이동해 보세요. Enter로 실행하면 메뉴가 닫히고 포커스가 버튼으로 돌아옵니다. 버튼에서 ↑를 누르면 마지막 항목부터 열립니다.

화면낭독기에서는

화면낭독기 안내 예시 (표현은 화면낭독기·브라우저·버전에 따라 조금씩 다릅니다)
상황들리는 안내 (예)
메뉴 버튼에 포커스편집, 메뉴 버튼, 축소됨
메뉴를 엶편집, 메뉴, 잘라내기, 메뉴 항목, 1/4
Esc로 닫음편집, 메뉴 버튼, 축소됨

사용 지침

이렇게 쓰세요

  • 메뉴 항목·그룹·구분선만 자식으로 두고, 사이의 <li> 래퍼에는 role="none"을 줍니다.
  • 열 때 포커스를 메뉴 안으로, 닫을 때 연 요소로 옮깁니다.
  • 메뉴를 여는 버튼에 aria-haspopup="menu"와 aria-expanded를 씁니다.

이렇게 쓰지 마세요

  • 사이트 내비게이션이나 값 선택 드롭다운에 쓰지 않습니다.
  • 메뉴 안에 일반 링크·입력란을 섞지 않습니다.
  • 메뉴가 열려 있을 때 Tab으로 항목 사이를 이동하게 하지 않습니다.

이 역할을 쓰는 패턴

참고 자료