웹 접근성과 사용자 경험을 고려한 프론트엔드 테스트 코드 작성하기

오형근·2023년 3월 28일
0

Testing

목록 보기
4/5
post-thumbnail

FE 테스팅의 관점과 목표

최근 개인 디자인 시스템 개발 및 리팩토링을 위해 프론트엔드 테스트를 공부하고 관련 아티클들을 여럿 읽어보면서 깨달은 것은 프론트엔드 테스팅의 관점이 확실히 다른 개발 분야와는 다르다는 것이다. 일반적인 테스팅이라고 하면 기본적으로는 비즈니스 로직을 담은 함수의 I/O를 검증하는 일(블랙박스 테스트)이나 세부 구조 및 동작을 검증하는 일(화이트박스 테스트) 등등이 있을텐데, 프론트엔드 테스트는 이러한 것들 보다는 기본적인 초점이 사용자에 맞춰져 있다는 것을 알 수 있었다. 즉 프론트엔드 테스트의 IN은 사용자가 발생시키는 이벤트고, OUT은 이에 따라 변경되는 UI라는 것이다.

사용자의, 사옹자에 의한, 사용자를 위한 FE 테스팅

그렇다면 사용자 중심의 프론트엔드 테스트 코드는 어떤 것을 의미하는 것일까. 웹을 공부하는 사람이라면 필수적인 정보들을 가지고 생각해보자.

  1. 웹 접근성: 웹 접근성은 의심의 여지 없이 프론트엔드 테스팅에서 필수적으로 고려해야 할 사항이다. 간단하게 말해서 '누구나' 웹 페이지를 접근하고 이용할 수 있도록 하기 위해 따지는 요소인데, 시각장애인을 위해 img 태그에 alt 속성을 붙이는 것도 웹 접근성을 고려한 사항이다. Apple에서 날이면 날마다 접근성을 중요시하는 것만 보아도 얼마나 필수적인지 알 수 있다.

  2. 사용자 경험: 웹 접근성을 고려하여 누구나 사용할 수 있는 웹 서비스를 구축했다면 다음은 더 좋은 사용자 경험을 제공하기 위한 웹 서비스를 구축할 차례이다. 이를 위해서는 시나리오 기반의 테스트 코드 작성이 필수적이고 BDD(Behaviour driven development)에 충실한 개발이 진행되어야 한다. 개발자의 관점이 아닌 사용자의 관점에서 코드를 작성하려 노력해야한다는 것이다.

어떻게 구현하면 되는데?

위에서 강조한 것들을 지키기 위한 구체적인 방법에는 무엇이 있을까.

이번 글에는 내가 사용하는 React-testing-library 내장 함수를 기반으로 작성하는 내용이 조금 포함되는데, 전반적인 FE 테스팅에 모두 적용되는 내용이라고 생각하므로 혹시라도 모른다고 해서 너무 걱정하지 않아도 좋을 것 같다.

React-testing-library(이하 RTL) 공식 문서에서 강조하는 원칙은 다음과 같다.

테스트 코드를 작성하고 테스트를 수행함에 있어서 테스트가 서비스의 사용 방식과 유사할수록 더 많은 신뢰를 얻을 수 있다

위에서도 언급했지만 테스트 진행이 서비스의 사용 방식에 최대한 근접해야 좋은 테스트라고 할 수 있다. 이를 위해 RTL에서는 웹 서비스가 사용되는 방식과 유사한 테스트를 작성하도록 하는 메서드와 기능들을 제공하려고 한다고 되어 있다.

이에 RTL 내부 기능들은 아래 세 원칙을 따른다.

  1. 테스트하는 동작이 컴포넌트 렌더링과 연관이 있다면, 테스팅은 컴포넌트 인스턴스 단에서 실행되는 것이 아닌 DOM node(렌더링되는 Element)와 연동하여 실행되어야한다.
    여기서 컴포넌트 인스턴스는 사실 함수형 컴포넌트에서는 존재하지 않지만, 맥락 상 JSX 내부에서 선언되는 리액트 컴포넌트로 이해하면 좋을 것 같다.

  2. 일반적으로 사용자가 컴포넌트를 사용하는 방식대로 테스트하기 유용해야한다. 가상의 DOM 환경에서 테스트를 진행하기 때문에 실제 서비스를 온전히 구현할 수는 없지만 최대한 사용자의 방식을 모방하고자 한다.

  3. 기능 구현과 제공되는 API는 간단하고 유연해야 한다.

