웹접근성 - a11y

🏷️ 접근성이란? (Accessibility / a11y)

장애 유무에 관계없이 모든 사용자가 동등하게 정보에 접근하고 서비스를 사용할 수 있도록 설계하는 것.

  • a11y = accessibility의 줄임말 (앞글자 a + 중간 11글자 + 마지막 y)
  • 웹 접근성은 시각, 청각, 운동, 인지 장애를 가진 사람들도 포괄하는 사용자 경험 설계의 기본

🔥 왜 프론트엔드 개발자에게 중요한가

항목 이유
🔒 법적 책임 국내·외 접근성 기준 위반 시 제재 대상 가능 (ex. WCAG 2.1 기준)
📈 SEO 향상 시멘틱 태그 + 구조적 HTML은 검색엔진 최적화에 도움
🙋 실 사용자 확대 키보드 전용 사용자, 색약 사용자 등 다양한 실 사용자 고려
🧹 코드 정돈 효과 시멘틱한 마크업은 유지보수성과 디버깅 효율 증가

📚 핵심 a11y 실전 기술 정리

1. 시멘틱 HTML 사용 (기본 중의 기본)

  • <header>: 사이트나 페이지의 머리말
  • <nav>: 주요 내비게이션 링크
  • <main>: 페이지의 주요 콘텐츠 영역
  • <section>: 논리적으로 구분되는 콘텐츠 묶음
  • <article>: 독립적으로 구분되는 콘텐츠(예: 블로그 글, 기사)
  • <footer>: 저작권 등 페이지 하단 정보

→ 시맨틱 태그를 사용하면 구조와 의미가 명확해지고, 보조기술(스크린리더)이나 검색 엔진이 페이지를 더 잘 이해할 수 있다.

❌ 나쁜 예제

<div onclick="submit()">제출</div>

✅ 좋은 예제

<button onclick="submit()">제출</button>
이유 설명
✅ 키보드 탐색 <button>은 Tab/Enter 키 자동 대응
✅ 스크린리더 호환 버튼 역할로 음성 안내됨
✅ 시멘틱 구조 의미 전달 명확 → SEO/UX 모두 강화

2. ARIA 속성

ARIA (Accessible Rich Internet Applications)는
HTML의 기본 기능만으로는 표현이 어려운 경우, 스크린리더 사용자에게 의미나 상태를 전달하기 위해 사용하는 보조 속성이다.

  • 시맨틱 HTML이 우선, ARIA는 보완용
  • 잘못 쓰면 오히려 혼란을 줄 수 있음

✔️ role

<div role="navigation">메인 메뉴</div>
<div role="button" tabindex="0">클릭하세요</div>
<div role="alert">중요 알림!</div>

✔️aria-expanded="false"

aria-expanded는 아코디언, 드롭다운, FAQ 스크린리더에게 알려주는 속성이다.
무엇을 열고 닫는지 연결하려면 aria-controls를 읽히지 않게 하려면 aria-hidden을 사용한다.

<!-- 확장 가능한 메뉴 -->
<button aria-expanded="false" aria-controls="menu1">메뉴 펼치기</button>
<ul id="menu1" aria-hidden="true">
  <li>항목 1</li>
  <li>항목 2</li>
</ul>

✔️aria-required="true"

  • 이 필드는 사용자가 반드시 입력해야 하는 필수 필드임을 스크린리더에 전달
  • 시각적으로 * 표시하는 것만으론 부족하니까 음성으로도 말해주는 것
<!-- 필수 입력 필드 -->
<input id="username" aria-required="true">

✔️aria-live="polite"

시각적으로 텍스트가 없어도 스크린리더에게 대체 텍스트 제공

  • 이 속성은 동적으로 변경되는 콘텐츠를 스크린리더가 자동으로 읽어주게 함
  • polite: 지금 읽고 있는 걸 끝낸 다음, 조용히 읽음
  • (반대로 assertive: 현재 말 끊고 바로 읽음)
<!-- 실시간 업데이트 영역 -->
<div aria-live="polite">새로운 메시지가 도착했습니다</div>

✔️aria-label

