웹 접근성 준수를 통한 모두에게 배달되는 일상의 행복

Jan.04.2024 전은영

WEB Web Frontend

들어가며

웹 접근성, 다들 잘 지키고 계신가요?
늘 지켜야지 하는 마음은 굴뚝이지만 바쁜 일정에 조금씩 미룬 경험은 없으셨나요?

배민페이 관리 지면 개편이 그랬는데, 이미 완성된 사이트를 접근성에 맞춰 수정하기는 쉽지 않았습니다. 오랜 시간을 들여 수정해야 했고, 부분적 수정이 아닌 라이브러리나 구조를 갈아엎는 대대적인 수정이 생기기도 했어요.

하지만 개발 단계에서 조금만 더 신경 쓴다면 이런 불상사를 막을 수 있습니다.


웹 접근성이란?

접근성이란 모든 사람이 쉽게 접근할 수 있도록 제품, 디바이스, 서비스, 환경을 설계한다는 것을 뜻해요.
여기서 말하는 “모든 사람”이라는 단어 안에는 남녀노소를 비롯해 디지털 사용 능력치가 낮은 사람부터 높은 사람까지, 또 장애가 없는 사람부터 일시적 또는 영구적인 장애가 있는 사람 모두가 포함됩니다. 즉, 짧게 표현해 보면 다음과 같습니다.

"모두를 위한 설계, Design for Everyone"

WHO에 따르면 세계 인구 15% 이상이 장애를 가지고 있다고 해요. 다시 말하면 최소 10억 명 이상의 유저가 접근성과 관련된 대응이 필요하다는 이야기이기도 합니다.
접근성이 반드시 장애를 가지고 있는 분들에게만 해당되는 이야기는 아니에요. 나이가 들어 디지털 사용에 익숙하지 않은 분들께 서비스를 쉽게 사용할 수 있게 풀어가는 영역도 접근성의 한 부분입니다. 남녀노소, 그리고 디지털 사용 능력치가 낮은 사람들과 높은 사람들, 장애인과 장애인이 아닌 “모든 사람”에게 우리의 서비스가 쉽게 닿을 수 있도록 만들어야 해요.

법적으로도 장애인 차별 금지법에 따라 웹 접근성을 준수할 의무를 지니는데, 장애인 차별 금지 및 권리주제 등에 관한 법률에 따르면 ‘정당한 사유 없이 장애를 고려하지 않는 기준을 적용함으로써 장애인에게 불리한 결과를 초래하거나 정당한 편의 제공을 거부’해서는 안 된다고 서술하고 있어요. 이에 따라 서비스에 접근성 개선 요구가 들어올 경우 접근성을 개선하지 않는 행위는 장애인 차별 금지법에 저촉되는 행위로 판단할 수 있으며 법적인 책임 소재가 있을 수 있습니다.

위 내용을 요약하자면 서비스를 제공할 때 접근성이 고려되어야 하고, 모든 사용자를 위한 전체적으로 개선된 경험을 제공할 수 있어야 합니다. 현대 디지털 사회에서 각종 서비스와 기술들이 나날이 발전하고 있고 웹 기술도 발전하고 있어요. 웹 접근성 또한 접근성에 포함되는 항목으로 웹 기술을 사용한 서비스도 누구나 쉽게 서비스에 접근할 수 있도록 섬세하게 서비스를 만들어야 합니다.


웹 접근성의 단짝, 웹 표준

"웹 표준을 잘 지킨다 = 웹 접근성을 완벽히 보장한다." -> X

정답일까요?
웹 표준을 잘 지킨다고 해서 웹 접근성을 완벽히 보장해 준다고 할 순 없어요.

하지만 올바른 목적으로 적절한 HTML 요소를 사용하는 것만으로도 사용성과 접근성의 많은 부분을 보장해 줍니다.

예시를 볼게요.

div태그와 button태그가 동일한 집모양 이미지로 노출되도록 스타일 작업을 하여 동일하게 노출되도록 스타일 작업된 홈 버튼 예시 이미지

div 태그와 button 태그를 사용하여 동일하게 홈 아이콘 모양으로 노출되는 두 개의 버튼이 있어요.
스크린리더기는 어떻게 읽어줄까요?

<div>home</div> -> 홈
<button>home</button> -> 홈 버튼

동일한 스타일을 제공해 같은 버튼으로 보이지만 스크린리더기는 div 태그가 버튼임을 알 수 없기 때문에 클릭할 수 있는 요소임을 알려주지 않아요.

이로 인해 시각 장애를 가진 사용자들은 홈으로 이동하는 버튼인지 알 수 없어 홈 화면으로 이동할 수 없게 돼요.

또, button 태그에는 PC, 모바일에서 탭 혹은 스와이프를 통해 버튼으로 이동하고, 클릭할 수 있도록 키보드 접근성이 내장되어 있지만 div 태그를 사용했기 때문에 해당 기능또한 사용할 수 없어요.

물론 예시처럼 버튼을 div 태그로 작성하는 분들은 없을 거라 생각해요.
하지만 우린 생각보다 많은 부분에서 실수를 하고, 목적에 맞지 않은 HTML 요소를 제공해 누군가에게 끔찍한 사용성을 경험하게 합니다.

