Gravity UI 디자인 시스템으로 Yandex Cloud를 더 접근하기 쉽게 만든 방법

안녕하세요, 저는 보바 티모페예프이고 Yandex Cloud의 기술 프로젝트 매니저입니다. 이 글에서는 우리가 클라우드 플랫폼 사이트를 더 접근 가능하게 만든 과정, 몇 번의 반복(이터레이션)을 거쳤는지, 그리고 그 과정에서 Gravity UI가 어떤 역할을 했는지 공유하겠습니다.

모든 서비스 접근성의 핵심은 화면낭독기(Screen reader) 프로그램을 얼마나 잘 지원하느냐입니다. 이러한 프로그램을 통해 제한이 있는 사용자는 인터페이스를 인지하고 상호작용합니다.

웹사이트도 예외가 아닙니다. 그래서 우리에게는 Yandex Cloud가 모든 사용자에게 얼마나 접근 가능한지 확인해야 하는 과제가 있었습니다.

Yandex에서 ‘접근성’은 일시적 또는 영구적인 신체적 제약과 상관없이 누구나 우리 서비스를 편안하게 사용할 수 있어야 한다는 의미입니다. 예를 들어 현재 시각장애 사용자를 위해 Yandex의 16개 서비스(예: Lavka, Go, 검색, 브라우저, 메일 등)가 адаптация (접근성 지원)되어 있습니다. 각 서비스의 접근성 작업에는 비시각 테스트 팀이 도움을 주는데, 이 글에서 다룰 사례도 그들의 도움 없이는 불가능했습니다.

스포일러: 테스트 결과 화면낭독기 사용 시 몇 가지 논쟁적인(모호하거나 불편한) 지점이 발견되었고, 이는 실제 작업 과제로 이어졌습니다.

그럼 순서대로 이야기해 보겠습니다.

모든 것은 Gravity UI에서 시작됐다

Gravity UI는 Yandex Cloud 웹사이트와 클라우드의 수십 개 다른 제품에서 사용하는 디자인 시스템이자 컴포넌트 라이브러리입니다. 오픈 소스로 공개되어 누구나 사용할 수 있습니다(최근 6개월 동안 커뮤니티 채팅방의 활동이 눈에 띄게 늘어난 것도 매우 반갑습니다).

우리가 제공하는 것:

  • 기본 React 컴포넌트 세트;
  • 랜딩 페이지용 빌더(생성기) 라이브러리;
  • 디자이너가 작성한 컴포넌트 사용 상세 가이드;
  • Figma 라이브러리;
  • 거의 600개에 달하는 готовые (준비된) 아이콘 세트;
  • ChartKit — 데이터 시각화 패키지;
  • Yagr — uPlot 기반의 고성능 차트 렌더링;
  • i18n — UI 로컬라이제이션 패키지;
  • 그 밖의 유용한 라이브러리.

2024년 3월, 핵심 라이브러리 업데이트인 UIKit 6버전이 릴리스되었습니다. 이 버전에서는 List 컴포넌트가 обновление (업데이트)되었고, 모든 컴포넌트에서 RTL 파라미터 지원이 추가되었으며, 접근성을 향상하는 a11y 개선 패키지도 포함되었습니다.

