역할 · 창
role="dialog"
본문 위에 따로 뜨는 대화상자(창)입니다. 레이어 팝업·모달 창이 여기에 해당하며, HTML <dialog>에 대응합니다.
한눈에 보기
- 분류
- 창
- 대응 HTML
<dialog>(모달은showModal()로 열기)- 이름 정하는 방법
- 작성자 (author)
- 이름 필수
- 예
- 필수 상위 요소
- 없음
- 필수 하위 요소
- 없음
설명
dialog는 웹 애플리케이션의 주 창(웹 문서 전체) 위에 뜨는 하위 창입니다. 사용자에게 정보를 입력받거나 응답을 요청할 때 씁니다. 흐름을 막고 응답을 받아야 하는 대화상자는 보통 모달(뒤 내용을 조작할 수 없음)이고, 옆에 띄워 두고 본문과 오가며 쓰는 대화상자는 비모달입니다.
HTML <dialog>를 먼저
<dialog> 요소를 showModal()로 열면 브라우저가 다음을 자동으로 처리합니다.
- 대화상자 밖의 내용을
inert로 만들어 포커스·클릭·화면낭독기 탐색에서 제외 - 열릴 때 대화상자 안으로 포커스 이동(
autofocus가 있으면 그 요소) - Esc로 닫기, 최상위 레이어(top layer)에 표시,
::backdrop제공 - 닫을 때 열기 전 포커스가 있던 요소로 포커스 복귀(HTML 명세에 포함, 최신 브라우저 지원)
show()로 열면 비모달 대화상자가 됩니다. <dialog>를 쓸 때도 이름(aria-labelledby)은 직접 지정해야 합니다.
ARIA로 만들 때 해야 할 일
- 이름 필수: 보이는 제목을
aria-labelledby로 연결하거나aria-label을 줍니다. - 설명(선택): 짧은 안내 문구가 있으면
aria-describedby로 연결합니다. 양식·표처럼 구조가 있는 긴 내용은 연결하지 않습니다(한 번에 길게 읽히므로). - 모달 표시:
aria-modal="true"로 대화상자 밖 내용이 비활성임을 알립니다. 실제로도 밖을 조작할 수 없게(포커스 가두기, 배경inert) 만들어야 합니다. - 포커스 관리: 열 때 안의 요소로 포커스를 옮기고(첫 조작 요소, 또는 내용이 길면 제목 같은 정적 요소에
tabindex="-1"), 닫을 때 연 버튼으로 돌려보냅니다. 명세는 모달·비모달 모두 포커스 가능한 요소를 하나 이상 두라고 권장합니다. - 닫기 수단: Esc와 보이는 닫기 버튼을 제공합니다.
주의할 점
- 여기서 말하는 “애플리케이션”은
application역할과 무관합니다. 대화상자에 application 역할을 덧씌우지 않습니다. - 열려 있는 동안 배경 스크롤을 막고, 확대(200%·400%)했을 때도 대화상자 내용을 모두 볼 수 있게 합니다.
- 사용자 확인이 필요한 경고라면
alertdialog가 더 정확합니다.
테스터 관점
① 열릴 때 포커스가 대화상자 안으로 가고 “제목, 대화상자”가 읽히는지 ② Tab·Shift+Tab이 밖으로 새지 않는지 ③ 화면낭독기 가상 커서로도 배경 내용이 읽히지 않는지 ④ Esc로 닫히는지 ⑤ 닫은 뒤 포커스가 연 버튼으로 돌아오는지 확인합니다. 포커스 복귀 누락이 가장 흔한 결함입니다.
함께 쓰는 속성
지원 속성
전역 속성(이름·설명 등)은 모든 역할에 쓸 수 있어 생략했습니다.
키보드 동작
| 키 | 동작 |
|---|---|
| Tab | 대화상자 안의 다음 포커스 가능 요소로 이동합니다. 마지막 요소에서는 첫 요소로 돌아갑니다(모달일 때). |
| Shift + Tab | 이전 포커스 가능 요소로 이동합니다. 첫 요소에서는 마지막 요소로 갑니다(모달일 때). |
| Esc | 대화상자를 닫고 열기 전 요소로 포커스를 되돌립니다. |
사용 예
HTML dialog (권장)
<button type="button" id="open">대출 신청</button>
<dialog id="dlg" aria-labelledby="dlg-title">
<h2 id="dlg-title">대출 신청</h2>
<form method="dialog">
<label><input type="checkbox" name="remind"> 반납일 알림 받기</label>
<button value="cancel">취소</button>
<button value="ok">신청</button>
</form>
</dialog>
<script>
const dlg = document.getElementById('dlg');
document.getElementById('open').addEventListener('click', () => dlg.showModal());
</script><form method="dialog"> 안의 버튼은 대화상자를 닫고, 그 값이 dlg.returnValue에 남습니다.
div로 만든 모달 대화상자
<div role="dialog" aria-modal="true" aria-labelledby="d-t" aria-describedby="d-d">
<h2 id="d-t">대출 신청</h2>
<p id="d-d">어린 왕자를 14일 동안 대출합니다.</p>
…
<button type="button">닫기</button>
</div>포커스 이동·가두기·Esc 닫기·포커스 복귀는 스크립트로 직접 구현해야 합니다.
이름도 포커스 관리도 없는 레이어 (비권장)
<div class="layer-popup" style="display:block">
<div class="title">대출 신청</div>
…
<span class="close" onclick="closeLayer()">X</span>
</div>대화상자로 인식되지 않고, 닫기 요소는 키보드로 조작할 수 없으며, 포커스가 그대로 배경에 남습니다.
직접 해 보기
“대출 신청”을 눌러 보세요. 포커스가 대화상자 안으로 이동하고, Tab은 안에서만 돌며, Esc나 버튼으로 닫으면 포커스가 원래 버튼으로 돌아옵니다. 결과는 아래 상태 메시지로 알려 줍니다.
대출 신청
어린 왕자를 14일 동안 대출합니다.
실시간 코드 — 조작하면 속성 값이 바뀌는 모습을 볼 수 있습니다
화면낭독기에서는
| 상황 | 들리는 안내 (예) |
|---|---|
| 대화상자가 열림 (포커스가 체크박스로 이동) | 대출 신청, 대화상자, 어린 왕자를 14일 동안 대출합니다. 반납일 하루 전에 알림 받기, 체크 상자, 체크 안 됨 |
| “신청”으로 닫음 | 대출 신청, 버튼 … 대출을 신청했습니다. 반납일은 14일 뒤입니다. |
사용 지침
이렇게 쓰세요
- 가능하면
<dialog>와showModal()을 씁니다. - 제목을
aria-labelledby로 연결해 이름을 줍니다. - 열 때 안으로, 닫을 때 연 버튼으로 포커스를 옮깁니다.
- Esc와 보이는 닫기 버튼을 모두 제공합니다.
이렇게 쓰지 마세요
aria-modal="true"만 주고 실제 포커스 가두기·배경 비활성화를 빠뜨리지 않습니다.- 긴 양식 전체를
aria-describedby로 연결하지 않습니다. - 닫기를 키보드로 조작할 수 없는
<span>·<div>로 만들지 않습니다.
관련 역할·패턴
이 역할을 쓰는 패턴