[번역] 모든 프런트엔드 개발자가 알아야 할 접근성 필수 사항

eunbinn·5일 전
80

FrontEnd 번역

목록 보기
40/40
post-thumbnail

출처: https://martijnhols.nl/blog/accessibility-essentials-every-front-end-developer-should-know

많은 개발자들은 접근성을 대단히 어려운 작업으로 보고, 많은 추가적인 노력이나 전문 지식을 필요로 한다고 생각합니다. 그러나 몇 가지 기본적인 것만 적용해도 큰 영향을 미칠 수 있습니다.

이 글에서는 모든 프런트엔드 개발자가 컴포넌트를 개발할 때 적용해야 한다고 생각하는 주요 접근성 원칙에 대해 설명하겠습니다.

  • 시맨틱 HTML: 상호작용 및 기본 기능에 알맞은 요소를 사용하세요.
  • : 모든 사용자의 사용성을 높이기 위해 라벨과 구조를 간단하게 만드세요.
  • 키보드 내비게이션: 사용자가 키보드를 사용하여 쉽게 탐색할 수 있도록 하세요.
  • 모달: 모달에는 많은 접근성 요구 사항이 있습니다.
  • 이미지 대체 텍스트: 더 나은 설명으로 이미지 접근성을 높이세요.
  • 스타일링: 포커스 표시기, 반응형 디자인, 애니메이션 최소화를 통해 접근성을 향상시키세요.
  • ARIA 속성: 접근성의 격차를 메우기 위해 언제, 어떻게 ARIA를 사용할지 확인해보세요.

이러한 실천은 보조 기술에 의존하는 사용자에게 도움이 될 뿐만 아니라 전반적인 사용자 경험(UX)도 개선합니다.

이 문서에서는 프런트엔드 개발자가 많은 시간과 노력을 들이지 않고도 접근성과 사용성을 개선하기 위해 할 수 있는 기본적인 작업에 중점을 둡니다.

참고: 이 글의 예시 대부분은 리액트를 사용하지만, 원칙은 모든 프런트엔드 앱에 적용됩니다. 리액트를 사용하는 개발자가 아니더라도 여기에 설명된 사례를 통해 많은 것을 배워갈 수 있습니다.

시맨틱 HTML

접근성은 시맨틱 HTML에서 시작됩니다. 올바른 HTML5 요소를 의도된 용도로 사용해야 합니다. 이렇게 하면 브라우저와 도구가 페이지의 구조를 이해하여 기본으로 제공하는 접근성에 대한 이점을 얻을 수 있습니다. 시맨틱 HTML은 SEO도 향상시킨다는 점도 추가적인 장점입니다.

인터랙티브 요소들

가장 중요한 요소는 <button><a>입니다. 이 요소들은 기본적으로 접근성 기능을 내장하고 있어, 키보드 지원(운영 체제에 따라 동작이 다를 수 있음)과 스크린 리더에 시맨틱한 의미를 제공하는 기능을 포함하고 있습니다.

웹 애플리케이션에서 흔히 볼 수 있는 안티 패턴은 onClick 핸들러가 있는 <div>입니다. <div>onClick 핸들러를 사용하여 인터랙티브 요소로 만드는 것은 절대 하지 마십시오. 이러한 요소들은 접근성 기능이 부족하여 사용자가 해당 요소와 상호작용하는 방법에 제한을 주고 스크린 리더에게는 인식되지 않습니다. 인터랙티브 요소로서 <button><a>를 제대로 사용하면 모든 사용자에게 이점이 있습니다.

  • 링크는 사용자가 다양한 작업을 수행할 수 있는 컨텍스트 메뉴를 우클릭으로 열거나, Windows에서는 Ctrl+클릭으로, Mac에서는 Cmd+클릭으로, 또는 중간 마우스 버튼으로 새 탭에서 열 수 있도록 합니다.
  • 버튼은 사용자가 키보드를 통해 사이트를 탐색할 수 있게 해줍니다. 이는 숙련된 사용자들에게 작업을 더 빠르게 할 수 있도록 도와주며, 보조 기술을 사용하는 사람들에게는 필수적입니다.

만약 맞춤형 스타일링이 필요하다면, 접근성을 희생하지 않고도 <button>이나 <a>를 완전히 다시 스타일링할 수 있습니다. 버튼과 링크의 스타일링에 관한 더 많은 내용은 추후에 다룹니다.

네이티브 요소