이미지 대체 텍스트

배달의민족 앱 내 장바구니 지면에서 장바구니가 빈 경우 노출되는 예시 이미지

이미지는 적절한 대체 텍스트를 제공해 주어야 한다고 다들 알고 계실 텐데요.
모든 이미지에 대체 텍스트를 제공해야 되는 건 아니에요.
예시에서의 냥이 이미지처럼 단순 꾸밈 요소의 경우 대체 텍스트를 제공해 주지 않아야 됩니다.
불필요한 설명 제공으로 오히려 정보 전달을 방해하기 때문이에요.

배달의민족 앱 내 장바구니 지면에서 오류가 발생된 경우 노출되는 예시 이미지

그렇다면 위 예시에서 헐 이미지의 대체 텍스트는 어떻게 제공되어야 할까요?
"헐"이라는 글자를 읽을 수 있지만 이는 정보 제공을 위함이 아닌 꾸밈 요소로 사용된 제공되지 않아도 되는 정보이기 때문에 대체 텍스트를 제공하지 않아야 합니다.

여기서 질문!

단순 꾸밈 요소인 img 에는 alt 속성을 생략해도 될까요? -> X

정보 전달에 영향을 주지 않는 꾸밈 요소는 반드시 빈 alt=“”값으로 제공되어야 하는데요.

alt 속성을 없애는 것이 아닌 빈 값을 넣어 주어야 하는 이유는 스크린리더기가 이미지의 alt 속성이 없는 경우 이미지명을 읽어주기 때문에요.

빈 값으로 제공되면 꾸밈 요소로 판단하여 읽지 않고 넘어가니 잊지 말고 꼭 넣어 주도록 합시다.

WAI-ARIA

(Web Accessibility Initiative – Accessible Rich Internet Application)

WAI-ARIA는 W3C에서 발표한 기술 명세로, 접근성 및 상호 운용성을 향상시키기 위한 목적으로 탄생했어요.

역할(Role), 속성(Property), 상태(State) 정보를 제공하여 접근성을 개선할 수 있도록 지원해 줘요.

  • Role(역할)은 UI에 포함된 특정 컴포넌트의 역할을 정의
  • Property(속성)은 컴포넌트의 특징이나 상황을 정의하며 ‘aria-*’라는 접두사를 사용
  • State(상태)는 컴포넌트의 상태 정보를 정의

역할(Role)

HTML 요소는 암묵적으로 가지고 있는 역할(Role)이 있어요.

<button role="button">버튼</button> -> X

예를 들어 <button>버튼</button>role="button"을 내재하고 있어요.
그러니 button role="button" 과같이 역할을 중복해서 정의할 필요는 없습니다.


<button role="presentation">버튼</button> -> X

또, button 태그와 같이 요소의 역할을 알려줘야 하는 경우에는 role=“presentation” 을 부여해서는 안 돼요.
스크린 리더 등의 보조 기기는 role=“presentation”로 지정된 요소 본연의 역할을 무시하고 단순히 정보를 전달하기 위한 요소로 인식하기 때문이에요.


<h1 role=”button”>배달 홈</h1> -> X

Role 속성을 이용해 요소의 네이티브 의미를 변경하는 것도 지양해야 되는데, 예시 코드와 같이 h1 태그에 button 역할을 부여하면 앞서 얘기한 키보드 접근성을 제공받을 수 없어요.