위 원칙들에서 중요하게 생각해볼 점은 테스트를 진행할 때 최대한 HTML 태그들을 이용해야 하며, 상위 컴포넌트 엘리먼트들을 끌어와 테스트하는 것을 자제해야한다는 것이다. 이는 실제 브라우저에서는 리액트 컴포넌트가 렌더링 되는것이 아니라 HTML 태그들이 렌더링되는 것이므로, 이렇게 구현해야만 실제 서비스 환경과 유사하게 구성할 수 있기 때문일 것이다.

또한 위와 같은 방법으로 테스트 코드를 구현하는 것은 이번 글에서 중점적으로 말하고자 하는 웹 접근성을 위해서도 필수적이다.

웹 접근성 향상을 위해서 우리는 접근성 트리에 대해 정확히 알 필요가 있다

사용자가 특정 사이트를 접속할 때, 서버는 브라우저에 마리소스를 전송하고, 브라우저는 이를 기반으로 DOM, CSSOM등을 생성하여 렌더링 트리를 생성하는 과정을 거쳐 UI를 그려나간다.

그러나 브라우저는 이러한 DOM 트리 외에 접근성 트리를 만든다. 접근성 트리는 DOM 트리를 기반으로 하며, 접근성과 관련된 모든 메타 정보들(역할, 이름, 속성 등)을 포함한 트리를 만든다. 이는 해당 사이트가 보조 기술에 노출될 때 사용된다.

보조 기술

보조 기술(AT: Assistive Technology)은 사람들이 무언가에 접근하는 방법을 개선하기 위해 사용하는 모든 도구의 종류를 포괄하는 말인데, 컴퓨터와 웹에서는 다음의 기술들을 일컫는다.

  • 사용자 머리에 부착되는 마우스와 같은 포인팅 기기
  • 화면을 확대하는 확대기
  • 화면을 점자로 변환시키는 점자 정보 단말기
  • 화면을 사용자에게 읽어주는 스크린리더

이러한 보조 기술은 OS에 내장된 플랫폼 API 에 접근하는 것은 잘 해내지만, 사용자가 접속하는 웹 사이트에 대한 정보를 가져오는 것은 해내지 못한다. 이럴 때 접근성 트리가 활약하게 되는데, 접근성 트리는 보조 기술에게 웹 사이트의 구조를 알려준다.

접근성 향상을 위한 접근 가능한 이름

접근성 향상을 위해 할 수 있는 한 가지는 요소들에게 항상 접근 가능한 이름을 지어주는 것이다. 고유한 이름은 해당 요소 탐색에 유용하다.

이름은 접근성 트리가 그 요소에 대해 보조기술에게 알려주는 것 중 하나이다. 어떻게 하면 접근성 좋은 이름을 지을 수 있을까.

접근성 향상을 위한 이름 짓기

안타깝게도, 100만 개 이상의 사이트를 살펴보고 자동화 접근성 검사를 실행한 WebAIM 100만 프로젝트의 결과는 다음과 같았다.

페이지들의 24.4%는 ‘여기를 클릭’, ‘더보기’, ‘계속’ 등과 같은 모호한 링크 텍스트를 가진 링크를 가짐

각 알림 항목의 링크 텍스트로 ‘더 보기’를 반복 사용하는 것은 코드와 컨텐츠 관리를 단순화 시키지만, 스크린리더 사용자에게는 나쁜 사용성을 제공한다. 보조 기술 사용자가 링크를 이용하고자 링크 탐색을 사용할 경우, 각 링크가 사용자를 어디로 데려다줄지 전혀 알 수 없다. 사용자가 링크 읽기를 요청하면 보조 기술은 그저 ‘링크 더보기’ 라는 말을 반복할 뿐이다…