버튼과 링크 외에도 <select>, <input>, <textarea>와 같은 네이티브 요소들은 기본적으로 접근성을 갖추고 있습니다. 예를 들어, <select> 드롭다운은 스크린 리더와 키보드 탐색에 원활하게 작동하여 추가 작업 없이 일관된 사용자 경험을 제공합니다.

미적이거나 기능적인 이유로 맞춤형 컴포넌트를 만드는 것이 유혹적일 수 있지만, 네이티브 요소의 대체물을 접근 가능하게 만드는 것은 매우 어렵고 시간이 많이 걸립니다. 비록 작은 문제를 위해 라이브러리를 설치하는 것을 좋아하지 않는 편이긴 하지만(지난 종속성에 관한 글에서 언급한 바와 같이), 이 경우에는 접근성이 이미 보장된 react-select와 같은 널리 사용되고 성숙한 라이브러리에 의존하는 것이 더 좋습니다.

제가 참여한 프로젝트에서 반복적으로 발견한 문제 중 하나는, <form> 내에 포함되지 않은 폼 필드입니다.

모든 폼 필드는 onSubmit 핸들러와 제출 버튼이 있는 <form> 내에 포함되어야 합니다. 이렇게 하면 브라우저와 스크린 리더가 관련 필드를 식별할 수 있게 해주며, 접근성과 사용성 면에서도 이점을 제공합니다. 예를 들어, 사용자가 Enter 키로 제출할 수 있게 하거나, 모바일에서는 스크린 위의 키보드를 닫지 않고도 필드 간 이동이 가능하게 합니다.

폼 안의 폼 필드는 필드 간 이동과 화면 키보드가 떠 있는 채로 제출할 수 있게 합니다.

라벨

모든 입력 필드에는 용도를 설명하는 명확한 라벨이 있어야 합니다. 라벨은 for 속성 (React에서는 htmlFor)을 사용하여 입력 필드의 id와 연결해야 합니다.

<label for="email">이메일:</label> <input type="email" id="email" />

라벨과 입력 필드를 for 속성을 생략하고 <label> 요소에 함께 감싸는 형태로 암시적으로 연결하는 것도 유효한 HTML이지만, 모든 스크린 리더가 이를 제대로 지원하지는 않습니다. 모든 보조 기술에서 원활히 지원되도록 하기 위해서 항상 for 속성을 사용하는 것이 좋습니다.

참고: 리액트에서는, 컴포넌트가 쉽게 재사용되고 동일한 페이지에 여러 번 렌더링될 수 있기 때문에 하드코딩된 ID를 사용하는 것을 선호하지 않습니다. ID 충돌을 피하기 위해서, 리액트의 useId 훅을 사용하여 각 필드에 고유한 ID를 생성할 수 있습니다. 폼에서 여러 관련 요소에 대한 ID를 생성하는 방법에 대한 예시는 여러 관련 요소에 대한 ID 생성 방법을 참조하세요.

플레이스홀더

플레이스홀더는 라벨의 대체물이 아닙니다. 사용자들이 입력을 시작하면 사라지기 때문에 필드의 용도가 무엇인지 혼란을 줄 수 있습니다. 또한, 플레이스홀더는 대개 대비가 낮아 읽기 어려울 때가 많습니다. 게다가, 플레이스홀더는 아래 이미지에서 보이는 것처럼 아직 채워지지 않은 필드를 식별하는 것을 더 어렵게 만들기도 합니다.

image
두 양식 중 어느 쪽도 작성되지 않았지만, 한쪽에서는 플레이스홀더 때문에 확인이 더 어렵습니다.

항상 적절한 <label>을 사용하고 플레이스홀더는 가급적 최소한으로 활용하는 것이 좋습니다.

키보드 내비게이션

키보드는 마우스로 탐색하는 것을 대체할 수 있는 중요한 도구입니다. 사용자가 Tab 키로 논리적으로 앱을 탐색하고 Enter 키를 사용해 동작을 실행할 수 있도록 보장해야합니다. <button><a>와 같은 네이티브 HTML 요소를 사용하는 것이 탐색을 원활하게 하는데 중요한 역할을 합니다.

포커스 표시기

포커스 표시기는 키보드 탐색에 필수적입니다. 포커스 표시기를 절대 완전히 비활성화하지 마세요. :focus 대신 :focus-visible 선택자를 사용하면 브라우저가 사용자가 필요로 할 때만 포커스 표시기를 표시할 수 있도록 합니다. 이는 접근성을 희생하지 않으면서 포커스 링이 시각적으로 보기 싫다는 불만에 대한 해결책이 됩니다.

포커스 표시기를 사용하여 폼 필드를 순차적으로 이동하기

