눈을 감으니 보이는 것들
2022.03.22.
"웹의 힘은 그 광범위함에 있다. 장애에 관계없이 모든 사람이 접근할 수 있다는 것이 절대적인 장점이다." - 팀 버너스 리
장애에 관계없이 모든 사람이 접근할 수 있는 서비스를 만들기 위해 접근성 작업을 하게 됐다. 기존 서비스는 접근성 대응이 미흡했다. 접근성을 개선해 시각 장애인도 서비스의 핵심 기능을 쓸 수 있도록 만들어야 했다.
스크린 리더 사용법 익히기
접근성 대응을 위한 첫 번째 관문은 장애를 가진 유저가 어떻게 서비스를 사용하고 있는지 아는 것이다. 그들과 동일한 방법으로 우리 서비스를 사용할 수 있어야 했다. iOS에서 제공하는 스크린 리더인 보이스오버(VoiceOver)를 익히기로 했다.
우선 '설정 > 손쉬운 사용 > 손쉬운 사용 단축키'로 가서 '측면 버튼 삼중 클릭' 했을 때 'VoiceOver'가 켜지도록 설정한다. 손쉬운 사용 메뉴에서 토글 버튼을 눌러 바로 보이스오버를 활성화할 순 있지만, 보이스오버가 처음인 경우에는 보이스오버로 토글 버튼을 끌 수 없기 때문에 굉장히 당황스러울 수 있다.
이제 측면 버튼을 삼중 클릭해서 보이스오버를 켜자. 개인적으로 처음엔 단조로운 기계음 때문인지 무서웠다. 본능대로 터치로 기능을 제어할 수 없으니 답답하기도 했다. 갑자기 기계음이 나오니 주변에서도 놀라 쳐다보는 일도 있었다. 접근성 작업에는 이어폰이 필수다.
스와이프로 항목을 이동할 수 있고 더블 클릭으로 항목을 클릭할 수 있다. 홈으로 가기 위해선 화면 아래를 길게 끌어 화면 중앙으로 이동하면 된다. 자세한 사용법은 보이스오버와 친해지기를 참고하길 권한다.
보이스오버를 켜고 끄고 항목을 선택할 수 있게 되면 무서웠던 기계음이 제법 귀엽게 느껴지기 시작한다. 이제 작업할 준비가 됐다.
접근성을 개선할 서비스를 스크린 리더로 제어해보기
우리 서비스가 장애를 가진 유저에겐 어떻게 느껴지는지 확인해볼 차례다. 개선할 화면에서 보이스오버를 켜보자. 처음 드는 생각은 "뭐야! 엉망이잖아?"였다. 보이스오버가 투머치토커가 된 것처럼 아무 정보나 읽어주기도 하고 정작 중요한 정보를 읽어주지 않기도 했다.
서비스 접근성 개선하기
중요한 정보를 읽어주지 않는 이유는 지정된 대체 텍스트가 없기 때문이었다. 대체 텍스트는 텍스트 요소가 아닐 때 어떻게 해당 요소를 유저에게 설명할지 정의한 문자열이다. 이미지의 경우 alt라는 속성으로 대체 텍스트를 정의하고 그 외의 요소에선 aria-label과 같은 속성으로 항목이 어떻게 설명될지 정의할 수 있다.
보이스오버가 투머치토커가 된 이유는 요소의 그룹화가 잘못되었기 때문이었다. 클릭이 가능한 항목(div) 하위에 이미지와 텍스트가 있을 때 보이스오버는 이미지와 텍스트를 모두 읽는다. 유저가 알고 싶은 정보는 해당 항목이 클릭이 가능하고 클릭했을 때 어떤 일이 일어나는지에 대한 정보인데 굳이 설명할 필요 없는 이미지 정보도 읽는 것. 이때는 클릭이 가능한 항목의 상위 요소를 버튼(button)으로 수정하면 문제가 해결된다.
컴포넌트별 대응 요령
상태가 있는 버튼은 aria-label에 상태 정보를 함께 전달해줘야 한다. 동의 버튼을 예로 들 수 있다. 이미 동의에 체크한 경우엔 '동의한 체크박스 버튼'이라고 읽혀야 하고 동의하기 전에는 '동의하지 않은 체크박스 버튼'으로 읽혀야 한다.
정보를 담지 않은 이미지는 aria-hidden을 이용하자. 시각적인 미려함을 위해 존재하는 이미지를 읽는 건 중요한 정보에 접근하는 데 방해가 된다. 스크린 리더가 읽지 않아도 되는 경우에는 적절하게 무시할 수 있도록 해줘야 한다.
다이얼로그나 모달의 경우에는 포커스 관리를 해주자. 보통 다이얼로그 같은 요소가 나타날 땐 딤(dim) 요소로 배경을 흐리게 처리한다. 배경을 클릭하면 다이얼로그가 닫히는 게 일반적이다. 별다른 대응을 해주지 않는다면 흐리게 처리된 배경에 있는 정보를 스크린 리더가 읽게 된다. 다이얼로그가 나타났을 때 읽으면 안 되는 요소에 aria-hidden을 활성화해주면 문제가 해결된다. 개인적으론 focus-trap이라는 라이브러리를 사용했다. (React 버전도 있다)
웹뷰 접근성 디버깅
웹뷰 디버깅을 위해 시뮬레이터와 함께 Accessibility Inspector를 사용할 수 있다. 하지만 실제 보이스오버와 다르게 동작하는 경우가 있기 때문에 시뮬레이터 대신 단말기에 직접 빌드해서 보이스오버로 디버깅하길 권한다.
시맨틱 마크업(Semantic Markup)
웹뷰를 기반으로 한 서비스를 개발하면서 시맨틱 마크업을 잊고 지냈다. 앱 밖에서 진입할 경우가 없으니 SEO를 신경 쓰지 않아도 된다는 이유가 컸다. 접근성을 이유로 시맨틱 마크업을 고려하자니 디자인 시스템을 구현하기 어려워진다는 판단도 있었다. 복잡도를 낮추고 빠르게 개발하기 위한 선택이었다. 이 때문에 section, header, footer, nav 같은 태그는 잊히고 div로 대부분의 요소를 구성했었다.
접근성을 작업하면서 과거의 판단에 아쉬움을 느꼈다. 명시적인 변수 선언은 중요하게 생각하면서 정작 마크업에는 의미를 담지 않았다는 게 부끄러웠다. 실제로 접근성을 개선하면서 div를 header, footer, nav로 바꾸고 다이얼로그 컴포넌트의 role 속성을 dialog로 설정했다. 어렵지 않은 작업이었다. 이 단순한 작업으로 보이스오버가 읽는 정보의 수준은 급격하게 상승했다.
접근성 개선의 유익
접근성은 장애가 있는 사람만을 위한 것이라는 오해가 사라졌다. SEO에도 도움이 된다는 말을 하고 싶은 게 아니다. 접근성 대응은 개발자에게 큰 유익을 준다. 어떤 태그를 사용할지 고민하면서 컴포넌트의 용도를 분명히 하게 되고, 대체 텍스트를 정의하면서 해당 항목이 유저에게 어떤 의미인지 확인하게 된다. 이 과정은 서비스에 대한 이해를 높여주고 결국엔 생산성에 긍정적인 영향을 줄 수 있다.
도움 되는 자료
React 공식 문서 - 접근성을 읽어보는 게 많은 도움이 됐다. 디버깅 툴이나 모범 사례도 소개하니 꼭 리액트로 개발하는 경우가 아니라도 확인해보길 권한다.
웹 브라우저에서 접근성 대응이 잘 되었는지 확인하는 데는 Firefox가 가장 좋았다. 특히 페이지 탭 순서보기 기능이 유용했다. 다이얼로그에서 포커스를 관리할 때 많이 사용했다.
FEConf 2021 - 모두를 위한 모바일웹: 접근성을 준수해서 스크린리더 UX 개선하기 영상은 정말 좋은 레퍼런스다. 웹뷰를 기반으로 하는 서비스의 접근성 개선 사례라 특히 좋았다. 실제로 작업하면서 느낀 문제와 해결책을 많이 담고 있어서 공감하며 봤다.
위에서도 언급한 것처럼 보이스오버 사용법은 보이스오버와 친해지기를 참고했다. AOA11Y 채널도 구독하면 이 글보다 정확한 정보를 습득할 수 있다.