본문 바로가기

프론트엔드

웹접근성(web accessibility), SEO 개선하기

  • 프로젝트: loplat homepage
  • 키워드: web accessibility, SEO, lighthouse, semantic tag, screen reader, aria
  • 상황
    1. 로플랫 홈페이지를 chrome lighthouse로 검사한 결과, a11y과 SEO에서 만족스럽지 못한 점수가 나왔다.
      개선 이전의 lighthouse 결과
    2. 패스트캠퍼스에서 'TheRED: 견고한 UI 설계를 위한 마크업 가이드 by정찬명' 이라는 강의를 수강한 뒤, 홈페이지 웹접근성 개선을 위한 작업을 수행하였다.
  • 해결과정
    1. 'HeadingsMap'이라는 크롬 확장 프로그램을 이용하여 페이지의 heading 구조를 확인해보았다.
      heading tag는 (구글 등의) 웹 크롤러가 페이지의 목차를 파악하는데 중요한 태그이며, 스크린 리더 사용자가 페이지를 빠르게 탐색할 때도 유용하게 쓰이므로 반드시 개선해야한다.
      기존 채용 페이지 heading map
      레거시때문에 hx tag를 순서대로 이용하지 않고 있었는데, 순서에 맞도록 모두 수정하였다.
      수정 후 heading map
    2. 구글에 '로플랫'을 검색한 결과, 모든 title과 description이 동일한 문제가 있었다.
      구글 '로플랫' 검색 결과

      page별로 description을 다르게 해주고 title도 페이지별로 다르게 개선해주었다.
      채용페이지는 title 앞에 Career를 추가

      page title은 스크린리더 사용자에게 현재 페이지가 어떤 페이지인지 알려주는 제목이기 때문에 페이지별로 명시해주는 것이 좋고, 이왕이면 맨 앞에 적는 것이 좋다.('로플랫 - Career' 보다는 'Career - 로플랫')
      또한 ' - ' 또는 ' | ' 를 이용하여 눈에 띄게 공간을 분리하는 것이 좋다.

      각 페이지별로 Layout template에 title prefix와 description prop을 넘겨주어 해결했다.
        <Layout
        pageName="Career"
        description="절차와 프로세스는 실수를 줄이는 데 유용하지만, 개인의 능력을 제한하며 한계를 만들기 때문에 이를 최소화하고자 우리는 항상 노력합니다. 사람의 역량을 최대화하기 위해 자유롭고 수평적인 조직문화를 추구합니다."
      >​


    3. html tag의 lang 속성을 명시했다.
        <html lang="ko">

      html 기본 템플릿(IDE에서 자동 완성해주는 HTML 템플릿)에 있는 lang 속성의 기본 값이 "en"이기 때문에 제대로 관리되지 않은 사이트들은 lang="en" 이거나 lang 속성 자체가 없다. 따라서, 구글 웹크롤러는 lang 속성을 신뢰하지 않고 무시한다고 한다.
      하지만 스크린 리더에게 언어는 중요한 속성이 될 수 있기 때문에 반드시 명시해야한다.

    4. a, button 태그에 적절한 aria-label을 적용했다.
      맥북에서 'command + f5' 로 voice over를 실행할 수 있고, 스크린리더와 유사한 방식으로 웹페이지를 읽어준다.
      개선 이전 Solution 버튼 voice over
      개선 이전 Solution 버튼 펼침 상태 voice over
      예를 들어, Header의 'Solution' 버튼은 하단 링크를 보이거나 숨기는 toggle button이다. 하지만 'Solution, 버튼'은 무엇을 의미하는지 이해하기 힘들며, 실제로 하단 링크를 펼치면 하위 텍스트까지 모두 읽혀서('Solution loplatXloplat i, 버튼') 흐름 파악이 더욱 어려워진다.

      따라서 적절한 aria-label 속성을 부여해주었다.
      aria-label 적용
      aria-label을 적용한 후, '메뉴 펼치기'를 위한 버튼임을 알려줄 수 있고 펼친 후에도 하위 텍스트와는 독립적으로 텍스트를 유지한다.(메뉴 닫기로 개선하면 더 좋을 듯하다.)

      비슷한 방식으로 페이지 전체의 button과 a 태그에 적절한 aria-label을 입력해주었다.
    5. 키보드 tab으로 페이지를 탐색할 때, lottie 애니메이션에 focus가 가는 현상이 발생했다. 이슈를 찾아보니 react-lottie에 tabindex가 0으로 하드코딩되어있어서 피할 수 없는 현상이었다.
      lottie에 focus가 이동

      react-lottie를 감싸는 WrapperComponent를 만들고 tabindex를 -1로 변경하도록 개선했다.
        import React, { useEffect, useRef } from 'react';
      import ReactLottie, { LottieProps } from 'react-lottie';
      
      const Lottie = (props: LottieProps): React.ReactElement => {
        const lottieWrapper = useRef<HTMLDivElement>(null);
      
        useEffect(() => {
          if (lottieWrapper.current?.firstElementChild) {
            lottieWrapper.current.firstElementChild.setAttribute('tabindex', '-1');
          }
        }, []);
      
        return (
          <div ref={lottieWrapper} style={{ width: '100%', height: '100%' }}>
            <ReactLottie {...props} />
          </div>
        );
      };
      
      export default Lottie;​

      개선 후에는 lottie 애니메이션에 focus가 이동하지 않는다.
  • 의의
    1. chrome lighthouse 재검사 결과, a11y와 SEO 점수가 만족스러울 정도로 증가했다!
      (a11y에서 감점된 3점은 명암비(contrast-ratio) 부문인데, 디자이너께서 색상 수정이 어렵다고하여 보류하기로 했다.)

개선 이후 lighthouse 결과