각 요소별로 적용할 수 있는 역할이 정해져있으니 작업 전 문서를 확인하면 도움이 될 것 같아요.
(https://www.w3.org/TR/html-aria/#docconformance)


<div role=”main”></div> -> O
<div role=”MAIN”></div> -> X
<div role=”Main”></div> -> X

최신 브라우저는 aria-*의 속성값에 대소문자를 구분하지 않는 것으로 처리하지만 모든 브라우저 버전 및 보조기술이 올바르게 구문 분석을 하지 않습니다.
그러니 role 또는 aria-*의 속성값을 정의할 때 소문자를 사용하는 것이 좋아요.

Landmark

스크린 리더 사용자가 웹사이트를 쉽게 탐색할 수 있도록 ARIA Landmark Role을 사용할 수 있는데요.
랜드마크는 화면에서 제공되는 콘텐츠 영역이 어떤 구조를 가지고 어떤 역할을 하는지 식별할 수 있도록 도와주는 표지판 기능으로, 기존 웹 접근성 지침에서 요구하는 건너뛰기 링크의 발전된 모습이고 콘텐츠 블록의 제목 제공보다 명확한 영역 구분이 가능해요.
스크린 리더 사용자는 랜드마크를 탐색하는 핫키를 이용하여 문서의 주요 영역을 자유롭게 탐색할 수 있습니다.

랜드마크는 banner, navigation, search, main, region, complementary, form, contentinfo로 8가지의 역할이 정의되어 있어요.

역할 상세 정보
Banner header 요소와 비슷한 역할을 해요. 대체로 사이트 전체에 걸쳐 동일한 형태로 제공되는데, 저는 처음에 banner라는 역할의 명칭 때문에 광고 배너 영역으로 오해했어요. 사이트의 로고나 제목 등을 포함할 수 있는 주로 브랜딩이나 사이트의 아이덴티티를 나타낼 수 있는 정보를 의미한다는 걸 잊지 맙시다.
navigation nav 요소와 동일한 역할을 하기 때문에 앞서 설명드린 것과 같이 역할을 중복해서 사용하면 안 돼요. 2~3개 이상 사용하지 않아야 하고, 여러 개의 navigation을 사용할 경우 aria-label 속성을 함께 사용하여 어떤 내비게이션 영역인지 알 수 있도록 제공해야 합니다.
search 검색을 위한 입력 폼 영역에서 사용할 수 있어요. 식당 검색 영역을 예로 들 수 있겠네요.
Main main 요소와 같은 역할을 하므로 역할을 중복해서 사용하면 안 돼요. 웹 페이지 내에서 main role은 한 번만 선언할 수 있으니 주의하셔야 합니다.
region section과 비슷한 역할을 합니다.
complementary aside 요소와 동일한 역할을 해요. 메인 콘텐츠를 보충할 수 있는 부가적인 영역이며, 기본 콘텐츠와 분리되어도 의미를 유지하는 콘텐츠 영역이에요.
form form 요소와 동일한 역할을 하며, 입력 가능한 영역임을 알려주는 역할이에요.
contentinfo footer와 비슷한 역할을 하며, 주로 개인정보 정책, 저작권 정보를 식별하는 데 사용돼요.

보다 보니 구조적 마크업이 떠오르지 않나요?

앞서 설명드렸던 것과 같이 적절한 태그를 사용하는 것만으로도 해당 영역에 대한 정보 제공을 충분히 해줄 수 있습니다.

ARIA의 속성과 상태

우리는 작업할 때 요소가 이미 적절한 역할과 의미를 가지고 있지 않는 한 요소에 ARIA 역할과 상태 및 속성을 할당해야 해요.

ARIA를 적용하면 브라우저의 접근성 API에 추가 정보만 노출되고 DOM에는 영향을 주지 않으니 이 부분은 신경 쓰지 않아도 됩니다.

상태 및 속성은 widget, live region, drag and drop, relationship으로 분류할 수 있어요.
이 중에 widget의 modal과 live region의 live 속성에 대해 예시를 들어 설명드리려 하는데요.
정말 많은 속성이 있으니 꼭 찾아보시고, 모든 브라우저 및 보조 기기에서 지원되지 않는 속성도 많으니 사용 시 주의해 주세요.

배민페이 계좌 등록지면에서 이탈 시 노출되는 컨펌창 예시

계좌 등록 지면에서 이탈 시 노출되는 컨펌창을 예시로 들어볼게요.
(예시 코드와 같이 실제 마크업 되어있진 않지만 설명드리기 위해 간단하게 작성했어요.)

화면의 컨펌창 뒤에는 배경을 가려주기 위한 backdrop이 존재해요.
backdrop을 제외한 영역이 알럿 역할을 하는 것을 알려주기 위해 role을 alertdialog로 설정해 주었고,
aria-modal 속성을 true로 주었어요.

aria-labelledby 속성에 어떤 컨펌창인지를 알려주는 계좌 등록 지면 이탈 요소의 id값을 연결해 주었는데, 해당 타이틀은 화면에 노출되지 않으므로 스타일 설정을 통해 가려줍니다. display: none을 통해 가리게 되면 해당 요소를 무시하니 주의해 주세요.

aria-describedby를 통해 컨펌의 목적을 설명하는 요소의 id를 연결해 주어 확인 창에 액세스 가능한 설명을 제공합니다.


배민페이머니 충전지면 충전금액 설정 예시 이미지

다음으로는 live region의 live 속성입니다.
예시 화면은 배민페이 충전 지면인데요.
금액 버튼을 클릭하면 충전 금액이 자동으로 설정되는 형태입니다.

코드를 보겠습니다.
p 태그에 aria-live 값을 보시면 assertive로 설정되어 있는 것을 알 수 있는데요.
위 예시에서 "+5만원" 을 클릭하면 변경된 50,000을 읽어주어 현재 설정된 값이 업데이트 된 것을 사용자에게 즉시 알려주고, 다시 한 번 "+5만원"을 클릭하면 스크린 리더는 업데이트 된 값인 100,000을 읽어줍니다.
이 설정을 통해 사용자에게 정보가 업데이트되었음을 알릴 수 있어요.

마치며

배민앱을 비롯한 우아한형제들에서 제공하는 서비스들은 집, 사무실, 가게 문 앞으로 평범하고도 대단한 행복이 배달될 수 있도록 많은 일들을 하고 있습니다.
“문 앞으로 배달되는 일상의 행복”이라는 우리의 비전을 모두에게 놓치지 않고 전달할 수 있도록 더욱 노력하는 우리가 되었으면 좋겠습니다.

[1] mdn web docs Accessibility

[2] aria-live

[3] 예제로 살펴보는 WAI-ARIA