때문에, 고유하고 서술적인 이름이 필요하다. HTML의 태그들이 이름을 제공하는 방식을 살펴보자.

a

a 태그의 텍스트는 일반적으로 접근 가능한 이름이 된다.

만일 a 태그 내부에 이미지만 존재한다면, 이미지의 alt 텍스트가 그 대안으로 사용될 수 있다.

input with label

앞서 언급한 설문에서 WebAIM은 다음과 같이 설명했다.

💡 input의 59%는 레이블이 제공되지 않음

레이블 오류는 다음의 경우에 생긴다.

<div>Email</div> 
<input type="email" id="email">

위 예시에서 단어 “Email”이 input 요소 이전에 나타나고, 우리는 시각적으로 이 둘이 연관되어있음을 알 수 있지만,

보조 기술 사용자는 이를 연관되어있다고 인지하기 어렵다.

따라서 위 예시는 다음과 같이 수정되어야한다.

<label for="email">Email</label> 
<input type="email" id="email">

fieldset, legend

input들의 그룹, 예를 들어 동일한 질문의 답변인 라디오버튼이나 체크박스 모음을 설정하고자 할 때가 있다. 그럴 때는 HTML의 fieldset과 legend 태그를 적극 활용하도록 하자. 아래 예시를 보면 어떻게 사용되는지 알 수 있다.

<fieldset>
  <legend>Don't you love HTML?</legend>
  <input type="radio" name="yesno" id="yes"/>
  <label for="yes">Yes</label>
  <input type="radio" name="yesno" id="no"/>
  <label for="no">No</label>
</fieldset>

접근성 트리에서 위 fieldset을 검사하면, 보조 기술은 사용자에게 위 그룹이 “Don’t you lvoe HTML?”임을 알려줄 수 있다.

ARIA는 대안일 뿐이다

이쯤에서 보통의 개발자들이 궁금해하는 것은 aria-label 이나 aria-labelledby 속성의 사용이다. 물론 이 두 속성을 이용해서도 효과적으로 요소를 선택해낼 수 있겠지만, aria가 대부분의 브라우저를 지원하는 것이지 HTML만큼 모든 범위의 브라우저를 커버하지 못한다는 것이 단점이다. 또한 국제화와 같은 작업을 진행할 때, aria를 고려하는 것이 추가적인 업무로 다가오고 차순위로 넘어갈 가능성이 크다. 따라서 모든 서비스에서 언제나 지원되기 어렵다는 것이다.

aria도 접근성 향상을 위한 좋은 방법임에 틀림없다. 다만 HTML을 우선순위로 두도록 하자!

결국 중요한 것은 ‘어떤’ 마크업인지

최신 브라우저에서 마크업은 인터페이스가 보조 기기에 어떻게 보이는지에 궁극적으로 영향을 주는 접근성 트리가 된다. 이 마크업이 어떤 프레임워크/라이브러리에서 어떻게 생성되었는지 등은 중요하지 않다. 결과적으로 어떤 마크업이 사용되고 있는지가 가장 중요하다.

구체적인 방법

기본 원칙에 기반한 메서드 우선 순위