UIKit 6버전의 변경 사항
  1. List 2.0 컴포넌트. UIKit에는 원래 List가 있었지만, 몇 가지를 보완하고 싶었습니다. 요구사항을 모으면서 다음 목록이 정리되었습니다:

    • 다양한 크기 및 너비 지원;
    • 리스트 항목에 아이콘 지원(아이콘 개수/위치 다양화);
    • 상태(state) 지원;
    • 리스트 항목의 다양한 콘텐츠(한 줄, 여러 줄, 사용자 목록 등) 지원;
    • 다양한 구분선(separator)과 그룹핑 지원.

    변경 규모가 커서 List 2.0을 새로 만들었습니다. 현재 prestable 버전으로 제공되지만, 사용자에게는 해당 버전으로 전환하고 피드백을 주시길 권장합니다.

  2. RTL. 앱이나 사이트가 히브리어, 아랍어 등 오른쪽에서 왼쪽으로 쓰는 언어로 표시돼야 한다면 RTL 표준 지원이 필요합니다. 또한 RTL에서는:

    • 라틴 문자를 삽입한 단어는 왼쪽에서 오른쪽으로 씁니다;
    • 숫자도 왼쪽에서 오른쪽으로 씁니다;
    • 아랍어의 문장부호도 왼쪽에서 오른쪽으로 쓰는 등…

    우리는 모든 컴포넌트에서 RTL 파라미터를 지원했습니다. 전체 예시를 손쉽게 볼 수 있도록 아랍어 프로모 페이지도 만들었습니다. 구현 방식은 landing의 소스 코드에서 확인할 수 있습니다. storybook에도 예시가 있습니다.

  3. 접근성(a11y):

    • 프로젝트에 eslint 플러그인을 추가했습니다;
    • Persona 컴포넌트의 clickable/closable 상태에서 키보드 지원을 추가했습니다;
    • 비인터랙티브 컴포넌트 15개에서 onClick을 비활성화했습니다;
    • SelectionTable 컴포넌트에 키보드 지원을 추가했습니다.

a11y 개선으로 이어진 과정

이 과정에서 비시각 테스트 팀과 팀 리더 아나톨리 포프코의 도움이 컸습니다. 미팅에서 아나톨리는 샌드박스와 Gravity UI 사이트를 단계별로 테스트하며, 현재 어떤 접근성 문제가 있는지 파악했습니다.

키보드와 화면낭독기의 특수 명령을 사용해 사이트를 이동하면서 컴포넌트 접근성을 확인했습니다.

시각적으로는 이렇게 보였습니다:

Full screen image

미팅 이후 팀에는 작업 과제가 생겼고, GitHub에는 базовые (기본) 컴포넌트 관련 새 이슈 3개가 생성되었습니다.

자세한 내용:

  • 드롭다운 목록에서 두 번째 레벨 항목이 키보드로는
    열리지 않습니다.
    마우스 클릭으로만 가능합니다.
Full screen image
  • Select 컴포넌트에서 markdown 불릿 리스트 중 어떤 항목이 선택되었는지 알기 어렵습니다.

  • 텍스트 레이블이 없고 그래픽으로만 표시된 버튼들은 단순히 “버튼” 또는 “라디오 버튼”으로만 읽힙니다. 이 버그는 랜딩에서만 발생하며, 컴포넌트 자체는 aria-label을 지원하지만 우리는 이를 사용하지 않았습니다.

Full screen image

결과적으로, 수십 개의 지적사항을 찾지 못했다는 것은 라이브러리 접근성이 이미 꽤 좋은 수준이라는 뜻임을 알게 됐습니다. 컴포넌트를 실제 컨텍스트 없이 테스트하는 것은 매우 어렵기 때문에, 우리는 완성된 제품의 접근성 검증을 시작하기로 했습니다. 그 덕분에 추가 a11y 개선점을 더 찾을 수 있었습니다.

Yandex Cloud의 접근성

Gravity UI 업데이트에서 영감을 받아, 우리 서비스의 접근성 테스트를 진행하기로 했습니다. 먼저 Yandex Cloud 웹사이트부터 시작하고, 이후 이 경험을 다른 인터페이스로 확장하는 것이 목표였습니다.

접근성을 달성하기 위한 여러 표준이 존재합니다. 하지만 Yandex Cloud 인터페이스를 신뢰할 수 있게 테스트하고, 우리 사이트가 모두에게 얼마나 편리한지 더 잘 이해하기 위해 접근성 감사를 수행했습니다.

접근성 감사(Audit)

비시각 테스트 팀과 아나톨리에게 다시 도움을 요청해, 함께 사이트를 테스트하고 문제를 기록한 뒤 개선 작업으로 가져갔습니다. 총 2회 반복으로 진행했으며, 두 반복의 간격은 거의 한 달이었습니다(테스트와 리테스트).