참고: 위의 GIF에서는 "Soort" (타입) 필드에 대한 커스텀 필드가 있습니다. 이 필드는 라디오 버튼과 CSS를 사용하여 완전히 접근 가능하게 만들어졌습니다. 라디오 버튼은 시각적으로 숨겨져 있지만, 여전히 선택할 수 있으며 스크린 리더기에 의해 공지됩니다. 이는 가능한 한 시맨틱한 HTML을 사용하는 것의 강점을 보여줍니다.

모달

모달은 대규모 웹 애플리케이션에서 일반적이지만, 모달을 접근 가능하게 만드는 것은 어려울 수 있습니다. 중요한 고려 사항은 포커스 관리, 키보드 내비게이션, 비활성화된 콘텐츠가 숨겨지도록 보장하는 것입니다.

모달을 접근 가능하게 만드는 가장 쉬운 방법은 역시 시맨틱한 HTML의 강점을 활용하는 것입니다. <dialog> 요소를 사용하세요. 이 요소는 이제 대부분의 브라우저에서 잘 지원되며, 키보드 탐색을 포함한 모달의 접근성 문제를 대부분 해결합니다.

커스텀 모달

<dialog> 없이 커스텀 모달을 구축하는 경우, 고려해야 할 많은 접근성 요소가 있습니다. 모달을 제대로 만드는 것은 까다롭고, 처음부터 완전히 접근 가능한 모달을 만드는 것은 상당한 도전입니다. 모든 세부 사항을 다루려면 하나의 글이 필요한 정도이지만, 몇 가지 고려해야 할 주요 사항만 확인해 보겠습니다.

포커스 관리

모달이 열리면 사용자의 포커스는 모달을 연 버튼에 머무르게 되어, 사용자가 새로 열린 모달과 상호 작용하기 어렵게 만듭니다. 이로 인해 사용자가 실수로 동일한 모달을 여러개 여는 경우도 생길 수 있습니다.

이 문제를 해결하려면,

  1. 모달이 열리자마자 포커스를 모달로 설정해야 합니다.
  2. 포커스 트랩을 구현하여, 사용자가 Tab 키를 눌러도 모달 밖으로 나가지 않도록 포커스를 유지합니다.
  3. 모달이 닫히면 모달을 트리거한 요소로 포커스를 반환하세요.

react-focus-lock과 같은 라이브러리는 이에 대한 좋은 해결책을 제공합니다. 이 라이브러리는 초기 포커스를 처리하고, 모달 내의 활성 요소만 순환하도록 포커스를 가둬주며, 모달이 닫힐 때 트리거 요소로 포커스를 복원할 수 있는 returnFocus 옵션을 제공합니다.

참고: 확인용 대화 상자의 경우, 초기 포커스를 "확인" 버튼에 설정하는 것을 고려해보세요. 이렇게 하면 사용자가 Enter 키를 눌러 즉시 작업을 확인할 수 있습니다.

비활성 콘텐츠

모달이 열리면 그 뒤의 콘텐츠는 일반적으로 배경에 의해 시각적으로 차단됩니다. 그러나 스크린 리더를 사용하는 사용자들은 기본 콘텐츠와 여전히 상호 작용할 수 있습니다.

이 문제를 예방하려면, 모달 뒤의 콘텐츠에 inert 속성을 추가해야 합니다. 이는 콘텐츠를 비활성화하고 보조 기술에서 숨깁니다.

리액트에서 inert를 사용하려면, 모달을 메인 콘텐츠에서 포털 처리해야 합니다. 이는 모달이 inert 범위 외에 위치하도록 보장합니다. inert는 모든 자식에게 적용되며 자식 요소에서 비활성화할 수 없습니다.

모달 닫기

사용자는 Escape 키를 사용하여 모달을 닫을 수 있어야 합니다. 이는 사용자들이 기대하는 일반적인 패턴으로, 이동 장애가 있는 사용자들에게 도움을 주고 일관된 방법으로 모달을 닫을 수 있게 하여 전체 사용자 경험을 개선합니다.

이미지 대체 텍스트

대체 텍스트 예제를 보여주는 의도적으로 깨진 이미지

대체 텍스트는 이미지를 접근 가능하게 만드는 데 필수적이며, 추가적으로 검색 엔진이 여러분의 콘텐츠를 더 잘 이해하게 하여 SEO를 향상시키는 장점이 있습니다.

이미지에는 예외 없이 alt 속성을 추가해야 합니다. 순수하게 장식용이거나 텍스트에서 중복된 정보를 제공하는 이미지의 경우에만 빈 대체 텍스트(alt="")를 사용하세요. 이렇게 하면 스크린 리더가 이미지를 건너뜁니다.

