ARIA 접근성 가이드

속성 · 위젯 상태

aria-modal

대화상자가 모달이라서, 열려 있는 동안 바깥 콘텐츠를 사용할 수 없다는 것을 알립니다.

중급

한눈에 보기

구분
속성 (Property)
분류
위젯 상태
값 형식
true / false
기본값
false
적용 범위
특정 역할에만 사용
HTML 대체
<dialog>의 showModal() (바깥 콘텐츠를 자동으로 비활성화)

설명

aria-modal="true"는 dialog나 alertdialog가 모달이라는 것, 즉 열려 있는 동안 대화상자 바깥의 콘텐츠는 사용할 수 없다는 것을 보조기술에 알립니다. 이를 지원하는 화면낭독기는 가상 커서가 대화상자 밖으로 나가지 않도록 바깥 콘텐츠를 탐색 대상에서 제외합니다.

이 속성은 실제로 바깥을 막아 주지 않습니다. 모달이라고 알렸다면 작성자가 다음을 모두 구현해야 합니다. 열릴 때 대화상자 안으로 포커스 이동, Tab·Shift+Tab이 대화상자 안에서만 순환(포커스 가두기), Esc로 닫기, 닫은 뒤 대화상자를 연 요소로 포커스 복귀, 바깥 콘텐츠의 시각적 가림(배경 막). 이 중 하나라도 빠지면 키보드 사용자가 대화상자 뒤의 요소로 빠져나가거나, 화면낭독기 사용자가 대화상자를 찾지 못하게 됩니다.

가능하면 HTML <dialog> 요소를 showModal()로 여는 방법을 우선 검토합니다. 바깥 콘텐츠가 자동으로 비활성(inert)되고 Esc 닫기도 기본 제공되며, 브라우저가 모달 상태를 접근성 API에 전달하므로 aria-modal을 따로 쓸 필요가 없습니다. 사용자 정의 대화상자를 쓴다면 aria-modal="true"와 함께 바깥 콘텐츠에 inert를 설정하는 방식이 가장 확실합니다.

바깥 콘텐츠를 계속 사용할 수 있는 비모달 대화상자(채팅 창, 찾기 패널 등)에는 true를 쓰면 안 됩니다. 사용할 수 있는 콘텐츠가 화면낭독기에서 사라지기 때문입니다. 또한 대화상자에는 aria-labelledby(제목)로 이름을 주고, 필요하면 aria-describedby로 안내 문구를 연결합니다.

테스트할 때는 대화상자가 열린 상태에서 Tab을 계속 눌러도 바깥으로 포커스가 나가지 않는지, 화면낭독기의 가상 커서(방향키)로 바깥 내용이 읽히지 않는지, Esc로 닫히고 원래 버튼으로 포커스가 돌아오는지 확인합니다.

값

값
값의미
true모달입니다. 대화상자가 열려 있는 동안 바깥 콘텐츠는 사용할 수 없습니다.
false 기본값모달이 아닙니다. 바깥 콘텐츠도 계속 사용할 수 있습니다.

사용 예

네이티브 모달 대화상자 (권장)

권장HTML
<button type="button" id="open">배송지 변경</button>
<dialog id="dlg" aria-labelledby="dlg-title">
  <h2 id="dlg-title">배송지 변경</h2>
  …
  <button type="button" id="close">닫기</button>
</dialog>
<script>
  open.addEventListener('click', function () { dlg.showModal(); });
  close.addEventListener('click', function () { dlg.close(); });
</script>

showModal()은 바깥을 자동으로 비활성화하고 Esc 닫기를 제공합니다. 닫은 뒤 포커스도 연 버튼으로 돌아갑니다.

사용자 정의 모달 대화상자

HTML
<div role="dialog" aria-modal="true" aria-labelledby="dlg-title" aria-describedby="dlg-desc">
  <h2 id="dlg-title">변경 사항을 저장할까요?</h2>
  <p id="dlg-desc">저장하지 않으면 입력한 내용이 사라집니다.</p>
  <button type="button">저장</button>
  <button type="button">취소</button>
</div>

열고 닫을 때 처리

JavaScript
var opener;
function openDialog(dlg) {
  opener = document.activeElement;
  document.getElementById('page').inert = true;   // 바깥 비활성
  dlg.hidden = false;
  dlg.querySelector('input, button').focus();       // 안으로 포커스 이동
}
function closeDialog(dlg) {
  dlg.hidden = true;
  document.getElementById('page').inert = false;
  opener.focus();                                   // 포커스 복귀
}

포커스 관리 없이 속성만 사용 (비권장)

비권장HTML
<div class="layer-popup" role="dialog" aria-modal="true">
  <p>이벤트 안내</p>
  <a href="#" class="close">닫기</a>
</div>

이름이 없고, 열릴 때 포커스가 이동하지 않으며 Tab으로 뒤쪽 콘텐츠에 갈 수 있다면 모달이라는 정보와 실제 동작이 어긋납니다.

직접 해 보기

“배송지 변경”을 누르면 모달 대화상자가 열립니다. Tab이 대화상자 안에서만 순환하는지, Esc로 닫히고 버튼으로 포커스가 돌아오는지 확인해 보세요.

화면낭독기에서는

화면낭독기 안내 예시 (표현은 화면낭독기·브라우저·버전에 따라 조금씩 다릅니다)
상황들리는 안내 (예)
모달 대화상자가 열리고 주소 입력란으로 포커스 이동배송지 변경, 대화 상자, 새 배송지를 입력하세요. Esc를 누르면 닫힙니다. 주소, 편집 창
대화상자 안에서 가상 커서로 끝까지 이동(대화상자 밖의 내용은 읽히지 않음)
Esc로 닫은 뒤배송지 변경, 버튼, 대화 상자 열기

사용 지침

이렇게 쓰세요

  • 가능하면 <dialog>와 showModal()을 씁니다.
  • 사용자 정의 모달은 포커스 이동·가두기·Esc 닫기·포커스 복귀를 모두 구현합니다.
  • aria-labelledby로 대화상자에 이름을 줍니다.
  • 바깥 콘텐츠에는 inert를 설정해 실제로 사용할 수 없게 만듭니다.

이렇게 쓰지 마세요

  • 바깥을 계속 쓸 수 있는 비모달 대화상자에 true를 쓰지 않습니다.
  • dialog·alertdialog가 아닌 요소에 쓰지 않습니다.
  • 속성만 붙이고 포커스 관리를 생략하지 않습니다.
  • 바깥 콘텐츠를 숨기려고 aria-modal과 aria-hidden을 중복으로 복잡하게 관리하지 않습니다. inert가 더 단순합니다.

사용할 수 있는 역할

이 속성을 쓰는 패턴

참고 자료