Skip to content

프론트엔드 접근성 개선 보고서

헤인 edited this page Oct 24, 2024 · 3 revisions

우리 서비스의 핵심 영역

코드잽 서비스에서는 다음과 같은 핵심 플로우를 선정해보았습니다.

로그인 → 템플릿 작성 페이지 이동 → 템플릿 작성 → 작성한 템플릿 조회

해당 핵심 영역에서의 접근성 문제 정의 및 개선

- Header의 햄버거 메뉴가 읽히지 않는다

햄버거 메뉴가 div로 되어있어 키보드 tab으로 접근 시 포커스가 가지 않았고 스크린리더가 읽지 못했다.

→ 해당 컴포넌트를 button 태그로 변경 후 aria-label을 추가한다

  • 실제 개선 과정과 결과

before

-.mov

after

-.mov

- 새 템플릿 버튼에 포커스 시, 어떤 동작이 일어나는지 알려주지 않는다

화면에는 ‘+’ 기호와 새 템플릿이 함께 있어서 해당 버튼이 ‘새 템플릿 추가’ 버튼임을 알 수 있으나 스크린리더에는 ‘새 템플릿’ 만 읽힌다.

→ aria-description='템플릿 작성 페이지로 이동됩니다.’ 를 추가하고, puls 아이콘의 aria-label을 제거한다

  • 실제 개선 과정과 결과

before

-.mov

after

-.mov

- 아이디, 비밀번호 입력 필드에서 현재 어떤 입력 필드인지, 각 입력의 요구사항이 무엇인지 명확히 설명하고 있지 않다

아이디, 비밀번호 Input에 포커스 시, 요구사항에 대한 설명을 하지 않고 있다. 또한 비밀번호 입력 필드에 있는 비밀번호 보기 버튼(눈 아이콘)에 대해서도 안내하고 있지 않다.

→ 기존에는 placeholder가 없었다. 따라서 placeholder를 추가하고, 해당 placeholder에 아이디, 비밀번호 입력 필드 안내 및 요구사항을 추가하였다. 그리고 placeholder 스타일을 투명하게 주어 육안으로는 보이지 않되 보이스 오버가 인식할 수 있게 해주었다.

button 태그를 추가하고 해당 버튼에 aria-label 달아 비밀번호 보기 버튼이라고 보이스 오버가 읽도록 하였다.

placeholder='아이디 입력. 1자에서 255자의 올바른 문자를 입력해주세요’

placeholder='비밀번호 입력. 영문자, 숫자를 포함한 8자에서 16자의 비밀번호를 입력해주세요.'

  • 실제 개선 과정과 결과

before

-.mov

after <1차 개선 - placeholder 추가하여 입력 필드가 어디인지 읽어주기, 비밀번호 버튼 읽어주기>

default.mov

<2차 개선 - 각 입력 필드의 요구사항 읽어주기>

-.mov

- 태그 등록 알림 기능 누락 → ScreenReaderOnly 요소 활용

기존에는 사용자가 태그를 등록하더라도 스크린리더가 이를 인식하지 못해 사용자가 등록 여부를 알 수 없는 문제가 있었습니다. 이는 특히 시각장애 사용자들에게 큰 불편을 초래할 수 있는 문제였는데요. 예를 들어, 사용자가 여러 태그를 추가하는 상황에서 현재 등록된 태그 목록을 파악하기 어려워 의도하지 않은 중복 태그를 추가할 가능성도 있었습니다.

→ 태그 등록 시 스크린리더가 "태그가 등록되었다"는 알림을 제공하도록 기능을 추가하였습니다. 이를 통해 사용자는 태그 등록 여부를 실시간으로 파악할 수 있게 되었습니다.

예를 들어, 템플릿의 태그가 생성되었을 때 해당 태그가 생성되었음을 알려야했습니다. 이를 화면에는 보이진 않지만 스크린 리더가 읽어주는 요소를 만들도록 하였습니다.

// TagInput.tsx

 const { updateScreenReaderMessage } = useScreenReader();
 
 // ...
 updateScreenReaderMessage(`${value} 태그 등록`);
// index.tsx
<HeaderProvider>
		<GlobalStyles />
		<RouterProvider router={router} />
		<ScreenReaderOnly />
</HeaderProvider>

// ScreenReacerOnly.tsx
const ScreenReaderOnly = () => (
  <div
    id='screen-reader'
    aria-live='polite'
    aria-hidden='true'
    style={{
      position: 'absolute',
      width: '1px',
      height: '1px',
      margin: '-1px',
      padding: '0',
      border: '0',
      overflow: 'hidden',
      clip: 'rect(0, 0, 0, 0)',
      whiteSpace: 'nowrap',
      wordWrap: 'normal',
    }}
  />
);

export default ScreenReaderOnly;
// useScreenReader.ts

import { useCallback } from 'react';

export const useScreenReader = () => {
  const updateScreenReaderMessage = useCallback((message: string) => {
    const element = document.getElementById('screen-reader');

    if (element) {
      element.setAttribute('aria-hidden', 'false');
      element.textContent = message;

      setTimeout(() => {
        element.setAttribute('aria-hidden', 'true');
        element.textContent = '';
      });
    }
  }, []);

  return { updateScreenReaderMessage };
};
  • 실제 개선 과정과 결과

before

-.mov

after

-.mov

- 카테고리 작성 팁의 불필요한 읽기

템플릿 작성 시, 필요하지 않은 상황에서도 스크린리더가 카테고리 작성 팁을 읽는 문제가 있었습니다. 이로 인해 사용자는 불필요한 정보를 듣게 되어 혼란을 겪었으며, 작업 흐름이 끊기는 경험을 하였습니다.

→ 스크린리더가 작성 팁이 화면에 표시될 때만 이를 읽도록 개선하였습니다. 이를 통해 불필요한 정보 전달을 줄이고, 사용자가 작업에 집중할 수 있도록 했습니다.

  • 실제 개선 과정과 결과

before

-.mov

after

-.mov

- 상세페이지에서 소스코드 접기 버튼을 이미지 라고 읽음

→ isSourceCodeOpen 여부에 따라 aria-label 읽도록 설정해주었습니다. 소스코드 접기 또는 소스코드 펼치기로 읽습니다.

  • 실제 개선 결과

after

default.mov

⚡️ 코드zap

프로젝트

규칙 및 정책

공통

백엔드

프론트엔드

매뉴얼

백엔드

기술 문서

백엔드

프론트엔드

회의록


Clone this wiki locally