[React] 웹 접근성 강화하기

js43o·2022년 12월 27일
1
post-thumbnail
post-custom-banner

'웹 접근성'이란?

저시력자, 청각이상자, 고령자 등을 가리지 않고 모든 사람이 웹 사이트에서 제공하는 정보에 동등하게 접근하고 이해할 수 있도록 보장하는 것을 말한다.

크롬 개발자 도구에는 현재 페이지에 대한 웹 접근성 점수를 측정할 수 있는 Lighthouse라는 도구가 내장되어 있다.
진행 중인 리액트 프로젝트를 마무리하기 전, Lighthouse를 통해 부족한 접근성 요소를 개선해보자.

측정 결과, 메인 페이지의 초기 점수는 76점이었으며, 다른 페이지도 이와 비슷한 점수가 나왔다.
Lighthouse에서는 단순 점수 산정을 넘어 정확히 어떤 부분이 웹 접근성을 충족하지 못했는지 알려주므로 빠르고 편하게 개선시킬 수 있다.


1. 버튼에 접근 가능한 이름 명시하기

텍스트가 포함되지 않은 아이콘형 버튼은 스크린 리더가 해당 버튼이 무슨 용도인지 알려줄 수 없게 된다. 이때는 aria-label 속성을 지정하여 눈에 보이지 않는 정보를 브라우저에게 전달해주도록 할 수 있다.
img 태그의 alt 속성과 유사하다. 모든 버튼에 대해 각 용도 및 목적을 명시해주었다.

2. 뷰 포트 제한 해제하기

리액트 기본 옵션으로 뷰 포트 content 속성의 값은 "width=device-width, user-scalable=no, initial-scale=1"으로 지정되어 있는데, 이때 마지막 두 가지가 접근성 측면에서 문제가 되는 모양이다.

  • user-scalable: 사용자가 페이지를 확대 또는 축소하는 것의 허용 여부
  • initial-scale: 페이지의 초기 줌 레벨을 지정

W3C github의 권장에 따라 위 두 가지 규칙을 빼주었다. 기능성 측면에서도 크게 지장이 없었다.

3. 색상 대비 늘리기

명암이 뚜렷하지 않은, 즉 대비가 적은 텍스트의 경우 사용자의 시력 또는 환경에 따라 읽기 힘든 경우가 있을 수 있다.

명암비는 작은 글씨의 경우 4.5, 큰 글씨의 경우 3 이상이어야 한다. (WCAG 통과 기준 1.4.3)

내 프로젝트의 경우 주로 '비활성화 상태'나 '보조 설명' 등의 의미를 나타낼 때 메인 색상보다 옅은 색을 썼었는데, 이것이 밝은 배경색과 합쳐지면서 문제가 되었다.
원래 의도를 벗어나지 않는 선에서 최대한 큰 대비를 갖도록 조정해주었다.

  • Constrast Finder라는 사이트에서 쉽게 두 색상의 명암비를 계산할 수 있다. 현재 색과 비슷하면서도 기준에 적합한 색을 샘플로 내어주는 기능도 있어 매우 유용함!

다만, 명암비를 4.5 이상으로 맞추게 되면 배경색이 글자색에 비해 극단적으로 밝아지거나 어두워지게 된다. 내 경우는 강조색(청록) 배경 위의 하얀색 글자가 문제가 되었다. 명암비를 맞추려고 색을 이리저리 바꿔봐도 다 보기 안 좋아서 고민이 많았다. 디자인 관점에서는 꽤나 큰 제약이 생긴다고 봐야겠다.

4. input 태그에 label 붙이기

일부 input 태그의 이름을 나타낼 때 label 대신 다른 일반적인 태그(div 등)를 이용하여 설명하는 부분이 있어서 이를 고쳐주었다.

이때 리액트 컴포넌트에서 반환하는 것은 일반 html이 아닌 jsx 객체이므로, label이 가리킬 요소를 지정할 때 for 속성 대신 htmlFor 속성을 쓰는 것을 유의하자.

5. ul 태그 안에는 li 요소만 넣기

컴포넌트가 리스트 형태임을 가리키기 위해 ul 태그를 사용했으면 그 자식들은 반드시 li 태그로 이루어져야 한다. 다른 태그가 삽입되면 스크린 리더가 리스트를 제대로 읽지 못하는 듯하다.

ul 태그 컴포넌트의 모든 자식들의 태그를 li로 고쳐주었다.


위 과정을 거친 후 다시 접근성 점수를 측정한 결과, 대부분의 페이지 점수가 100점에 가깝게 올랐다.

물론 좋은 일이지만 Lighthouse가 모든 웹 접근성 항목을 검사해 주는 것은 아니기에, 다른 항목들도 직접 확인하고 개선하는 시간이 필요하다.


6. tabIndex를 통한 키보드 접근성 확보

키보드 접근성이란 마우스와 같은 장치를 이용하기 어려운 사용자가 키보드 조작만으로도 웹 페이지의 모든 정보 및 기능을 이용할 수 있도록 하는 것을 말한다.
이때 사용자는 주로 'Tab'키와 'Shift + Tab'키를 통해 페이지에서 상호작용 가능한 요소를 탐색하게 되므로, 모든 상호작용 가능한 요소가 올바른 순서로 Tab키에 반응하도록 만들어야 한다.

내 프로젝트의 경우, 이러한 개선 과정을 거쳤다.

  • Tab키가 <div>, <li> 등의 요소에 반응하지 않음
    • 이는 지극히 당연한 현상이다. 애초에 상호작용을 염두에 두고 만들어진 태그(<a>, <button>, <input> 등)가 아니기 때문이다.
    • 해당 태그가 버튼 역할을 한다면 내부에 <button> 태그를 한 번 더 중첩하여 Tab키에 반응하도록 하였다.
    • 상호작용하지 않는 요소라도 Tab키에 의해 focus 되어야 하는 요소라면, 속성으로 tabIndex={0}을 부여한다.
  • Tab키가 아직 보이지 않는 요소(Modal 등)에도 반응함
    • 해당 요소가 보이지 않는 상태라면 display: none 속성을 명시한다. 그러면 Tab키가 해당 요소를 건너뛰게 된다.
    • 만약 display: none을 쓸 수 없다면 tabIndex={visible ? 0 : -1} 속성을 부여하여 요소가 보이지 않을 때 Tab키가 반응하지 않도록 강제한다.
  • Tab키가 중간에 보이도록 변한 요소(Modal 등)를 건너뜀
    • 해당 요소에 useRef hook을 이용하여 ref 값을 할당한다.
    • 요소의 현재 상태(visible)가 바뀔 때마다 visibletrue인지 확인하고 (useEffect hook 이용) 만일 그렇다면 ref.current.focus() 함수를 실행하여 해당 요소가 강제로 focus 되도록 한다.

아래는 위 사항을 적용한 Modal 컴포넌트 코드이다.

const Modal = ({ isVisible, children }: ModalProps) => {
	const ref = useRef<HTMLDivElement | null>(null);

	useEffect(() => {
  	if (!ref.current) return;
  	if (isVisible) ref.current.focus();
	}, [isVisible]);

	return (
  	<ModalWrapper visible={isVisible}>
    	<ModalBlock visible={isVisible} ref={ref} tabIndex={0}>
      	{children}
    	</ModalBlock>
  	</ModalWrapper>
	);
};
profile
공부용 블로그
post-custom-banner

0개의 댓글