들어가며
회사에서 들었던 웹 접근성을 고려한 콘텐츠 제작 가이드 강의에서 웹 접근성 지침 준수는 모든 웹사이트의 의무사항이라고 들었습니다. 웹 접근성 마크를 취득해야 하는 프로젝트가 아니고서야 접근성 개선 작업은 많은 시간과 노력이 필요하기 때문에 굳이 작업하지는 않습니다. 작년에 진행한 프로젝트에서 웹 접근성 작업을 어떻게 해야 할지 고민하다 WAI-ARIA를 처음 접하고 경험하게 되었습니다.
언젠가부터 React, Vue, Angular와 같은 동적 콘텐츠를 제작하는 SPA 환경 프로젝트가 점차 많아지면서 WAI-ARIA는 사용자에게는 적절한 정보를 개발자에게는 편리하게 접근성을 높일 수 있는 기술이라 생각합니다. 복잡하고 동적으로 변화하는 웹 환경에서 신체적, 환경적 조건에 차별 없이 동등하게 이용할 수 있도록 도와주는 WAI-ARIA 기술에 대해 소개하고자 합니다.
WAI-ARIA란?
Web Accessibility Initiative – Accessible Rich Internet Applications
WAI 는 W3C에서 웹 접근성을 담당하는 기관으로 ARIA는 RIA 환경의 웹 접근성에 대한 표준 기술 규격을 의미
RIA : 정적인 HTML, 단순한 자바스크립트 환경의 웹이 아닌 동적인 자바스크립트와 Ajax와 같은 기술을 사용한 환경에서 수준 높은 UX(User eXperience)를 제공하는 웹 애플리케이션
WAI-ARIA를 사용하는 이유
- RIA의 동적 웹 애플리케이션 접근성 보장 지침이 부족
- Ajax, 통한 실시간 변경 콘텐츠, SPA 방식의 콘텐츠 변경
- 화면 확대사용자의 경우, 가시 범위 밖 콘텐츠의 변경 내용 인지 불가능
WAI-ARIA를 이용해서 개발자가 의도한 유저 인터페이스(User Interface) 행동이나 구조적인 정보를 스크린 리더와 같은 보조 기술에 전달하여 시각/인지 장애인들에게 일반 사용자들과 동일하게 정보를 제공하고 행동을 유도함으로써 웹페이지 탐색을 돕는 사용자 경험(UX)을 제공합니다.
WAI-ARIA 사용 하는 방법
ARIA는 HTML 태그에 필요한 정보를 제공해주는 보조 기술로서 아래의 내용을 주의하여 WAI-ARIA를 사용해주세요.
-
HTML5 Section 요소와 중복되어 사용하지 말아 주세요.
HTML5에서 추가된 의미 있는 태그를 먼저 사용하고 의미를 부가적으로 설명해주고자 할 때 WAI-ARIA의 role을 추가해줍니다.
HTML5 Section tag | Landmark Role | 설명 |
---|---|---|
<nav> |
role="navigation" |
다른 페이지 또는 페이지 내 특정 영역으로 이동하는 링크 콘텐츠 영역(메인 메뉴 혹은 서브 메뉴로 사용) |
<main> |
role="main" |
본문의 주요 콘텐츠 영역. 한 페이지 내에 1개만 사용이 가능하며, <article> , <aside> , <footer> 요소의 하위 요소로 사용할 수 없다 |
<aside> |
role="complementary" |
주요 콘텐츠와 연관이 적은 의미 있는 콘텐츠 영역 (예) 날씨, 주식 |
<form> |
role="form" |
폼 요소로 서버에 전송될 수 있는 콘텐츠 |
X | role="application" |
<div> 요소와 같이 그룹 역할을 하는 요소로 대체 |
X | role="banner" |
<header> 요소와 비슷한 의미<header role="banner"> 로 사용 시 페이지별 한 번만 사용 |
X | role="search" |
검색의 역할을 담당하는 서식 영역<div> 또는 <form> 요소 사용 권장 |
X | role="contentinfo" |
<footer> 요소와 비슷한 의미<footer role="contentinfo"> 로 사용 시 페이지별 한 번만 사용 |
- 의미를 가진 HTML 요소를 함부로 바꾸지 말아 주세요.
// X
<h1 role="button">PXD XE GROUP</h1>
// △
<h1><span role="button">PXD XE GROUP</span></h1>
// ○
<h1><button>PXD XE GROUP</button></h1>
- 키보드를 사용하여 접근할 수 있게 해주세요.
만약 <button>, <input>
요소들처럼 키보드 지원이 되는 요소를 <div>
와 WAI-ARIA로 작업해야 한다면, 동일하게 작동되도록 작업해주세요.
// html5
<button>버튼<button>
</select>
// div + WAI-ARIA
<div role="button" tabindex="0">버튼</div>
- 사용자의 브라우저와 보조기기가 WAI-ARIA를 지원하는지 확인해주세요.
WAI-ARIA는 우리가 사용하는 크롬, 인터넷 익스플로어, 사파리 등의 최신 버전 브라우저들은 대체로 지원을 합니다. 아래의 이미지는 Can I Use에서 확인한 WAI-ARIA의 지원 범위를 보여줍니다.
Ajax 등을 이용해 콘텐츠가 동적으로 변경되는 요소에 사용되는 aria-live 속성을 대표적으로 알아보면 스크린 리더기 JAWS(JAWS for Windows)는 version 10.0, Windows Eyes는 version 8.0부터 사용 가능합니다.
WAI-ARIA 구조
WAI-ARIA를 구성하는 역할, 속성, 상태 기능은 HTML 요소에 보충하여 사용됩니다.
1. 역할(Role) : 컴포넌트, 요소 내 역할을 정의 우리는 대체로 눈으로 인지하고 학습해온 경험으로 아래의 이미지를 봤을 때 ‘탭 버튼이구나! 버튼을 누르면 아래의 콘텐츠는 변경이 되겠지’라고 생각 할 수 있습니다.
개발자는 탭 버튼을 작업할 때 단순히 <ul>
, <li>
, <a>
태그로 탭을 구성합니다.
WAI-ARIA role=“tabList”, role=“tab” role=“tabpanel” 로 스크린 리더기 사용자에게 더 정확한 정보를 제공할 수 있습니다.
// 일반적인 작업
<ul class="btnList">
<li>
<a href="#" class="on">관람정보</a>
</li>
<li>
<a href="#">관람순서</a>
</li>
<li>
<a href="#">장애인 관람객 이용안내</a>
</li>
</ul>
<div class="wrap-tab-contents">
<div id="tabpanel01" class="tab-contents on"><p>관람정보 콘텐츠</p></div>
<div id="tabpanel02" class="tab-contents"><p>관람순서 콘텐츠</p></div>
<div id="tabpanel03" class="tab-contents"><p>장애인 관람객 이용안내 콘텐츠</p></div>
</div>
// WAI-ARIA 적용
<ul class="btnList" role="tabList">
<li>
<a
href="#"
id="tab01"
class="on"
role="tab"
aria-selected="true"
aria-controls="tabpanel01"
>관람정보</a
>
</li>
<li>
<a href="#" id="tab02" role="tab" aria-selected="false" aria-controls="tabpanel02"
>관람순서</a
>
</li>
<li>
<a href="#" id="tab03" role="tab" aria-selected="false" aria-controls="tabpanel03"
>장애인 관람객 이용안내</a
>
</li>
</ul>
<div class="wrap-tab-contents">
<div
id="tabpanel01"
class="tab-contents"
role="tabpanel"
aria-labelledby="tab01"
tabindex="0"
>
<p>관람정보 콘텐츠</p>
</div>
<div
id="tabpanel01"
class="tab-contents"
role="tabpanel"
aria-labelledby="tab02"
tabindex="0"
hidden="true"
>
<p>관람순서 콘텐츠</p>
</div>
<div
id="tabpanel01"
class="tab-contents"
role="tabpanel"
aria-labelledby="tab03"
tabindex="0"
hidden="true"
>
<p>장애인 관람객 이용안내 콘텐츠</p>
</div>
</div>
위 코드를 NVDA(NonVisual Desktop Access)라는 스크린 리더기 프로그램으로 들어보면 의미가 다르게 전달 되는 것을 알 수 있습니다.
- 탭 메뉴 WAI-ARIA 적용 전
- 불릿 [링크] 관람정보
- 불릿 [링크] 관람순서
- 불릿 [링크] 장애인 관람객 이용안내
-> 페이지를 이동하는 “링크” 태그로서의 의미만을 정보만 전달해주다.
- 탭 메뉴 WAI-ARIA 적용 후
- 불릿 [탭] 선택됨 관람정보
- 불릿 [탭] 관람순서
- 불릿 [탭] 장애인 관람객 이용안내”
-> 버튼의 역할이 “탭”이라고 명시해주고, 선택된 요소 정보도 함께 전달해줄 수 있다.
2. 속성(Property) : 컴포넌트의 특징이나 상황을 정의
폼 요소의 필수 요소와 관련된 속성인 aria-required
, 텍스트 레이블이 없이 이미지로 표현될 때 정보를 부여 설명해주는 aria-label
, 업데이트된 정보의 상황에 대한 aria-live
와 같이 사용자에게 인지 할 수 있도록 도와주는 속성들이 있습니다.
검색이라는 안내 텍스트 없이 버튼을 나타낼 때 시각 정보를 이용할 수 없는 사용자는 어떤 버튼인지 알 수 없습니다. 물론 우리는 대체 텍스트를 이용할 수 있지만, aria-label
을 이용하여 버튼 요소에 검색이라는 설명을 추가할 수 있습니다.
<button class="btn_search"></button>
// 숨김 텍스트 이용
<button class="btn_search">
<span class="hidden">검색</span>
</button>
// WAI-ARIA 적용
<button class="btn_search" aria-label="검색"></button>
3. 상태(State) : 컴포넌트 상태 정보를 정의
메뉴의 활성 여부를 보여주는 aria-expanded
, aria-selected
, 폼 요소 유효성 검증과 관련 있는 aria-invalid
와 같이 현재 상태와 변화된 값을 가집니다.
상태가 변화될 때 확장됨 / 축소됨, 눌림 / 눌리지 않음 으로 음성으로 알려주며, aria-invalid
상태에 따라 에러 텍스트를 노출함으로써 사용성을 높여줄 수 있다. 흔히 사용되는 탭, 아코디언, 폼 요소, 토글버튼 등 상태 값을 이용하여 Javascript 기능을 만듭니다.
아코디언 메뉴의 활성 상태 값인 aria-expanded
를 이용하면 스크린 리더기가 상태 정보(확장됨 or 축소됨)를 읽어 줄 수 있습니다.
javascript로 기능을 정의할 때 상태 값(aria-expanded)을 통해 작성할 수 있고 또한 css 처리를 위한 .open 클래스 바인딩을 하지 않아도 됩니다.
// WAI-ARIA 적용 전
<ul class="btnList">
<li class="open">
<button>[XD그룹] UI 기획 디자이너 (경력)</button>
<div>[XD그룹] UI 기획 디자이너 (경력) 콘텐츠</div>
</li>
<li>
<button>[XE그룹] UX Engineer (신입/경력)</button>
<div>[XE그룹] UX Engineer (신입/경력) 콘텐츠</div>
</li>
<li>
<button>인턴 디자이너</button>
<div>인턴 디자이너 콘텐츠</div>
</li>
</ul>
<style>
li {
background-image: url(arrow_down.png);
}
li.open {
background-image: url(arrow_up.png);
}
</style>
// WAI-ARIA 적용 후
<ul class="btnList">
<li>
<button id="accordion-head01" aria-controls="accordion-region01" aria-expanded="true">
[XD그룹] UI 기획 디자이너 (경력)
</button>
<div id="accordion-region01" role="region" aria-labelledby="accordion-head01">
[XD그룹] UI 기획 디자이너 (경력) 콘텐츠
</div>
</li>
<li>
<button id="accordion-head02" aria-controls="accordion-region02">
[XE그룹] UX Engineer (신입/경력)
</button>
<div id="accordion-region02" role="region" aria-labelledby="accordion-head02">
[XE그룹] UX Engineer (신입/경력) 콘텐츠
</div>
</li>
<li>
<button id="accordion-head03" aria-controls="accordion-region03">
인턴 디자이너
</button>
<div id="accordion-region03" role="region" aria-labelledby="accordion-head03">
[XD그룹] 인턴 디자이너 콘텐츠
</div>
</li>
</ul>
<style>
li {
background-image: url(arrow_down.png);
}
li button[aria-expanded='true'] {
background-image: url(arrow_up.png);
}
</style>
- 아코디언 메뉴 WAI-ARIA 적용 전
- XD 그룹 UI 기획 디자이너 괄호 열고 경력 괄호 닫고 버튼
- (버튼 누른 후 음성 변화 없음)
-> 아코디언 버튼 메뉴가 활성화/비활성화 상태에 대한 정보를 알 수가 없다.
- 아코디언 메뉴 WAI-ARIA 적용 후
- XD 그룹 UI 기획 디자이너 괄호 열고 경력 괄호 닫고 버튼
- (버튼 누른 후) 확장됨
-> 아코디언 버튼 메뉴가 활성화됐을 경우, “확장됨, 축소됨”으로 상태 정보를 전달해줄 수 있다.
위에 소개된 역할, 속성, 상태의 다양한 값들은 아래의 링크로 자세히 알아볼 수 있습니다.
마치며
현재 그룹 블로그 내 이슬비 책임님이 웹 접근성을 준수하는 코드 작성하기 시리즈를 포스팅 중인데 WAI-ARIA에 대한 이해도를 높이고 읽으면 더 좋지 않을까 싶어요.
이번 포스팅이 WAI-ARIA에 대한 이해와 실제 코드를 읽을 때 조금이라도 도움이 되었길 바랍니다.
감사합니다.