아래는 RTL에서 권장하는 메서드 우선 순위이다. React 에서 요소들을 가져오고 싶을 때 가장 권장되는 메서드들을 최대한 사용하도록 노력해야한다. 각 메서드들의 장단점과 사용하기 좋은 시점을 중점으로 알아두자.

  1. 보조 기술(포인팅 기기, 화면 확대기 등) 사용자들의 경험을 반영한 접근성 높은 메서드

    → 우리는 요소를 선택할 때 여기 기재된 메서드들이 사용 가능한지 최우선적으로 고려해야한다.

    getByRole: 요 메서드는 접근성 트리에 노출된 모든 요소를 조회하는 데 사용 가능하다. 이를 사용하면 접근 가능한 이름이 name으로 표시되는 요소들을 골라낼 수 있다. 가장 접근성과 사용자 경험을 고려하는 메서드!!

    getByLabelText: 이 메서드는 form 필드에서 유용하다. form 필드 내부 요소들을 각자의 label을 지니고 있고 사용자가 이 label을 토대로 요소를 찾기 때문에, 사용자의 행동을 그대로 반영할 수 있다.

    getByPlaceholderText: placeholder는 label의 대체자가 될 수는 없지만 label이 존재하지 않을 때 그 대안책으로 사용되기에는 충분하다!!

    getByText: 텍스트는 form 외부에서 사용자가 요소를 찾는 가장 쉽고 자주 사용되는 방법이다. 이는 div, span, paragraphs 와 같은 정적 요소들을 선택할 때 사용하기 좋다.

    getByDisplayValue: form 내부에서 이미 값이 입력되어있는 요소를 선택할 때 사용하기 좋다.

  2. ARIA 관련 props를 이용하는 메서드

    →위의 메서드들보다는 접근성이 떨어지고, 사용하는 브라우저나 보조 기술에 따라 사용자 경험이 달라질 수 있기 때문에 2순위로 사용된다.

    getByAltText: 요소 내에 alt 속성을 조회하여 가져오는 메서드. alt 텍스트가 존재하는 img, area, input등을 가져올 때 사용하기 좋다.

    getByTitle: Title 속성은 스크린리더가 일관되게 일지 않고, 시각장애인이 아닌 경우 표시되지 않으므로 크게 권장되지는 않는다.

  1. Test-id

    → 위의 방법이 모두 불가한 경우 최후의 수단으로 사용된다.

    getByTestId: 사용자가 보거나 들을 수 없어서 Role이나 Text로 일치시킬 수 없거나 의미가 없는 경우(Text가 동적인 경우)에만 권장된다.

그래서 결론이 뭐야

글을 총 정리해서 우리가 좋은 테스트 코드를 작성하는 방법을 나열해보면 다음과 같다.

  1. 컴포넌트나 마크업 코드를 작성할 때 웹 접근성이나 해당 요소의 역할을 고려하여 작성하기(시맨틱 태그 활용, alt, label 설정 등). 사실 가장 중요한 부분이 되는 것 같다. 여러 상황과 주어진 환경을 고려해서, 예상되는 사용자들을 미리 파악해서 이러한 부분들을 충분히 반영한 마크업을 작성하는 것이 좋을 것 같다.

  2. 1번에서 활용한 태그나 속성들을 적극 활용하여 어떤 메서드로 요소를 가져올지 생각하기. 테스팅 라이브러리에서 제공되는 메서드들의 가이드를 토대로 적재적소에 메서드를 활용해주어야 한다.

  3. 사용자가 서비스를 이용하는 관점에서 바라본 정교한 행동 기반 시나리오 작성하기.

  4. 생각한 메서드로 요소를 불러온 후, 시나리오에 따른 이벤트 발생 및 변화 확인하기. 위의 내용들에 충실한 테스트 코드를 작성했다면, QA 에서 좋은 결과를 얻을 수 있지 않을까?


시나리오 기반 프론트엔드 테스팅은 앞에 Storybook Interactions 관련 글에서 한 번 다뤘기 때문에 이번에는 웹 접근성에 대한 내용을 중점적으로 다뤄보았다. 사실 이 글은 테스트 코드를 작성할 때 어떤 메서드를 이용해서 요소를 가져오면 좋을까...라는 궁금점에서 출발해 어쩌다보니 웹 접근성까지 다루게 된 케이스인데, 다행히 그 궁금점은 잘 해결된 것 같아서 좋다.

최대한 공식 문서를 찾아보고 잘못되지 않은 정보들만 가져오려고 노력했지만,,,혹시라도 이상하거나 틀린 부분이 있다면 언제든지 피드백 부탁드립니다!

Reference

React-testing-library 사용 시 주의점
React-testing-library 공식문서
MDN | Accessibility tree
접근성 향상을 위한 이름 짓기

0개의 댓글