대체 텍스트 작성

좋은 대체 텍스트를 작성하는 것은 어렵고, 인터넷에 있는 많은 가이드라인은 혼란을 줍니다. 수년간, 저는 효과적인 경험치로 얻어진 일종의 원칙을 개발하게 되었습니다.

시력이 좋지 않은 사람에게 이미지를 설명한다고 상상해 보세요. 그들은 이미지의 일부를 볼 수 있지만, 모든 것을 선명하게 알아차릴 수는 없습니다. 대체 텍스트는 그들이 보고 있는 것과 보지 못하는 것의 차이를 메워야 합니다.

이 접근 방식에서 중요한 요점은 이미지에 텍스트가 포함되어 있다면, 그 텍스트를 항상 대체 텍스트에 포함시켜야 한다는 것입니다. 이 접근 방식은 다른 지침보다 더 자주 이미지에 대체 텍스트를 추가하도록 이끈다고 생각합니다.

참고: 다양한 스크린 리더 사용자의 특성에 대해 더 알고 싶다면 Adrian Roselli의 모든 스크린 리더 사용자가 시각 장애인인 것은 아닙니다를 읽어보세요.

스타일링

스타일링(즉, 디자인)의 많은 측면은 접근성에 중요한 역할을 합니다.

  • 포커스 표시기: 포커스된 요소를 테두리로 강조합니다(앞서 다룬 내용).
  • 인터랙티브 요소: 링크는 링크처럼, 버튼은 버튼처럼 보이도록 하여 상호작용이 쉽게 합니다.
  • 인터랙티브 피드백: 명확한 호버, 활성 및 비활성 상태를 제공합니다.
  • 색상 대비: 요소를 구별하기 위해 충분한 대비를 사용하세요.
  • 색상: 색맹인 사용자를 위해 색상을 텍스트나 아이콘과 함께 사용하세요.
  • 반응형 디자인: 커스텀한 글꼴 크기 및 확대를 지원하세요.
  • 애니메이션 및 움직임: 움직임에 민감한 사용자를 위해 움직임을 줄이거나 비활성화하세요.
  • 글꼴 및 간격: 간격이 충분한 명확한 글꼴을 사용하세요, 특히 난독증 사용자에게는 더 중요합니다.

이 중 대부분은 디자인으로 이루어지며 우리의 직접적인 영향력 밖에 있습니다. 저희는 저희가 가장 직접적인 영향을 미칠 수 있는 영역에 집중하도록 하겠습니다.

클릭 가능한 영역

버튼과 링크가 마우스와 터치 사용자를 위해 크고 쉽게 클릭할 수 있는 영역을 가지도록 보장하세요. 이는 요소에 패딩을 추가하고, 필요한 경우 시각적으로 균등하게 보이도록 음수 마진을 사용함으로써 간단히 구현할 수 있습니다.

imgae
모달 닫기 버튼의 클릭 가능한 영역을 보여주는 좌우 비교.

애니메이션 최소화

애니메이션은 상태 간 전환 시 페이지에서 사용자가 방향을 유지하는 데 도움을 주어 사용성을 향상시킬 수 있습니다. 그러나 일부 사용자는 움직임 민감성을 가지고 있으며, OS 설정에서 움직임 축소를 선택했을 수 있습니다. 이 선호도를 존중하여 애니메이션과 전환을 비활성화하세요. 이는 간단한 미디어 쿼리를 사용하여 구현할 수 있습니다.

@media (prefers-reduced-motion: reduce) {
  .modal {
    animation: none;
  }
}

접근성 있는 반응형 디자인

잘 알려지지 않은 사실 중 하나는 브라우저가 사용자에게 웹 페이지의 기본 글꼴 크기를 사용자 정의할 수 있도록 허용한다는 것입니다.

접근 가능한 반응형 디자인은 사용자의 글꼴 크기 선호도와 사용자가 조절할 수 있는 확대 수준에 맞춰 레이아웃을 조정하는 것을 포함합니다. 웹페이지는 이러한 선호도를 존중하여 글꼴 크기, 여백, 텍스트 블록의 너비 및 기타 레이아웃 값을 설정할 때 'em'과 'rem'과 같은 상대 단위를 사용해야 합니다. 이러한 값을 픽셀로 하드코딩하는 것은 일반적으로 피해야 합니다.

이 블로그에 적용된 예시