테스트 과정에서 수정해야 할 전체 항목(풀)을 기록했습니다.

메인 페이지

  • 검색 컨트롤을 재설계할 필요가 있었습니다. 우리 UI에서는 검색 컴포넌트가 돋보기 아이콘이 있는 ‘검색 영역’ 형태로 구현되어 있고, 이를 클릭하면 입력 필드가 열립니다. 이전 구현에서는 화면낭독기 입장에서 서로 독립된 요소였기 때문에 시각장애 사용자가 혼란스러워했습니다.

    image

  • 언어 선택에서 ‘접힘(축소됨)’ 상태 속성을 사용했지만, 실제로는 드롭다운이 아니라 선택 버튼에 가까웠습니다. ‘언어’ 레이블이 없었고, ‘언어 — 지역’ 전환 문자열에는 공백이 부족했습니다.

  • 계정 메뉴에서 포커스가 갇히지 않았습니다. 활성화하면 사용자가 메뉴 항목 범위를 벗어날 수 있었습니다.

  • 메인 페이지에서 main 태그가 중복되어 하나를 제거해야 했습니다.

  • 예시 섹션: 버튼 대신 탭을 사용해야 했습니다.

Full screen image
  • 예시 카드에서 텍스트가 aria-describedby 안으로 들어가 있었고, 그 때문에 화면낭독기가 텍스트를 한 번만 읽었습니다. 중요한 정보를 살펴볼 때 불편합니다. 버그를 분석하는 과정에서 Card 컴포넌트에 대한 종합적인 리팩터링이 필요하다고 판단했고, 변경 상세와 논의 참여가 가능한 이슈를 생성했습니다.

내비게이션

  • 포커스 문제: 메뉴의 최상위 레벨을 펼칠 때 포커스를 서브메뉴로 이동해야 했습니다.
  • 메뉴 최상위 레벨의 TabIndex를 제거해야 했습니다. 기존 방식은 메뉴 항목 전체를 두 번 나열하게 만들었습니다.
  • 내비게이션이 펼쳐져 있을 때 키보드 포커스를 내비게이션 내부에 가둬야 했습니다. 그렇지 않으면 메뉴에서 페이지로 ‘빠져나가’ 이후 다시 메뉴로 돌아오지 못할 수 있습니다.
  • Yandex Cloud가 리스트로 감싸져 있었습니다. 푸터의 링크 목록 제목이 li 요소로 감싸져 있어 NVDA가 이를 목록의 일부로 인식했고, 동일한 목록을 사용자에게 두 번 읽어주었습니다.
  • AppStore, Google Play 링크에 대한 레이블이 부족했습니다. 테스트 당시 URL 일부가 읽혔기 때문에 사용자 입장에서는 의미를 파악하기 어려웠습니다.

‘블로그’ 섹션

  • ‘모든 주제’, ‘모든 서비스’ 버튼이 버튼과 제대로 연결(연관)되어 있지 않았습니다. 셀렉트 버튼이 자신의 내용을 읽어주지 못했습니다.
  • 리스트의 접근성 지원이 필요했습니다. 드롭다운을 열 때 화면낭독기의 포커스가 해당 리스트 항목으로 이동해야 합니다. 또한 어떤 키 조합 없이 일반 화살표 키만으로 항목 간 이동이 쉽게 동작해야 합니다.

블로그 글

  • 브레드크럼에 ‘여기 있습니다(You are here)’ 요소가 없었습니다.
  • 다이얼로그 내부에 포커스를 가둬야 했습니다.
  • 즐겨찾기 카운터에 이름이 없었습니다. 카운터는 아이콘과 숫자가 있는 버튼이었고, 화면낭독기는 숫자만 읽었습니다. 아이콘이 없으니 버튼이 무엇을 하는지 알 수 없었습니다.

모든 작업을 하나의 에픽(epic)으로 모으고 구현을 시작했습니다. 일부 작업은 GitHub에 이슈로 생성했습니다.

