웹 접근성(Accessibility, a11y)은 장애가 있는 사람을 포함한 모든 사람이 웹을 사용할 수 있도록 만드는 원칙과 기술이다. WCAG(Web Content Accessibility Guidelines) 2.2 기준으로 A, AA, AAA 레벨로 구분된다.
WCAG 4대 원칙 (POUR)
| 원칙 | 의미 | 예시 |
|---|
| Perceivable (인식) | 모든 사용자가 인식 가능 | 대체 텍스트, 자막 |
| Operable (조작) | 모든 기기로 조작 가능 | 키보드 접근, 충분한 시간 |
| Understandable (이해) | 이해 가능한 콘텐츠 | 명확한 레이블, 오류 메시지 |
| Robust (견고) | 다양한 기술과 호환 | 시맨틱 HTML, ARIA |
시맨틱 HTML
html
<!-- 나쁜 예: 의미 없는 div 남용 -->
<div class="header">
<div class="nav">
<div class="nav-item" onclick="navigate('/home')">홈</div>
</div>
</div>
<!-- 좋은 예: 시맨틱 요소 사용 -->
<header>
<nav aria-label="주요 메뉴">
<ul>
<li><a href="/home">홈</a></li>
<li><a href="/about">소개</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>글 제목</h1>
<p>내용...</p>
</article>
</main>
<footer>
<p>저작권 정보</p>
</footer>
ARIA (Accessible Rich Internet Applications)
html
<!-- 아이콘 버튼 -->
<button aria-label="검색">
<svg aria-hidden="true">...</svg>
</button>
<!-- 모달 다이얼로그 -->
<div role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc">
<h2 id="modal-title">확인</h2>
<p id="modal-desc">정말 삭제하시겠습니까?</p>
</div>
<!-- 상태 알림 (라이브 리전) -->
<div role="status" aria-live="polite">
저장되었습니다.
</div>
<!-- 토글 버튼 -->
<button aria-pressed="false" id="toggle">다크 모드</button>
키보드 접근성
javascript
// 포커스 트랩 (모달)
function trapFocus(element) {
const focusable = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
}
색상 대비
css
/* WCAG AA: 일반 텍스트 4.5:1, 큰 텍스트 3:1 */
/* WCAG AAA: 일반 텍스트 7:1, 큰 텍스트 4.5:1 */
/* 좋은 예 */
.text { color: #1a1a1a; background: #ffffff; } /* 대비 19.7:1 */
/* 나쁜 예 */
.text { color: #aaaaaa; background: #ffffff; } /* 대비 2.32:1 */
관련 개념