접근성은 더이상 선택 사항이 아닙니다. 요즘은 모두를 위해 동작하는 웹사이트를 만드는 것이 그 어느 때보다 쉬워졌습니다. ARIA 속성은 그 중심에 있고, 그 힘은 대부분의 개발자들이 생각하는 것보다 훨씬 큽니다.
이 글에서는 존재하는 모든 ARIA 속성을 하나하나 설명해 드리겠습니다. 인기 있는 속성만 다루는 게 아니라 완전하고 철저한 목록을 다룰 것입니다. 문서 속에서 먼지만 쌓여가는 생소한 사양이 아닙니다. 모던 웹 애플리케이션을 구축할 때 실제 문제를 해결하는 실용적인 도구들입니다.
더 진행하기 전에, 실용적인 예제가 담긴 CodePen 링크를 알려드립니다.
ARIA는 접근 가능한 리치 인터넷 애플리케이션(Accessible Rich Internet Applications)을 의미합니다. ARIA의 핵심은 스크린 리더와 같은 보조 기술과 소통할 수 있는 방법을 제공합니다. 사용자 정의 드롭다운이나 화려한 모달을 구축할 때, 코드는 그 요소가 무엇인지 알지만 스크린 리더는 알지 못합니다. ARIA는 그 간극을 메웁니다.
이렇게 생각해 보세요. div와 CSS를 사용해 아름다운 탭 인터페이스를 만들었습니다. 시각적으로는 완벽하지만, 스크린 리더를 사용하는 사람은 그것이 탭이라는 사실을 전혀 알 수 없습니다. 적절한 ARIA 속성을 추가하면, 갑자기 그 스크린 리더가 전체 상호작용 패턴을 이해하게 됩니다.
전 세계적으로 10억 명 이상의 사람들이 어떤 형태로든 장애를 가지고 있으며, 이는 전 세계 인구의 약 15~16%에 해당합니다. 많은 사람들이 웹을 사용하기 위해 스크린 리더, 음성 제어, 키보드 탐색 또는 기타 보조 기술에 의존합니다. 적절한 ARIA 구현이 없다면, 사이트가 겉보기에 멋질지 몰라도, 이 사용자들에게는 완전히 사용할 수 없는 사이트가 됩니다다.
접근성은 단순히 규정 준수나 소송 회피를 위한 것이 아닙니다(물론 그것들도 중요한 문제이긴 합니다). 접근성이 보장된 웹사이트는 더 나은 웹사이트입니다. 의미론적으로 더 명확하고, 키보드로 탐색하기 쉬우며, 구조가 더 잘 잡혀 있고, 종종 검색 엔진에서도 더 좋은 성과를 내기도 합니다.
이 방대한 목록을 깊이 있게 살펴보기 전에, 반드시 알아야 할 것이 있습니다. 의미론적 HTML이 항상 우선입니다.
<button> 요소가 존재할 때 <div role="button">을 사용하지 마십시오. HTML이 이미 그 역할을 수행하고 있다면 ARIA로 불필요한 작업을 반복하지 마십시오. 기본 요소는 접근성, 키보드 지원, 예상되는 동작이 내장되어 있습니다. ARIA는 HTML이 부족한 부분을 채우기 위한 것입니다.
자, 여기 완전한 목록이 있습니다. 각 속성을 언제, 왜 사용해야 하는지 이해할 수 있도록 용도별로 분류했습니다.
역할 속성은 보조 기술에 해당 요소가 정확히 어떤 유형인지 알려줍니다.
페이지의 주요 섹션을 정의합니다.
role=“banner” 메인 헤더 영역role=“navigation” 모든 네비게이션 메뉴role=“main” 주요 콘텐츠role=“complementary” 사이드바 같은 보조 콘텐츠role=“contentinfo” 푸터 콘텐츠role=“search” 검색 영역role=“form” 양식 영역role=“region” 식별할 가치가 있는 중요한 섹션콘텐츠가 어떻게 구성되었는지 설명합니다.
role=“article” 독립적인 구성 요소role=“document” 문서 콘텐츠role=“feed” 스크롤 가능한 기사 목록(소셜 미디어 피드 등)role=“figure” 이미지, 다이어그램, 코드 스니펫role=“img” 이미지 컨테이너role=“list” 항목 목록role=“listitem” 개별 목록 항목role=“math” 수학 표기법role=“none” 또는 role=“presentation” 의미적 의미 제거role=“note” 각주 또는 부가 설명role=“table” 표 형식 데이터role=“row” 표 행role=“rowgroup” 행 그룹 (thead, tbody, tfoot)role=“cell” 표 셀role=“columnheader” 열 머리글role=“rowheader” 행 헤더role=“separator” 시각적 구분선role=“toolbar” 컨트롤이 있는 툴바role=“tooltip” 컨텍스트 팝업 정보모든 인터랙티브 컴포넌트에 적용됩니다.
role=“button” 버튼role=“checkbox” 체크박스role=“radio” 라디오 버튼role=“textbox” 텍스트 입력란role=“searchbox” 검색 입력란role=“switch” 토글 스위치role=“slider” 범위 슬라이더role=“spinbutton” 숫자 스피너role=“combobox” 콤보 박스 (입력 + 드롭다운)role=“listbox” 옵션 목록role=“option” 개별 옵션role=“menu” 메뉴 위젯role=“menubar” 메뉴 바role=“menuitem” 메뉴 항목role=“menuitemcheckbox” 선택 가능한 메뉴 항목role=“menuitemradio” 라디오 버튼 메뉴 항목role=“tab” 탭 컨트롤role=“tablist” 탭 컨테이너role=“tabpanel” 탭 콘텐츠 패널role=“tree” 트리 뷰role=“treeitem” 트리 항목role=“treegrid” 편집 가능한 트리 그리드role=“grid” 대화형 그리드role=“gridcell” 그리드 셀role=“link” 링크role=“progressbar” 진행률 표시기role=“scrollbar” 스크롤바항목을 그룹화하기 위한 역할입니다.
role=“group” 일반 그룹role=“radiogroup” 라디오 버튼 그룹role=“rowgroup” 테이블의 행 그룹동적으로 변경되는 콘텐츠를 위한 역할입니다.
role=“alert” 긴급 메시지role=“log” 추가되는 로그role=“marquee” 비필수 업데이트role=“status” 상태 메시지role=“timer” 타이머 및 카운트다운모달 상호작용을 위한 역할입니다.
role=“dialog” 대화 상자role=“alertdialog” 경고 대화 상자command, composite, input, landmark, range, roletype, section, sectionhead, select, structure, widget, window 사양에는 존재하지만 직접 사용하기 위한 용도는 아닙니다.
사용자가 요소와 상호작용하는 방법을 알려줍니다.
aria-autocomplete=“none|inline|list|both” 자동 완성 동작aria-checked=“true|false|mixed” 선택 상태aria-disabled=“true|false” 비활성화 상태aria-errormessage=“[ID]” 오류 메시지 링크aria-expanded=“true|false|undefined” 확장 상태aria-haspopup=“true|false|menu|listbox|tree|grid|dialog” 팝업 표시aria-hidden=“true|false|undefined” 보조 기술에 대한 가시성aria-invalid=“true|false|grammar|spelling” 유효성 검사 상태aria-label=“[string]” 접근 가능한 레이블aria-level=“[integer]” 계층적 수준aria-modal=“true|false” 모달 상태aria-multiline=“true|false” 다중 줄 입력aria-multiselectable=“true|false” 다중 선택aria-orientation=“horizontal|vertical|undefined” 방향aria-placeholder=“[string]” 플레이스홀더 힌트aria-pressed=“true|false|mixed|undefined” 토글 상태aria-readonly=“true|false” 읽기 전용 상태aria-required=“true|false” 필수 입력 필드aria-selected=“true|false|undefined” 선택 상태aria-sort=“ascending|descending|none|other” 정렬 방향aria-valuemax=“[number]” 최댓값aria-valuemin=“[number]” 최솟값aria-valuenow=“[number]” 현재값aria-valuetext=“[string]” 사람이 읽을 수 있는 값사용자에게 변경 사항을 알리는 방식을 제어합니다.
aria-atomic=“true|false” 전체 영역 또는 변경 사항만 알림aria-busy=“true|false” 로딩 상태aria-live=“off|polite|assertive” 알림 긴급도off 알림 없음polite 유휴 시 알림assertive 알림을 위해 중단aria-relevant=“additions|removals|text|all” - 알릴 변경 사항 유형aria-dropeffect=“copy|move|link|execute|popup|none” 드롭 효과 (ARIA 1.1에서 사용 중단됨)aria-grabbed=“true|false|undefined” 드래그 상태 (ARIA 1.1에서 사용 중단됨)요소 간 의미적 관계를 생성합니다.
aria-activedescendant=“[ID]” 현재 활성화된 자식 요소aria-colcount=“[integer]” 총 열 수aria-colindex=“[integer]” 열 위치aria-colspan=“[integer]” 병합된 열 수aria-controls=“[ID list]” 제어되는 요소aria-describedby=“[ID list]” 설명 출처aria-details=“[ID]” 상세 설명aria-flowto=“[ID list]” 읽기 순서 재정의aria-labelledby=“[ID list]” 레이블 출처aria-owns=“[ID list]” 소유된 자식 요소aria-posinset=“[integer]” 세트 내 위치aria-rowcount=“[integer]” 총 행 수aria-rowindex=“[integer]” 행 위치aria-rowspan=“[integer]” 행 스팬aria-setsize=“[integer]” 세트 크기aria-atomic (위에서 다룸)aria-busy (위에서 다룸)aria-controls (위에서 다룸)aria-current=“page|step|location|date|time|true|false” 현재 항목 표시기aria-describedby (위에서 다룸)aria-details (위에서 다룸)aria-disabled (위에서 다룸)aria-dropeffect (사용 중단됨)aria-errormessage (위에서 다룸)aria-flowto (위에서 다룸)aria-grabbed (사용 중단됨)aria-haspopup (위에서 다룸)aria-hidden (위에서 다룸)aria-invalid (위에서 다룸)aria-keyshortcuts=“[string]” - 키보드 단축키aria-label (위에서 다룸)aria-labelledby (위에서 다룸)aria-live (위에서 다룸)aria-owns (위에서 다룸)aria-relevant (위에서 다룸)aria-roledescription=“[string]” 사용자 정의 역할 설명실제 코드에서 이 기능이 어떻게 작동하는지 살펴보겠습니다.
<div
role="button"
tabindex="0"
aria-pressed="false"
onclick="this.setAttribute('aria-pressed', this.getAttribute('aria-pressed') === 'false')"
>
Dark Mode
</div>
버튼이 이미 있다면 div를 버튼으로 절대 사용하지 마세요
<div
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc"
>
<h2 id="dialog-title">Delete Item?</h2>
<p id="dialog-desc">This action cannot be undone.</p>
<button>Delete</button>
<button>Cancel</button>
</div>
<label for="email">Email Address</label>
<input
type="email"
id="email"
aria-required="true"
aria-invalid="true"
aria-describedby="email-error"
/>
<span id="email-error" role="alert"> Please enter a valid email address </span>
<button aria-expanded="false" aria-controls="content-panel">
Show More Details
</button>
<div id="content-panel" hidden>Additional content here...</div>
<label for="search">Search Products</label>
<input
id="search"
type="search"
aria-controls="results"
aria-describedby="results-count"
/>
<div id="results" role="region" aria-live="polite">
<span id="results-count">12 products found</span>
<!-- 리스트 결과는 여기에 -->
</div>
<!-- ❌ -->
<div role="button" onclick="submit()">Submit</div>
<!-- ✅ -->
<button onclick="submit()">Submit</button>
<!-- ❌ - 상태는 절대 업데이트되지 않습니다 -->
<button aria-expanded="false" onclick="toggle()">Menu</button>
<!-- ✅ - 상호작용을 통한 상태 업데이트 -->
<button
aria-expanded="false"
onclick="this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') === 'false')"
>
Menu
</button>
<!-- ❌ - 버튼이 보조 기술에서 숨겨져 있습니다 -->
<button aria-hidden="true">Important Action</button>
<!-- ✅ - 데코레이티브(decorative) 요소만 숨기기 -->
<span aria-hidden="true">★</span><button>Rate 5 Stars</button>
<!-- ❌ - 불필요한 aria-label -->
<h1 aria-label="“Welcome”">Welcome</h1>
<!-- ✅ - 텍스트 콘텐츠가 이미 접근 가능함 -->
<h1>Welcome</h1>
<!-- ❌ - 의미가 혼란스러움 -->
<button role="heading">네비게이션 항목</button>
<!-- ✅ - 적절한 요소 사용 -->
<h2>네비게이션</h2>
<button>네비게이션 항목</button>
ARIA를 추가한다고 해서 제대로 작동할 거라고 기대해서는 안 됩니다. 검증 방법은 다음과 같습니다.
aria-label 직접 라벨 텍스트aria-labelledby 다른 요소의 텍스트 참조aria-describedby 추가 설명aria-expanded 확장 가능한 섹션용aria-pressed 토글 버튼용aria-checked 사용자 정의 체크박스용aria-selected 선택된 옵션용aria-invalid 유효하지 않은 필드 표시aria-errormessage 오류 텍스트 링크role="alert" 즉시 오류 알림aria-live=“polite” 적절한 시점에 알림aria-live=“assertive” 즉시 알림aria-busy=“true” 로딩 중aria-current=“page” 탐색 내 현재 페이지aria-hidden=“true” 장식적 콘텐츠 숨김aria-controls 콘텐츠로의 링크 트리거이 방대한 목록을 보면 ARIA가 부담스러울 수 있습니다. 하지만 알아두셔야 할 점은 모든 속성을 외울 필요는 없다는 것입니다. aria-label, aria-expanded, aria-hidden, aria-live 같은 일반적인 속성부터 시작하세요. 프로젝트에서 필요할 때마다 나머지 속성을 배우면 됩니다.
진정으로 중요한 것은 ARIA의 존재 이유를 이해하는 것입니다. ARIA는 접근 방식에 관계없이 모든 사람이 웹을 사용할 수 있도록 하기 위해 존재합니다. 적절한 ARIA 속성을 추가할 때마다 여러분의 웹사이트는 더 많은 사람들에게 열립니다. 바로 이것이 웹이 추구해야 할 본질입니다.
그러니 작은 것부터 시작하세요. 현재 프로젝트에서 하나의 구성 요소를 선택하세요. 올바른 ARIA 속성을 추가하세요. 스크린 리더로 테스트해 보세요. 얼마나 빨리 익숙해지는지 놀라실 겁니다.
모두가 사용할 수 있을 때 웹은 더 나아집니다. 이제 여러분은 이를 실현할 도구를 갖췄습니다.
단순히 ARIA에 대해 훑고 가려다 '접근 방식에 관계없이 모든 사람이 웹을 사용할 수 있도록 하기 위해' 부분에서 생각이 많아졌습니다. 비타민보다는 진통제같은 속성인것 같네요. 좋은 글 감사합니다.