iBetter Books
수정

도입 스토리

"WAI-ARIA 명세를 읽으려고 W3C 문서를 열었는데..." 김개발이 브라우저 탭을 보여주었습니다. "너무 방대해요. 어디서 시작해야 하죠?"

"세 가지만 이해하면 돼요." 박멘토가 화이트보드에 썼습니다. "역할(Role), 상태(State), 속성(Property). 이 세 가지가 ARIA의 전부예요."

"그리고 실제 구현 패턴은 APG라는 곳에서 찾을 수 있어요. ARIA Authoring Practices Guide — W3C가 제공하는 공식 컴포넌트 패턴 가이드예요. 코드 예제까지 있어요."

핵심 개념 설명

ARIA의 세 가지 구성 요소

역할(Role) — 요소가 무엇인지.

<div role="dialog">     <!-- 대화상자 --><div role="tablist">    <!-- 탭 그룹 --><div role="tab">        <!-- 탭 --><div role="tabpanel">   <!-- 탭 내용 --><div role="progressbar"> <!-- 진행 표시줄 -->

상태(State) — 요소의 현재 상태 (동적으로 변함).

<!-- aria-expanded: 열림/닫힘 --><button aria-expanded="false">메뉴 열기</button><button aria-expanded="true">메뉴 닫기</button><!-- aria-checked: 체크 여부 --><div role="checkbox" aria-checked="true">동의합니다</div><div role="checkbox" aria-checked="false">동의하지 않습니다</div><!-- aria-selected: 선택 여부 --><div role="tab" aria-selected="true">첫 번째 탭</div><!-- aria-disabled: 비활성 여부 --><button aria-disabled="true">제출 (처리 중)</button><!-- aria-invalid: 유효성 오류 --><input aria-invalid="true">

속성(Property) — 요소의 특성 (주로 정적).

<!-- aria-label: 접근 가능한 이름 직접 지정 --><button aria-label="닫기">X</button><!-- aria-labelledby: 다른 요소의 텍스트를 이름으로 --><h2 id="modal-title">주문 확인</h2><dialog aria-labelledby="modal-title">...</dialog><!-- aria-describedby: 설명 연결 --><input aria-describedby="hint error"><!-- aria-haspopup: 팝업을 열 수 있음 --><button aria-haspopup="menu">메뉴</button><button aria-haspopup="dialog">도움말</button><button aria-haspopup="listbox">선택</button><!-- aria-controls: 제어하는 요소 참조 --><button aria-controls="panel1">패널 열기</button><div id="panel1">...</div><!-- aria-owns: 논리적 부모-자식 관계 --><ul aria-owns="extra-items">...</ul><!-- aria-live: 실시간 업데이트 알림 --><div aria-live="polite">...</div><!-- aria-atomic: 전체/부분 읽기 --><div aria-live="polite" aria-atomic="true">...</div>

ARIA 역할 분류

분류 role 예시 설명
위젯 button, checkbox, tab, slider 인터랙티브 UI 컴포넌트
복합 위젯 tablist, menu, listbox, grid 위젯의 컨테이너
문서 구조 article, section, list, heading 콘텐츠 구조화
랜드마크 banner, navigation, main, region 페이지 영역
실시간 alert, log, status, timer 동적 업데이트

ARIA Authoring Practices Guide (APG)

W3C APG는 자주 쓰이는 UI 패턴별 ARIA 구현 가이드와 예제 코드를 제공합니다.

https://www.w3.org/WAI/ARIA/apg/patterns/

수록된 주요 패턴:

  • Accordion (아코디언)
  • Alert Dialog (경고 대화상자)
  • Breadcrumb (경로 탐색)
  • Button (버튼)
  • Carousel (슬라이더)
  • Combobox (자동완성)
  • Dialog Modal (모달 대화상자)
  • Disclosure (열기/닫기)
  • Feed (무한 스크롤)
  • Grid (그리드)
  • Listbox (목록 선택)
  • Menu (메뉴)
  • Menubar (메뉴 바)
  • Radio Group (라디오 그룹)
  • Slider (슬라이더)
  • Spinbutton (숫자 입력)
  • Switch (스위치)
  • Table (테이블)
  • Tabs (탭)
  • Toolbar (툴바)
  • Tooltip (툴팁)
  • Tree (트리뷰)

ARIA 연결 관계 다이어그램

  aria-labelledby   ← "이 요소의 이름은 저 요소에 있다"
  aria-describedby  ← "이 요소의 설명은 저 요소에 있다"
  aria-controls     ← "이 요소는 저 요소를 제어한다"
  aria-owns         ← "이 요소는 저 요소를 자식으로 소유한다"
  aria-flowto       ← "읽기 흐름이 저 요소로 이어진다"

단계별 실습

따라하기: APG 패턴 탐색하기

  1. https://www.w3.org/WAI/ARIA/apg/patterns/에 접속합니다.
  2. "Tabs" 패턴을 엽니다.
  3. 예제 코드를 보며 role, aria-selected, aria-controls의 관계를 파악합니다.
  4. "Keyboard Interaction" 섹션에서 키보드 동작 명세를 확인합니다.

변형하기: ARIA 속성 현황 파악하기

// 페이지 내 ARIA 속성 사용 현황 확인const ariaAttrs = [  'role', 'aria-label', 'aria-labelledby', 'aria-describedby',  'aria-expanded', 'aria-hidden', 'aria-live', 'aria-invalid'];const summary = {};ariaAttrs.forEach(attr => {  const count = document.querySelectorAll(`[${attr}]`).length;  if (count > 0) summary[attr] = count;});console.table(summary);

정리와 확인

핵심 내용 요약

  • ARIA 3요소: 역할(role), 상태(state), 속성(property)
  • 역할: 요소가 무엇인지 (dialog, tab, progressbar)
  • 상태: 현재 상태, 동적 변화 (expanded, checked, selected)
  • 속성: 특성, 주로 정적 (label, labelledby, describedby)
  • APG: W3C 공식 패턴 가이드 — 구현 전 반드시 확인

확인 문제

문제 1. aria-expanded는 역할, 상태, 속성 중 무엇인가?

상태(State). 드롭다운이나 아코디언이 열렸는지/닫혔는지를 나타내며,
사용자 인터랙션에 따라 동적으로 변합니다.

문제 2. aria-labelledbyaria-label의 차이는?

aria-label: 직접 이름 문자열을 지정 (보이지 않는 이름)
aria-labelledby: 페이지 내 다른 요소의 id를 참조
같은 내용이 화면에 이미 있다면 aria-labelledby가 더 좋습니다.
동일 내용을 중복 관리하지 않아도 되기 때문입니다.

다음 챕터에서는 모달 대화상자와 드롭다운 메뉴의 실전 구현을 다룹니다. APG 패턴을 코드로 구현하는 방법을 단계별로 알아봅니다.