웹 접근성을 고려한 모달 윈도우 설계

모달 윈도우는 사용자가 특정 작업에 집중할 수 있도록 하는 중요한 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>

핵심 요소:

  1. role="dialog": 스크린 리더에게 이 요소가 대화 상자임을 알립니다.
  2. aria-labelledby: 제목 요소를 참조해 모달의 제목을 명확히 전달합니다.
  3. 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를 위한 추가 팁

  1. 배경 스크롤 차단:
    • 모달이 열렸을 때 bodyoverflow: hidden;을 적용해 스크롤을 비활성화.
  2. 키보드 단축키 제공:
    • Escape 키로 모달을 닫는 기능을 반드시 추가.
  3. 시각적 피드백:
    • 포커스가 이동할 때 시각적 강조 효과를 추가하여 접근성을 향상.
  4. 닫기 버튼 명확화:
    • 닫기 버튼에 aria-label="Close modal"을 사용해 스크린 리더 사용자에게 명확한 피드백 제공.

웹 접근성을 고려한 모달 윈도우 설계는 단순히 ARIA 속성을 추가하는 것에 그치지 않고, 사용자 경험 전반을 최적화하는 데 초점을 맞춰야 합니다. 포커스 트랩과 aria-live 속성 등을 적절히 활용하면 모든 사용자가 손쉽게 모달 윈도우를 이용할 수 있습니다. 이를 통해 접근성을 높이고, 더 많은 사용자에게 친화적인 웹사이트를 제공해 보세요.

이 게시물이 얼마나 유용했습니까?

평점을 매겨주세요.

평균 평점 0 / 5. 투표수: 0

지금까지 투표한 사람이 없습니다. 가장 먼저 게시물을 평가해 주세요.

error: 우클릭이 불가능 합니다.