가장 흥미로운 케이스를 더 자세히 설명하겠습니다.

Select 컴포넌트

Full screen image

테스트 중 키보드 내비게이션 시 리스트 항목의 이름이 화면낭독기에 의해 안내(announce)되지 않는 문제를 발견했습니다. aria-activedescendant 속성으로 일부는 고칠 수 있었지만, 완전히 해결되지는 않았습니다.

남아 있는 문제

  • Safari에서는 이 방식이 동작하지 않으며, 아직 이를 해결할 방법이 명확하지 않습니다.

  • 검색 필터가 항상 지원되지 않습니다(정확히 말하면 지원되지 않습니다. 구현이 되어 있지 않습니다). 보통 aria-activedescendant는 드롭다운의 메인 요소에 붙고, 리스트에서 선택된 요소를 가리킵니다. 현재는 드롭다운을 여는 버튼에 붙어 있습니다. 위/아래 화살표를 누르면 버튼의 aria-activedescendant 값을 이전/다음 리스트 항목으로 바꿉니다. 그러면 화면낭독기는 버튼에서 현재 선택된 항목이 무엇인지 읽을 수 있습니다.

    검색 필터의 문제는 입력 필드에 aria-activedescendant가 없다는 점입니다. 사용자가 필터 입력 필드에 포커스를 두고 타이핑하려고 할 때, 화면낭독기는 그 입력 필드에서 어떤 리스트 항목이 활성(active)인지 읽을 수 없어서 화살표로 리스트를 탐색하는 동작이 깨집니다.

  • 선택된 옵션이 표시되지 않습니다. aria-selected 같은 속성을 추가해야 합니다.

현재 문제를 정리한 이슈는 여기에서 볼 수 있습니다.

Full screen image

브레드크럼은 사용자가 사이트에서 이동한 경로를 보여주는 내비게이션 요소입니다. 우리 경우 화면낭독기가 전체 경로를 읽었고, 사용자가 사이트의 어느 부분에 있는지 파악하기가 어려웠습니다. 또한 컴포넌트 전체가 단순히 링크들의 집합처럼만 인식되었습니다.

우리는 표준에서 한 걸음 벗어나, 단순하면서도 최적의 방법으로 문제를 해결하기로 했습니다. 즉, 화면낭독기를 위해 “여기 있습니다” 라벨을 추가했습니다. 최종적으로는 표준적인 접근과 라벨을 결합했습니다.

작업 과정에서 알게 된 점: 이 라벨이 읽히려면, 화면낭독기가 무시하지 않는 요소에 라벨을 달아야 합니다. 라벨을 피하는 구조를 새로 придумать (고안)하기보다는, 관례적인 구조에 라벨을 다는 편이 더 쉬웠습니다. 그래도 라벨은 여전히 유용합니다. 사용자가 지금 듣는 것이 브레드크럼임을 더 빠르게 이해하는 데 도움을 줍니다.

설명이 없는 이미지

사이트의 일부 이미지는 설명 없이 배치되어 있었고, 화면낭독기는 이를 “이미지”로 읽었습니다. 이는 사용자에게 유용한 정보가 아니고 인터페이스를 이해하는 데 도움도 되지 않기 때문에, 설명이 없는 이미지는 화면낭독기에서 숨기기로 했습니다.

블록 내 텍스트 읽기 순서

Full screen image

우리 사이트의 여러 위치에서 정보가 하나의 블록으로 표시됩니다. 예를 들어 이벤트 카드나 블로그 글 카드 같은 것입니다.

우리는 화면낭독기가 시각 사용자와는 다른 순서로 정보를 읽는다는 것을 발견했습니다. 이벤트 카드의 경우 화면낭독기는 등록 상태, 시간, 장소를 먼저 읽고, 그 다음에야 제목과 설명을 읽었습니다.

