마우스를 전혀 사용할 수 없는 신체적 환경이거나, 화면을 보지 못해 낭독기(스크린 리더)를 사용하는 분들에게는 웹 사이트의 '키보드 Tab 이동'과 '소리 알림'이 생명선과 같습니다.
우리는 tabindex를 사용해 키보드가 닿을 수 없는 곳에 길을 열어주고, aria-live를 사용해 눈에 안 보이는 화면의 변화를 라디오처럼 귀에 방송해 줄 수 있습니다.
1. 탭(Tab) 키의 마법과 긴급 방송 시스템
모달(Modal) 창이 뜨거나 장바구니 숫자가 올라갈 때, 보이지 않는 곳에서는 어떤 처리가 필요할까요?
⌨️
포커스 길잡이 (tabindex)
기본적으로 div나 span은 탭(Tab) 키로 도달할 수 없습니다. 하지만 tabindex="0"을 부여하는 순간, 마치 버튼처럼 키보드 포커스를 받을 수 있게 마법의 길이 열립니다.
📻
동적 방송국 (aria-live)
쇼핑몰에서 조용히 "장바구니 추가됨" 팝업이 뜰 때, aria-live 영역 안에 글씨를 써주면 스크린 리더가 그 변화를 감지하고 마치 라디오처럼 귀에다 내용을 낭독해 줍니다.
2. 심화 접근성 핵심 속성
속성명
값 예시
설명 및 역할
tabindex
0
키보드의 Tab 이동 순서에 강제로 포함시킵니다. 클릭 가능한 커스텀 컴포넌트를 만들 때 무조건 넣어야 합니다.
-1
Tab 키로는 영원히 도달할 수 없지만, 자바스크립트의 focus() 함수를 써서 코드로만 강제 이동시킬 때 사용합니다. (모달 창 띄울 때 필수)
aria-live
polite
해당 태그 안의 글자가 바뀌면 스크린 리더가 이를 알아채고 낭독합니다. 단, 현재 낭독 중이던 말이 다 끝날 때까지 기다렸다가 예의 바르게(polite) 말해줍니다. (일반 알림)
assertive
스크린 리더가 현재 하던 말을 즉각 끊어버리고 다 무시한 채 즉시 새빨간 경고를 낭독(assertive)합니다. (에러, 세션 만료 등 긴급 상황)
<div class="keyboard-demo-container">
<h2>접근성 심화 훈련장</h2>
<p class="hint">💡 마우스 대신 <strong>Tab 키</strong>를 눌러 포커스를 이동해보세요.</p>
<!-- 1. 키보드 접근성 (tabindex) -->
<div class="card">
<h3>1. 키보드 포커스 관리 (tabindex)</h3>
<div class="flex-box">
<!-- 기본적으로 포커스를 받을 수 없는 div에 tabindex="0" 부여 -->
<div tabindex="0" class="focus-box" onclick="alert('클릭됨!')" onkeydown="if(event.key==='Enter') alert('키보드로 실행됨!')">
난 div지만 Tab 키로 선택 가능해! (tabindex="0")
</div>
<!-- tabindex="-1"은 Tab 키로는 못 가고, 모달창 띄울 때 강제로 포커스 줄 때만 씁니다 -->
<div tabindex="-1" class="focus-box disabled-box">
난 탭 키로 절대 올 수 없어! (tabindex="-1")
</div>
</div>
</div>
<!-- 2. 동적 화면 알림 (aria-live) -->
<div class="card">
<h3>2. 동적 긴급 방송 시스템 (aria-live)</h3>
<p>버튼을 누르면 화면 아래 텍스트가 바뀝니다. 스크린 리더는 이 변화를 감지하고 시각장애인에게 귀에다 방송해 줍니다.</p>
<button id="addCartBtn" class="action-btn">장바구니에 담기</button>
<button id="errorBtn" class="action-btn danger-btn">결제 오류 발생</button>
<!-- polite: 현재 하던 말이 끝나면 예의 바르게 알려줌 -->
<div id="liveRegionPolite" aria-live="polite" class="live-region polite-msg"></div>
<!-- assertive: 다 무시하고 지금 즉시 경고함 -->
<div id="liveRegionAssertive" aria-live="assertive" class="live-region assertive-msg"></div>
</div>
</div>