WAI-ARIA란 무엇인가요?
이 글에서 다루는 내용
이 글에서는 WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications) 의 개 념과 실무 적용 방법을 다룹니다.
먼저, WAI-ARIA가 필요한 이유와 HTML의 시맨틱 요소만으로 해결하기 어려운 접근성 문제를 어떻게 보완하는지를 설명합니다. 이후, Roles(역할), States(상태), Properties(속성) 과 같은 핵심 개념을 살펴보고, 이를 UI 요소에 적용하는 방법을 구체적인 예제와 함께 소개합니다.
또한, 폼(Form), 모달 다이얼로그(Modal Dialog), 커스텀 UI 컴포넌트(예: 아코디언, 탭) 와 같은 실제 사례에서 WAI-ARIA를 활용하는 방법을 설명하며, 잘못된 사용 사례를 방지하기 위한 주의점과 Best Practices를 정리합니다.
마지막으로, 프론트엔드 개발자로서 접근성을 고려하는 방법과 실무에서 활용할 수 있는 Lighthouse, axe DevTools, NVDA 같은 접근성 테스트 도구를 소개하며, WAI-ARIA를 효과적으로 적용하기 위한 실천 방안을 제안합니다.
이 글을 통해 WAI-ARIA의 개념을 명확하게 이해하고, 실제 프로젝트에서 접근성을 고려한 UI를 구현하는 데 필요한 실질적인 가이드라인을 얻을 수 있을 것입니다.
WAI-ARIA에 대해
WAI-ARIA의 정의
WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)는 W3C(World Wide Web Consortium)에서 제안한 웹 접근성 표준으로, 보조 기술(Screen Reader, 음성 명령 시스템 등)이 웹 콘텐츠를 올바르게 해석하도록 돕는 역할을 합니다.
기본적으로 HTML은 <button>
, <nav>
, <article>
등의 시맨틱 요소를 제공하여 웹페이지의 구조와 의미를 전달하지만, 복잡한 UI 컴포넌트(예: 아코디언, 드롭다운, 모달 등)는 기본 HTML 요소만으로 접근성이 충분히 보장되지 않습니다. 예를 들어, <div>
로 구현된 버튼은 보조 기술이 버튼으로 인식하지 못하기 때문에 추가적인 정보가 필요합니다.
WAI-ARIA는 이러한 문제를 해결하기 위해 역할(Role), 상태(State), 속성(Property) 을 정의하여 보조 기술이 UI를 올바르게 해석할 수 있도록 합니다. 예를 들어, role="button"
을 사용하면 일반 <div>
도 버튼처럼 동작할 수 있으며, aria-expanded="true"
속성을 추가하면 드롭다운 메뉴가 열린 상태임을 알릴 수 있습니다.
WAI-ARIA는 웹 접근성을 보완하는 기술이지만, HTML의 기본 시맨틱 요소를 우선적으로 활용하는 것이 더 좋은 접근 방식입니다.
웹 접근성이 중요한 이유
웹은 모든 사용자가 접근할 수 있어야 하지만, 접근성이 고려되지 않은 사이트는 장애가 있는 사용자들에게 심각한 장벽이 될 수 있습니다.
시각 장애가 있는 사용자는 스크린 리더(Screen Reader) 를 이용하여 웹페이지의 콘텐츠를 청취합니다. 하지만 구조가 잘못 설계 되거나 시맨틱한 정보가 부족하면 보조 기술이 올바르게 작동하지 않아 사용자가 원하는 정보를 찾기 어려워집니다.
마우스를 사용할 수 없는 사용자들은 키보드만으로 모든 인터페이스를 조작해야 합니다. 하지만 키보드 포커스 이동이 원활하지 않거나, 클릭 가능한 요소가 키보드로 접근할 수 없도록 구현되어 있다면, 웹사이트 이용이 불가능해집니다.
또한, 접근성은 장애가 있는 사용자뿐만 아니라 일시적인 장애(예: 손목 부상으로 마우스를 사용할 수 없는 경우)나 환경적 제약(예: 강한 햇빛 아래에서 화면을 보기 어려운 상황) 에서도 유용하게 작용합니다.
결국, 웹 접근성은 특정 사용자 그룹만을 위한 것이 아니라 모든 사용자를 위한 보편적인 원칙입니다.
WAI-ARIA가 필요한 이유
HTML5는 웹 접근성을 높이기 위해 다양한 시맨틱 요소를 제공하지만, 동적 UI가 많아진 현대 웹 환경에서는 기본 요소만으로 충분하지 않은 경우가 많습니다.
특히 다음과 같은 경우에는 WAI-ARIA가 필요합니다.
- 커스텀 UI 컴포넌트
<button>
대신<div>
로 버튼을 구현하면 보조 기술이 이를 버튼으로 인식하지 못합니다.
- 동적 콘텐츠 변경
- 화면의 특정 요소가 변경되었을 때 이를 보조 기술이 인식하도록 알려주지 않으면, 사용자는 변화를 감지하지 못할 수 있습니다.
- 키보드 네비게이션 부족
- 키보드만으로 조작할 수 없는 UI는 접근성이 떨어집니다.
이러한 문제를 해결하기 위해 WAI-ARIA는 HTML 요소가 본래 제공하지 않는 추가적인 정보를 명시적으로 정의할 수 있도록 합니다. 예를 들어, <div role="dialog" aria-labelledby="modal-title">
처럼 사용하면 일반 <div>
요소도 모달 다이얼로그로 인식되도록 만들 수 있습니다.
하지만 WAI-ARIA는 HTML의 기본 기능을 대체하는 것이 아니라, 필요할 때만 보조적으로 활용하는 것이 가장 바람직한 접근 방식입니다.
WAI-ARIA의 주요 개념
웹 접근성을 고려한 UI 개발에서는 Roles(역할), States(상태), Properties(속성) 의 세 가지 개념이 중요합니다. WAI-ARIA는 이 개념들을 통해 보조 기술이 웹 콘텐츠를 더욱 명확하게 해석할 수 있도록 도와줍니다.
- Roles(역할): 요소가 수행하는 기능을 정의합니다. 예를 들어,
role="button"
을 사용하면<div>
도 버튼처럼 동작할 수 있습니다. - States(상태): 요소의 현재 상태를 나타내며, 동적 UI 변화를 보조 기술이 인식할 수 있도록 합니다. 예를 들어,
aria-expanded="true"
는 아코디언이 열려 있음을 의미합니다. - Properties(속성): UI 요소와 관련된 추가적인 정보를 제공합니다. 예를 들어,
aria-labelledby="header-title"
은 특정 제목과 요소가 연결되어 있음을 나타냅니다.
이제 각 개념을 구체적으로 살펴보겠습니다.
ARIA Roles(역할)
ARIA Roles는 특정 UI 요소의 기능을 명확히 정의하는 속성입니다. HTML의 시맨틱 요소만으로 충분하지 않은 경우 role
속성을 추가하여 보조 기술이 요소의 역할을 올바르게 인식하도록 할 수 있습니다.
예를 들어, <div>
요소를 버튼처럼 동작하게 만들고 싶다면 다음과 같이 정의할 수 있습니다.
<div role="button" tabindex="0">클릭하세요</div>
여기서 role="button"
은 보조 기술이 이 요소를 버튼으로 인식하게 하며, tabindex="0"
을 추가하면 키보드 포커스도 가능해집니다.
Landmark Roles(랜드마크 역할)
랜드마크 역할은 페이지의 주요 영역을 명확히 정의하여 보조 기술이 콘텐츠를 더 쉽게 탐색할 수 있도록 합니다.
<header role="banner">웹사이트 제목</header>
<nav role="navigation">
<ul>
<li><a href="/">홈</a></li>
<li><a href="/about">소개</a></li>
</ul>
</nav>
<main role="main">
<h1>메인 콘텐츠</h1>
</main>
위 코드에서 role="banner"
, role="navigation"
, role="main"
은 각각 페이지의 제목, 내비게이션, 주요 콘텐츠 영역을 나타냅니다.
Widget Roles(위젯 역할)
위젯 역할은 버튼, 다이얼로그, 탭과 같은 동적 UI 요소에 대한 접근성을 보장하는 역할을 합니다.
<div role="dialog" aria-labelledby="modal-title">
<h2 id="modal-title">로그인</h2>
<button aria-label="닫기">X</button>
</div>
이처럼, 특정 역할을 명확히 부여하면 보조 기술이 UI를 올바르게 해석할 수 있습니다.
ARIA States(상태)
ARIA 상태 속성은 UI 요소의 현재 상태를 나타내며, 사용자의 상호작용에 따라 변하는 동적 정보를 제공합니다.
aria-checked
: 체크박스나 라디오 버튼이 선택되었는지를 나타냅니다.aria-disabled
: 요소가 비활성화된 상태인지 여부를 지정합니다.aria-expanded
: 아코디언이나 드롭다운이 열려 있는지를 나타냅니다.
<button aria-expanded="true" aria-controls="content">더보기</button>
<div id="content">추가 정보</div>
여기서 aria-expanded="true"
는 해당 버튼이 현재 확장된 상태임을 의미합니다.
ARIA Properties(속성)
ARIA 속성은 특정 UI 요소의 설명이나 관계를 명확하게 정의하는 데 사용됩니다.
aria-labelledby
: 요소가 어떤 제목과 연결되어 있는지를 지정합니다.aria-describedby
: 요소에 대한 추가 설명을 제공합니다.aria-hidden
: 특정 요소를 보조 기술이 무시하도록 설정합니다.
<h2 id="header-title">제품 목록</h2>
<ul aria-labelledby="header-title">
<li>제품 A</li>
<li>제품 B</li>
</ul>
위 코드에서 aria-labelledby="header-title"
속성을 사용하면 보조 기술이 목록과 제목을 함께 읽어줄 수 있습니다.
WAI-ARIA와 HTML5의 역할 분담
HTML5는 <button>
, <input>
, <nav>
, <header>
같은 시맨틱 요소를 제공하여 보조 기술이 웹 콘텐츠를 더 쉽게 이해할 수 있도록 합니다. 따라서, 가능하면 WAI-ARIA 대신 HTML의 기본 시맨틱 요소를 활용하는 것이 더 좋습니다.
✅ 올바른 예시 (HTML 기본 요소 사용)
<button>클릭하세요</button>
🚫 잘못된 예시 (ARIA를 불필요하게 사용)
<div role="button" tabindex="0">클릭하세요</div>
ARIA를 사용하면 보조 기술이 요소를 버튼으로 인식할 수는 있지만, HTML의 <button>
요소는 이미 접근성을 고려하여 설계되었기 때문에 불필요한 역할(role) 지정은 하지 않는 것이 좋습니다.
Recap
WAI-ARIA의 role
, state
, property
속성은 웹 접근성을 향상시키는 중요한 도구입니다. 하지만 HTML의 기본 기능이 이미 제공하는 정보를 불필요하게 중복하는 것은 피해야 하며, 필요한 경우에만 ARIA를 추가적으로 활용하는 것이 가장 바람직한 접근 방식입니다.
WAI-ARIA 적용 사례
실제 웹 애플리케이션에서는 다양한 UI 요소에 WAI-ARIA를 적용하여 접근성을 향상시킬 수 있습니다. 대표적인 예로 Form 요소, Modal Dialog, Custom UI 컴포넌트(예: 아코디언, 탭 등) 에서의 적용 방식을 살펴보겠습니다.
Form 요소에 WAI-ARIA 적용하기
폼(Form)은 웹에서 가장 중요한 인터랙티브 요소 중 하나이며, 보조 기술 사용자가 원활하게 입력할 수 있도록 접근성을 고려해야 합니다. HTML 자체적으로 <label>
을 제공하지만, WAI-ARIA를 활용하면 더 명확한 연관성을 부여할 수 있습니다.
aria-labelledby
와 aria-describedby
를 활용한 폼 입력
<label id="email-label" for="email">이메일</label>
<input
type="email"
id="email"
aria-labelledby="email-label"
aria-describedby="email-hint"
/>
<p id="email-hint">이메일 주소를 입력하세요.</p>
aria-labelledby="email-label"
: 입력 필드가 특정 레이블과 연결되어 있음을 나타냅니다.aria-describedby="email-hint"
: 입력 필드에 대한 추가 설명을 제공합니다.
aria-invalid
와 aria-required
를 활용한 유효성 검사
<input type="text" aria-required="true" aria-invalid="true" />
aria-required="true"
: 해당 필드가 필수 입력 항목임을 의미합니다.aria-invalid="true"
: 잘못된 입력이 감지되었음을 나타냅니다.
이러한 속성들은 시각적으로는 보이지 않지만, 보조 기술이 이를 해석하여 사용자에게 필요한 정보를 제공합니다.
Modal Dialog에서 WAI-ARIA 활용하기
모달 다이얼로그는 웹에서 자주 사용되지만, 접근성을 고려하지 않으면 키보드 사용자나 스크린 리더 사용자가 모달을 인식하지 못할 수 있습니다.
role="dialog"
와 aria-labelledby
를 활용한 모달
<div
role="dialog"
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<h2 id="modal-title">로그인</h2>
<p id="modal-description">이메일과 비밀번호를 입력하세요.</p>
<button aria-label="닫기">X</button>
</div>
role="dialog"
: 보조 기술이 해당 요소를 모달 대화 상자로 인식하도록 합니다.aria-labelledby="modal-title"
: 다이얼로그의 제목을 명확하게 지정합니다.aria-describedby="modal-description"
: 다이얼로그의 내용을 설명합니다.
키보드 포커스 유지
모달이 열릴 때, 사용자의 키보드 포커스를 모달 내부에 유지하고 닫힐 때는 원래 위치로 돌아가도록 처리해야 합니다. 이를 위해 JavaScript로 focus()
를 적절히 제어해야 합니다.
<button id="open-modal">모달 열기</button>
<div id="modal" role="dialog" aria-labelledby="modal-title" hidden>
<h2 id="modal-title">로그인</h2>
<button id="close-modal">닫기</button>
</div>
<script>
const openModal = document.getElementById("open-modal");
const closeModal = document.getElementById("close-modal");
const modal = document.getElementById("modal");
openModal.addEventListener("click", () => {
modal.hidden = false;
closeModal.focus(); // 모달이 열릴 때 닫기 버튼에 포커스
});
closeModal.addEventListener("click", () => {
modal.hidden = true;
openModal.focus(); // 모달이 닫힐 때 원래 위치로 포커스 복귀
});
</script>
이렇게 하면 모달이 열릴 때 키보드 포커스가 모달 내부로 유지되며, 닫히면 원래 위치로 돌아가게 됩니다.
Custom UI 컴포넌트에서 WAI-ARIA 적용
기본 HTML 요소로 제공되지 않는 아코디언(Accordion), 탭(Tab)과 같은 UI 컴포넌트는 WAI-ARIA를 활용하여 접근성을 높일 수 있습니다.
아코디언(Accordion)에 WAI-ARIA 적용
아코디언은 펼치거나 닫을 수 있는 UI 컴포넌트로, aria-expanded
속성을 활용하여 현재 상태를 나타낼 수 있습니다.
<button aria-expanded="false" aria-controls="content">더보기</button>
<div id="content" hidden>추가 정보</div>
<script>
const button = document.querySelector("button");
const content = document.getElementById("content");
button.addEventListener("click", () => {
const isExpanded = button.getAttribute("aria-expanded") === "true";
button.setAttribute("aria-expanded", !isExpanded);
content.hidden = isExpanded;
});
</script>
aria-expanded="false"
: 아코디언이 닫힌 상태임을 나타냅니다.aria-controls="content"
: 버튼이 제어하는 콘텐츠를 명시합니다.- JavaScript를 활용하여 상태 변경 시
aria-expanded
값을 업데이트합니다.
탭(Tab) 컴포넌트에서 WAI-ARIA 적용
탭(Tab) UI를 구현할 때, role="tablist"
, role="tab"
, role="tabpanel"
을 사용하여 보조 기술이 탭의 구조를 인식할 수 있도록 할 수 있습니다.
<div role="tablist">
<button role="tab" aria-selected="true" aria-controls="panel1" id="tab1">
탭 1
</button>
<button role="tab" aria-selected="false" aria-controls="panel2" id="tab2">
탭 2
</button>
</div>
<div id="panel1" role="tabpanel" aria-labelledby="tab1">탭 1 내용</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>탭 2 내용</div>
<script>
const tabs = document.querySelectorAll('[role="tab"]');
const panels = document.querySelectorAll('[role="tabpanel"]');
tabs.forEach((tab) => {
tab.addEventListener("click", () => {
tabs.forEach((t) => t.setAttribute("aria-selected", "false"));
panels.forEach((p) => (p.hidden = true));
tab.setAttribute("aria-selected", "true");
document.getElementById(tab.getAttribute("aria-controls")).hidden = false;
});
});
</script>
role="tablist"
: 탭 요소들을 그룹화합니다.role="tab"
: 개별 탭을 정의합니다.aria-selected="true"
: 현재 활성화된 탭을 나타냅니다.role="tabpanel"
: 탭의 내용을 감싸는 요소를 정의합니다.aria-labelledby="tab1"
: 해당 탭과 연결된 콘텐츠를 명시합니다.
이렇게 구현하면 키보드와 보조 기술을 통해 탭 UI를 쉽게 탐색할 수 있습니다.
Recap
WAI-ARIA는 폼 요소, 모달 다이얼로그, 커스텀 UI 컴포넌트에서 접근성을 보장하는 강력한 도구입니다. 그러나 HTML의 기본 기능을 우선적으로 활용하고, 필요한 경우에만 WAI-ARIA를 추가하는 것이 바람직한 접근 방식입니다.
이제 실제 프로젝트에서 WAI-ARIA를 어떻게 적용할 수 있을지 고민해 보시고, 적절한 방법을 선택하여 활용해 보시길 바랍니다.