일반적으로 사용자는 선형적으로 따라가지 않습니다. 제목을 보고, 다음으로 부제와 이미지 등을 봅니다. 문제는 화면낭독기가 페이지의 DOM 트리에 배치된 순서대로 요소를 읽는다는 점입니다. 순서를 바로잡기 위해 DOM 구성을 재조립해야 했습니다.

Full screen image

놀랍게도 일부 “운영체제 — 브라우저” 조합에서는 이 방법이 통하지 않았습니다. 예를 들어 macOS의 Mozilla Firefox에서는 페이지 트리에서 순서를 바꿨는데도 문제가 남아 있었습니다. Firefox 개발팀이 향후 버전에서 이 동작을 고쳐주길 기대합니다.

모달 창

Full screen image

시각 사용자가 интерфейс (인터페이스)에서 팝업 창을 열면, 시선은 그 창 안의 내용에 집중됩니다. 하지만 사이트 전체 콘텐츠도 여전히 доступен (접근 가능)하며, 필요하면 다시 돌아가 볼 수 있습니다.

반면 화면낭독기로 사이트를 사용할 때는 상황이 달라집니다. 팝업이 모달로 만들어져 경계가 설정되지 않으면, 내비게이션이 더 어려워집니다. 요소 탐색을 사용하다가 실수로 팝업 밖으로 나가버릴 수 있습니다.

모달 창에는 표준이 있으며, 그 표준을 따르면 모든 팝업을 반드시 모달로 “잠글” 필요는 없습니다.

하지만 테스트 과정에서 우리는 팝업을 모달로 만드는 것이 화면낭독기 사용 시 사이트 이용을 단순화하는 좋은 практик (관행)이라고 결론 내렸습니다.

그래서 모든 팝업을 모달로 만들기로 했습니다. 동시에 사용자가 이러한 창을 다르게 동작시키는 альтернативный (대체) 시나리오를 설정할 수 있는 옵션도 남겨두었습니다.

이 시나리오는 role="dialog", aria-modal="true"를 지정해 설정할 수 있습니다. VoiceOver + Firefox 조합에서는 이 해결책이 지원되지 않습니다. 자세한 내용은 закрытом (닫힌) 이슈에 있습니다.

Diplodoc

우리의 활동에 자극받아, 기술 문서 제작 플랫폼 Diplodoc 개발팀도 제품에 a11y 개선을 여러 가지 적용했습니다:

  • YFM (Yandex Flavored Markdown)의 모든 추가 문법 요소를 점검하고, 화면낭독기에서 인지될 수 있도록 다시 작성했습니다.
  • 키보드로 문서를 사용하는 흐름을 개선했습니다: 요소 선택 순서를 수정하고, 모든 인터랙티브 요소에 선택 가능 동작을 추가했습니다.
  • UI 요소에 올바른 레이블과 표기를 추가해, 화면낭독기 사용자가 서비스를 훨씬 쉽게 이용할 수 있게 했습니다.

우리는 문서 표시를 위해 Diplodoc을 사용하고 있으므로, 이 개선은 Yandex Cloud 사이트의 문서 접근성도 함께 높였습니다.

결과와 계획

우리는 모든 사용자를 위해 Yandex Cloud 인터페이스의 접근성을 개선하는 첫 단계를 밟았습니다. 앞으로 이 경험을 서비스의 다른 인터페이스로 확장하고, 현재 알고 있는 문제들을 계속 해결해야 합니다.

Gravity UI는 접근성 작업을 더 수월하게 해주었고, 우리는 a11y 태그가 달린 열려 있는 이슈들을 계속 처리하고 있습니다. 이 글을 작성하는 시점에 열린 이슈 14개, 닫힌 이슈 24개가 있으며, 여기에서 확인할 수 있습니다.

Full screen image

접근성 및 서비스 동작에 대한 PR과 의견, 그리고 여러분의 사이트에서 Gravity UI를 사용한 사례도 기다리겠습니다.

image

블라디미르 티모페예프
Yandex Cloud 기술 프로젝트 매니저

Gravity UI 디자인 시스템으로 Yandex Cloud를 더 접근하기 쉽게 만든 방법

Sign in to save this post