모달 윈도우는 사용자가 특정 작업에 집중할 수 있도록 하는 중요한 UI 구성 요소입니다. 하지만 제대로 설계되지 않으면 웹 접근성을 크게 저해할 수 있습니다. 특히, 스크린 리더 사용자와 키보드 내비게이션 사용자에게 불편을 초래할 수 있습니다. 이번 포스팅에서는 ARIA 속성과 포커스 트랩(focus trap)을 사용하여 접근성 높은 모달 윈도우를 설계하는 방법을 소개합니다.
1. 접근성 높은 모달 윈도우의 중요성
모달 윈도우가 올바르게 동작하지 않으면 다음과 같은 문제가 발생할 수 있습니다.
- 키보드 트랩: 키보드 사용자가 모달 외부로 포커스를 이동할 수 없거나, 반대로 모달 내부에 포커스를 유지하지 못할 수 있음.
- 스크린 리더 혼란: 모달 창이 열렸음을 알리지 않으면 스크린 리더 사용자가 이를 인식하지 못함.
- 콘텐츠 접근 제한: 모달이 닫히지 않거나 배경 콘텐츠와 섞여 혼란을 줄 수 있음.
이를 해결하기 위해 ARIA 속성과 포커스 트랩을 적용한 모달 설계가 필요합니다.
2. 모달 윈도우의 기본 구조
모달 윈도우의 HTML 기본 구조는 다음과 같습니다.
<div id="modal" class="modal" aria-hidden="true" aria-labelledby="modal-title" role="dialog">
<div class="modal-content">
<button class="modal-close" aria-label="Close modal">×</button>
<h2 id="modal-title">모달 제목</h2>
<p>모달 내용이 여기에 들어갑니다.</p>
<button class="modal-action">확인</button>
</div>
</div>
<div id="overlay" class="overlay"></div>
핵심 요소:
role="dialog": 스크린 리더에게 이 요소가 대화 상자임을 알립니다.aria-labelledby: 제목 요소를 참조해 모달의 제목을 명확히 전달합니다.aria-hidden: 모달의 가시성을 나타냅니다. 모달이 열릴 때false로 설정.
3. CSS를 활용한 기본 스타일링
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
background: white;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
}
.modal[aria-hidden="false"] {
display: block;
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
}
.overlay[aria-hidden="false"] {
display: block;
}
4. ARIA 속성 활용
4.1 모달 열기와 닫기 상태 관리
JavaScript로 모달 창의 aria-hidden 속성을 변경합니다.
const modal = document.getElementById('modal');
const overlay = document.getElementById('overlay');
const openButton = document.getElementById('open-modal-button');
const closeButton = document.querySelector('.modal-close');
function openModal() {
modal.setAttribute('aria-hidden', 'false');
overlay.setAttribute('aria-hidden', 'false');
modal.querySelector('.modal-action').focus();
}
function closeModal() {
modal.setAttribute('aria-hidden', 'true');
overlay.setAttribute('aria-hidden', 'true');
openButton.focus();
}
openButton.addEventListener('click', openModal);
closeButton.addEventListener('click', closeModal);
overlay.addEventListener('click', closeModal);
4.2 aria-hidden 관리
배경 콘텐츠를 숨김 처리하여 스크린 리더가 모달 이외의 콘텐츠를 탐색하지 못하도록 해야 합니다.
5. 포커스 트랩 구현
포커스 트랩은 키보드 사용자가 모달 창 외부로 포커스를 이동하지 못하도록 합니다.
function trapFocus(e) {
const focusableElements = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (e.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
e.preventDefault();
} else if (!e.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
e.preventDefault();
}
}
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') trapFocus(e);
if (e.key === 'Escape') closeModal();
});
6. 스크린 리더 지원 개선
6.1 aria-live로 상태 알림
모달 창이 열렸음을 알리기 위해 aria-live를 사용합니다.
<div id="status" aria-live="polite" class="sr-only"></div>
function announceStatus(message) {
const status = document.getElementById('status');
status.textContent = message;
}
function openModal() {
modal.setAttribute('aria-hidden', 'false');
overlay.setAttribute('aria-hidden', 'false');
modal.querySelector('.modal-action').focus();
announceStatus('모달 창이 열렸습니다.');
}
7. UX를 위한 추가 팁
- 배경 스크롤 차단:
- 모달이 열렸을 때
body에overflow: hidden;을 적용해 스크롤을 비활성화.
- 모달이 열렸을 때
- 키보드 단축키 제공:
Escape키로 모달을 닫는 기능을 반드시 추가.
- 시각적 피드백:
- 포커스가 이동할 때 시각적 강조 효과를 추가하여 접근성을 향상.
- 닫기 버튼 명확화:
- 닫기 버튼에
aria-label="Close modal"을 사용해 스크린 리더 사용자에게 명확한 피드백 제공.
- 닫기 버튼에
웹 접근성을 고려한 모달 윈도우 설계는 단순히 ARIA 속성을 추가하는 것에 그치지 않고, 사용자 경험 전반을 최적화하는 데 초점을 맞춰야 합니다. 포커스 트랩과 aria-live 속성 등을 적절히 활용하면 모든 사용자가 손쉽게 모달 윈도우를 이용할 수 있습니다. 이를 통해 접근성을 높이고, 더 많은 사용자에게 친화적인 웹사이트를 제공해 보세요.