시각적으로 텍스트가 없어도 스크린리더에게 대체 텍스트 제공

<div role="button" tabindex="0" aria-label="장바구니 열기">🛒</div>

✔️ aria-invalid

  • 이 속성은 “이 필드의 값이 유효하지 않다”는 신호를 스크린리더에게 보냄
  • 시각적으로는 빨간 테두리나 에러 메시지가 보이겠지만, 스크린리더는 그걸 “보지 못하므로” 코드로 알려줘야 함
<input id="email" aria-invalid="true" aria-describedby="email-error">
<p id="email-error">올바른 이메일 형식이 아닙니다.</p>

<button aria-labelledby="button-desc">저장</button>
<span id="button-desc">현재 작업 내용을 저장합니다</span>

🧠 중요한 점: 이건 단지 “오류 상태”만 알려줄 뿐
→ 실제 오류 메시지 텍스트를 읽게 하려면 aria-describedby와 함께 써야 함

✔️ aria-describedby

  • 이 속성은 해당 필드가 설명을 참조할 요소(id)를 연결함
  • 스크린리더가 입력 필드를 읽을 때, 연결된 요소의 텍스트도 함께 읽음
<input type="email" aria-describedby="email-error" />
<div id="email-error">유효한 이메일 주소를 입력하세요.</div>

🎧 스크린리더가 읽는 순서:

“이메일, 입력란, 올바른 이메일 형식이 아닙니다.”

aria-describedby는 사용자가 입력 필드를 만났을 때,
해당 필드에 대한 설명이나 오류 메시지를 스크린리더가 읽을 수 있게 연결하는 다리이다.
사용자에게 보여주기만 하는 게 아니라, 말로 들려줘야 하는 정보는 반드시 이 속성으로 연결해야 한다.


3. 숨김 텍스트: 시각적으로 숨기되 스크린리더는 읽게 하기

.u-hide-visually {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
<input type="email" aria-invalid="true" />

📌 시각적으로는 안 보이지만 스크린리더는 읽을 수 있음
→ 버튼이나 아이콘의 설명, 화면 내 텍스트 중복 방지 등에 활용


4. 키보드 내비게이션 지원

<div
  role="button"
  tabindex="0"
  aria-label="제출"
  onkeydown="if (event.key === 'Enter' || event.key === ' ') this.click()"
  onclick="submit()"
>
  제출
</div>

속성 역할
tabindex="0" 키보드 포커스 허용
role="button" 의미 없는 <div>에 버튼 역할 부여
onkeydown Enter/Space로도 클릭 이벤트 가능하게 처리
aria-label 버튼명 음성 안내

5. 실시간 알림 처리: aria-live

<button onclick="notify()">알림 보기</button>
<div id="live" aria-live="polite"></div>

<script>
  function notify() {
    document.getElementById("live").textContent = "새로운 메시지가 도착했습니다.";
  }
</script>

📌 aria-live="polite": 스크린리더가 현재 읽고 있는 내용을 끝낸 뒤, 해당 내용을 읽음
→ 비동기 알림, 동적 메시지 전달 시 유용


🧪 접근성 테스트 툴

툴 이름 설명
WAVE 웹 페이지의 접근성 시각적 검사
Lighthouse (Chrome DevTools) SEO + 접근성 + 퍼포먼스 종합 분석
VoiceOver (Mac) / NVDA (Win) 실제 시각장애인 사용 환경 시뮬레이션
axe DevTools 고급 접근성 검사 플러그인

📋 실무 체크리스트

• 모든 버튼/링크는 button/a 태그 또는 role 정의됨
• alt 속성은 모든 이미지에 정확하게 적용됨
• 동작하는 UI 요소는 키보드 탐색 가능
• 오류 메시지는 aria-describedby 등으로 연결되어 있음
• 시각적 정보 외에도 텍스트로 정보 전달됨
• 중요한 동적 변경은 aria-live로 감지 가능

🎯 결론

웹 접근성은 선택이 아닌 기본 설계이다.
시멘틱 HTML → ARIA → 키보드 대응 → 스크린리더 대응
→ 작은 배려의 누적이 모두를 위한 UI를 만든다.