이 블로그는 대부분의 곳에서 상대 크기를 사용합니다(늦게 추가되어 완벽하진 않습니다). 기본 글꼴 크기를 설정하지 않고, 브라우저에 구성된 설정을 사용합니다. 그 다음으로, 대부분의 다른 크기는 em 값을 사용하여 상대적으로 설정되고 필요한 경우 rem을 사용합니다.

비텍스트 요소에 em을 사용하는 것의 가치를 확실히 느낀 한 예시는 이 글의 너비입니다. 저는 코드 블록이 제가 사용하는 IDE의 80자 열 너비와 완벽하게 일치하도록 너비를 57em으로 설정했습니다(이는 이상적인 줄당 단어 수에 가깝습니다). 컨테이너가 글꼴 크기에 맞추어 조정되기 때문에, 사용자가 설정한 글꼴 크기와 상관없이 줄당 단어 수는 일관성을 유지합니다.

마진에 em을 사용하는 것도 많은 의미가 있습니다, 특히 텍스트 요소 주변에서 말입니다. 공백은 글꼴 크기와 함께 커지기 때문입니다.

ARIA 속성

접근성에 관한 글은 스크린 리더를 사용하는 사람들만이 아니라 모든 사용자에게 유익한 내용을 다루더라도 ARIA 속성을 언급하지 않고는 완성될 수 없습니다.

시맨틱 HTML이 좋은 출발점이 되지만, 시맨틱 요소가 원하는 결과를 가져오지 못할 때만 최후의 수단으로 ARIA 속성을 사용해야 합니다. ARIA를 잘못 사용하면 오히려 해로울 수 있으므로, 신중히 고려해 사용해야 합니다.

가장 중요한 두 가지 ARIA 속성은 다음과 같습니다.

aria-label

눈에 보이는 텍스트가 없는 요소에 접근 가능한 라벨을 추가합니다. 예를 들어, 아이콘만 있는 검색 버튼에는 다음과 같이 aria-label을 포함시켜야 합니다.

<button aria-label="검색">
  <SearchIcon />
</button>

aria-label은 모든 요소에서 사용할 수 있지만, 상호작용하는 요소에서만 사용해야 합니다. 비상호작용 요소에서는 지원되지 않으며, 그곳에 사용하면 라벨이 무시되거나 혼란스럽고 예상치 못하거나 성가신 알림을 초래할 수 있습니다.

aria-hidden

요소를 시각적으로 제거하지 않고 스크린 리더에서 숨깁니다. 이는 장식용이거나 중복된 요소에 적합합니다.

<div>React <ReactLogo aria-hidden /></div>

이 두 속성은 훌륭한 출발점이지만, 전체 스크린 리더 지원을 원할 경우 더 많은 ARIA 속성들이 필요합니다. 대표적인 속성으로 aria-live, aria-expanded, aria-describedby가 있지만, 제대로 구현하려면 상당히 복잡해집니다.

결론

이것들은 프런트엔드 개발자가 컴포넌트를 만들 때 사용해야 한다고 생각하는 도구와 원칙들입니다. 접근성은 나중에 해결할 별도의 작업이 아니라, 처음부터 개발 과정의 일부가 되어야 합니다.

보았듯이, 대부분의 접근성 개선은 특정한 필요를 가진 사용자에게만 혜택을 주는 것이 아니라, 모든 사용자를 위한 유용성 및 전체적인 사용자 경험(UX)을 향상시킵니다. 심지어 SEO 혜택도 있어서, 검색 엔진이 좋은 접근성 관행을 보여주는 사이트의 순위를 더 높일 수 있습니다.

이 글에 언급된 변경 사항은 기본적인 내용을 다루고 있으며 큰 도움이 되지만, 완전한 접근성을 위해서는 더 많은 노력이 필요합니다. 어느 시점에는 실제로 스크린 리더를 사용해 앱을 테스트하여 정말로 모든 사용자가 사용할 수 있는지 확인해야 할 것입니다.

이러한 기본적인 실천이 갖춰지면, 모든 사람을 위한 포괄적이고 사용자 친화적인 애플리케이션을 만드는 길로 잘 나아갈 수 있을 것입니다.

3개의 댓글

comment-user-thumbnail
4일 전

Thanks for sharing this interesting knowledge.

답글 달기
comment-user-thumbnail
3일 전

개발하다보면 놓치는게 많죠 ,, 좋은글이네요 ㅎㅎ

답글 달기
comment-user-thumbnail
2일 전

항상 좋은 글들 번역해주셔서 감사합니다. 🙇🏻

답글 달기

관련 채용 정보