너도, 나도, 동등하게 살아가는 웹 세상

쏘쏘임·2021년 10월 18일
3

So, 웹접근성

목록 보기
1/3
post-thumbnail

포스팅 시작 이유 : 웹 접근성을 잘 다루는 웹 개발자가 되고자 꾸준히 공부하기 위해 시작했다. 더 욕심을 내자면 이를 통해 다른 개발자들도 웹 접근성에 관심을 갖고 필요한 정보도 공유할 수 있으면 하는 바람이다.

1. 웹접근성이 중요한 이유

장애란 무엇일까

장애란 무엇일까? 수 년 전 대학교 특수교육학개론 OT에서 교수님께서 던지셨던 물음이다. 무심한 듯 질문을 던지시고는 안경을 쓴 학생들에게 안경을 벗고 칠판을 보라고 하셨다. 당시 심한 난시를 갖고 있으면서 가장 뒷자리에 앉아 있던 난 안경을 벗자 칠판의 글이 하나도 보이지 않았다. 너무나 일상적으로 가지고 있던 '교정시력'이 상실되자 매우 낯설고 난감했다. 내 시력으론 맨 앞자리에 앉아도 눈을 잔뜩 찌푸려야 겨우 알아볼 정도일 것이다. 안경이라는 보조 기기를 박탈 당한 순간, 나는 당연히 누려왔던 일상을 함께 박탈당하고 하나의 장애를 가지게 된 것이다. 기억나는 대로 교수님께서 하신 맥락을 정리해 보자면 아래와 같다.

장애를 가졌다고 할 때는 의도대로 원하는 바를 이행할 수 없는 경우를 말합니다. 이곳에서 공부하는 여러분들은 장애를 가졌다고 말하나요? 아니라면 왜일까요? 안경이라는 보조 기구를 이용해 학습을 하는데 무리가 없는 시야를 확보할 수 있기 때문입니다. 안경과 같은 보조 기구를 통해 장애를 없애거나 완화시킬 수 있고, 바꿔 말하면 보조 수단을 차단함으로써 '장애를 발생'시킨다고 할 수도 있습니다. 만약, 제가 '내 수업 시간엔 안경 착용을 금한다'라는 환경을 만드는 순간 절반가량의 학생들에게 장애를 주는 셈이죠.

장애 환경을 고려한다고 할 때 혜택을 주고 선의를 베푼다고 생각할 것이 아니라, 고려하지 않음으로써 장애를 '발생'시킨다는 측면으로 접근할 수 있다는 것이다.

웹에서 제공할 수 있는 보조 기기 중 대표적인 것으로 스크린 리더기(화면 낭독 프로그램)가 있다. 문제는 각각이 다양한 포맷을 가졌다는 것이다. 하지만 다양한 브라우저가 하나의 웹 사이트를 유사하게 해석해 내듯 이들이 공통적으로 적용시키는 웹 표준을 잘 지키면 문제의 상당 부분을 해결할 수 있다.

소수만을 위한 ? NO ! 소수는 물론 다수를 위한!

웹 표준 기구인 W3C에서는 Web Content Accessibility Guidelines (WCAG) 라는 웹 접근성 가이드라인을 제시하고 있다. 하지만 실상 이가 제대로 고려되지 않고 웹이 개발되는 경우가 많다. '그럼 지키면 되지!'라고 생각할 수 있다. 나 또한 그런 생각이었지만 직접 웹을 개발해 보니 만만한 것이 아니었다. 웹 개발이란 디자인, 마크업 개발, 프론트, 백엔드 등 다양한 분야의 사람들이 각자가 맡은 역할을 해내고 이를 하나의 웹에 합치는 큰 규모의 작업이다. 각 분야별로도 고민해야 하는 부분이 많다. 프론트엔드 개발자로서 프론트 엔드 한 분야만 말해보자면 웹 성능 최적화, 프레임워크별 제한, 코드의 가독성 및 유지보수 성, 안정적인 기능 구현 등 무수히 많은 부분을 고려해야 한다.

그렇게 복잡하다면 소수는 안타깝지만 배제하면 되는 것 아니야?라고 생각할 수도 있지만, 절대 그렇지 않다. 일단, 개인적인 가치관으로 '프론트엔드 개발자'에겐 웹 사용에 대한 장애를 최소화해야 한다는 책임이 명확히 있다고 생각한다. 다만 이윤을 추구해야 하는 기업의 입장에서 '소수'를 고려하기에 부담이 크기 때문에 고려하지 않겠다고 한다면, 그것 또한 기업 입장에서 합리적인 결정일 것이다.

다만 그 '소수'라는 것을 너무 좁은 범위로만 보는 것이 아닌가에 대해서는 좀 더 생각해 볼 필요가 있다고 생각한다. 비단, 웹 접근성이 소수만을 위한 것일까? 웹 접근성을 위한 기본인 웹 표준에 대해 생각해 보자. 마우스뿐만이 아니라 탭으로도 자유롭게 웹 사이트를 활보하고, 인풋창 등 UI 사용에 불편함 없이 매끄럽게 진행이 되며 증진된 SEO로 적절한 정보를 빨리 찾을 수 있는 것, 모두 일반 유저들에게도 똑같이 적용되는 편리함이다.

또한 스마트폰, 스마트 티비, 스마트 냉장고, 카카오AI, 클로바 등 다양한 인공지능 기기들이 등장하고 있는 상황에서 이 기기들이 적절한 정보를 해석해 내게 하려면 웹 표준을 준수하는 것을 넘어 모니터 화면과는 다른 사용자들의 접근성을 다각도로 고려할 필요가 있다.

시력의 저하와 세밀한 조작에 어려움이 있는 노년층에게도 웹 접근성은 중요한 부분이다. 노년층 인구가 급증과 이미 인터넷 사용이 일상이 된 대다수 사람들을 생각하면 기업 측에서도 이 사용자 그룹을 고려 해야 할 니즈가 클 것이다.

조금의 노력으로 크게 개선될 수 있다.

사실, '기본적인' 웹 접근성을 지키는 것은 생각보다 그리 어렵지 않을 수도 있다. 이미지에 대한 대체 텍스트(alt 속성)를 제대로 넣고, 시먼틱한 HTML 구조를 짜기 위해 용도에 맞는 태그를 사용하는 것만으로도 웹 접근성의 상당 부분을 보장할 수 있다. 결국, 본격적으로 웹 접근성을 고려하기 위해서는 프론트 엔드 개발자들의 끊임없는 관심과 공부, 노력이 필요하겠지만 작은 첫 발이 가진 힘이 매우 큰 것이 웹 접근성이라고 생각한다.

일차적으로는 신입 개발자로서 웹 접근성 관련 개발 능력을 키우고 공부하고자 이 포스트를 작성하였지만, 다른 프론트 엔드 개발자들이 이 글을 읽고 웹 접근성에 대해 조금이라도 관심을 가질 수 있지 않을까 하는 바람이 있다.

2. WCAG2.1 웹접근성 대원칙 4가지

WCAG란 웹 표준 국제기구인 W3C에서 기획된 웹 개발 가이드라인으로, 웹 개발 관련자들이 웹 접근성을 보장하는 웹 컨텐츠들을 제작할 수 있도록 도와주기 위한 것이다.

다음의 4가지 대원칙과 하위 상세 지침들을 제시하고 있다.

원칙 1. 인식의 용이성 (Perceivable)
모든 정보와 UI 컴포넌트들은 반드시 유저가 인지 가능한 방법으로 인지될 수 있어야 한다.

원칙 2. 운용의 용이성 (Operable)
UI 컴포넌트와 내비게이션은 용이하게 조작할 수 있어야 한다.

원칙 3. 이해의 용이성 (Understandable)
정보와 UI 조작은 용이하게 이해할 수 있어야 한다.

원칙 4. 견고성 (Robust)
콘텐트는 보조 기기를 포함한 다양한 유저 에이전트에서 해석될 수 있도록 견고해야 한다.

포스팅에서 각각의 원칙을 상세히 분석하기 보다 예제를 진행하며 지침에 대한 공부를 함께하려 한다.

3. 예제 : 쿠팡 로그인 폼 만들기

(웹접근성 수업 이전 VS 이후)

웹 접근성을 배우고 관심을 갖기 시작한 이후, 제작했던 코드를 리팩토링하며 더 공부하기로 마음을 먹었다. 그 첫 번째 시작을 위해 수업 전 사전 과제로 제출했던 쿠팡 로그인 화면 구현 코드를 다시 열어보았다. 웹 접근성에 대한 개념이 없던 때라 무작정 눈에 보이는 데로 그려내기 바빴던 것을 알 수 있었다. 이번 포스팅에선 Semantic한 html으로 수정하는 부분들을 정리해 보려 한다. 따라서 class, id 등의 선택자나 스타일과 관련한 부분은 빼고 정보와 관련된 요소들만 뽑아 예시로 들었다.

언어 설정

<!-- 수정 전 -->
<html lang="en">

<!-- 수정 후-->
<html lang="ko-KR">

원칙 3 이해의 용이성
3.1 기본 사용 언어가 각각의 웹 페이지에서 자동으로 정해지도록 해야한다.

html에 지정하는 언어 속성 lang 은 보조 기기가 어떤 언어를 기준으로 읽어낼지에 대한 구체적인 기준이 된다. 코드 에디터가 자동완성해 주어 제대로 살펴보지 않고 있다면 반드시 짚어주는 습관을 가지자.

타이틀 설정

<!-- 수정 전 -->
<title>Coupang</title>

<!-- 수정 전 -->
<title>Coupang 로그인</title>

원칙 2 운영의 용이성
(제목) 페이지, 프레임, 콘텐트 블록에는 적절한 제목을 제공해야 한다.

즉, 타이틀을 반드시 달아줄 뿐만 아니라 '홈페이지 내에서 네비게이션이 가능'한 교유한 타이틀을 달아주어야 한다. 수정 전 사용했던 Coupang 은 쿠팡 홈페이지 전체를 아우르는 광범위한 제목이다. 이를 쿠팡 로그인 혹은 'Coupang 로그인' 으로 구체적으로 달아주면 좋다.

이미지의 alt

<!-- 수정 전 -->
<header>
  <img src="./images/UI/type=color.svg" alt="logo"/>
</header>

<!-- 수정 후 -->
<header>
  <img src="./images/UI/type=color.svg" alt="coupang"/>
</header>

원칙1 지각의 용이성
1.1 대체 텍스트
글자가 아닌 모든 컨텐츠에 대체 텍스트를 주어 유저들에게 필요한 다른 형태의 정보로 변환될 수 있어야 한다.

예제 이미지 가운데 크게 그려져 있는 COUPANG 이미지에 대한 코드다.
alt에 대해선 '이미지에 대한 설명을 적는 속성', '써주면 좋지만 안 써줘도 문제(에러)는 되지 않는 것'이라는 정도로 들어왔다. 이때 의심을 했어야 했다. 웬만하면 최대한 덜 적고 적게 일하려는 개발자들이 왜인지 모르겠지만 꾸준히 쓴다면 무슨 이유가 있을 것이었는데...
alt 프로퍼티는 대체 텍스트를 제공하는 것으로 해당 이미지를 시각적으로 인지하지 못하는 사람들에게 그에 상응하는 정보를 텍스트로 전달해 주는 것이다.
따라서 기존에 적었던 logo는 사실 그 이미지의 역할을 뜻하는 것으로 우리가 눈으로 보고 있는 COUPANG이라는 정보와 거리가 멀다. 최대한 이미지와 동등한 정보를 제공하여야 한다.

장식용 이미지

<!-- 수정 전 -->
<img src="./images/UI/shape=letter.svg" alt="input_id_icon"/>

<!-- 수정 후 -->
<img src="./images/UI/shape=letter.svg"/>
  1. 인지의 용이성
    1.1 대체 텍스트
    만약 텍스트가 아닌 컨텐츠가 순수 장식용으로 사용되었거나 보이지 않는다면 보조기기에 인식되지 않도록 해야한다.

이유를 모르고 코드를 사용한 흔적을 볼 수 있다. alt는 대체 텍스트이며 이미지에 대한 정보를 제공하는 용도다. WCAG2.1에도 명시되어 있듯이 순수하게 시각적 장식 용도로 사용된 이미지, 아이콘 등은 보조 기기가 인식하지 못하도록 해야 한다.

form 요소

<!-- 수정 전 -->
<main>
  ...
  <form action="login.do" id="login_container">
    <div id="inputbox_id" class="inputbox">
      <img src="./images/UI/shape=letter.svg"/>
      <input type="email" placeholder="아이디(이메일)" required />
    </div>
    <div class="error_msg" id="error_msg_pw">
      아이디(이메일)는 이메일 형식으로 입력해주세요.
    </div>
    ...
    ...자동로그인 체크박스
    ...아이디(이메일)/비밀번호 찾기
    ...로그인 버튼
    ...회원가입
  </form>
</main>

위의 form은 여러모로 문제가 많다. form을 구성하는 방법은 다양하지만 가장 기본적인 방법을 따르는 것이 안전하다. 바로 form - fieldset - leng - input 으로 감싸는 것이다.

<form class="login-form">
  <fieldset>
    <legend class="a11y-hidden">회원 로그인 폼</legend>
    <p class="user-email">
      <img src="./images/UI/shape=letter.svg" class="input_icon letter" />
      <label for="user-email">아이디</label
        ><input type="email" id="user-email" name="uid" required placeholder="이메일 주소" />
    </p>
    
    <button type="submit" class="button-login">로그인</button>
  </fieldset>
</form>

원칙 3 이해의 용이성
3.3 Labels or Instructions : 유저 인풋이 요구될 때는 라벨 혹은 인스트럭션이 제공되어야 한다.

fieldset은 관련된 다양한 폼 컨트롤 요소들을 묶어줄 수 있고, legend는 이 묶음의 헤딩 역할을 한다. 각각의 라벨은 인풋 요소들의 개별적인 헤딩이라고 볼 수 있다. 라벨은 위의 예시와 같이 <label for='inputId'> 를 이용해 암묵적으로 연결할 수도 있고, 라벨의 태그로 인풋요소를 감싸 직접적으로 연결시켜줄 수도 있다.

그런데 쿠팡의 예제를 보면 라벨의 텍스트가 화면에 시각적으로 보이지 않고 있다. 이렇듯 웹접근성 측면에서 작성해 주어야 하는 요소들이 시각적으로는 보이지 않아야 하는 경우가 많다. 이럴 때 어떻게 할까?
'display: none 해주지 뭐!'라고 하면 적지 않느니만 못하다. display:none 으로 작성된 요소들을 렌더 트리에서 사라지는 돔 요소로, 보조기기에서도 보이지 않기 때문이다. 이럴 때 사용하는 여러 트릭들이 있는데, 수업 중에 배운 유용한 트릭을 공유한다.

A11y-hidden, 눈에만 보이지 않도록하는 CSS 트릭

.a11y-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  clip: rect(0, 0, 0, 0);
  clip-path: polygon(0 0, 0 0, 0 0);
  overflow: hidden;
}

position: absolute 를 주어 독립된 배치 문맥을 가지게한 후 1px의 가로 세로 높이를 준 후 음수 마진을 준다. 가로 세로 길이와 같은 값을 음수마진으로 주었기 때문에 사실상 화면에 보여지는 픽셀은 없다고 볼 수 있다. 하지만 아무 미미하게 남아있을 수 있는 점을 완전히 지우기 위해 clip을 이용해 모든 사각형 꼭지점에 0을 주고, 크로스 브라우징 이슈를 해결하기 위해 clip-path까지 사용한 후 overflow:hidden 을 주면 완벽하게 화면상에서 보이지도, 클릭 등으로 접근할 수도 없게 된다. 하지만 돔 요소는 여전히 존재하므로 보조기기는 접근이 가능하다.

전체 구조 : 헤딩 태그 쓰기

사전 과제에서 작성했던 구조는 다음과 같다.

<header>
  <img id='logo'>
</header>
<main>
  <form></form>
  <div></div>
</main>
<footer>
  <div></div>
</footer>

나름대로 header, main, footer 와 같은 시맨틱 태그를 사용해 각 영역을 나누려는 시도는 좋았다고 생각한다. 하지만 각각의 영역에 헤딩 태그를 이용해 돔 문서의 전체 개요를 지정해 주지 않은 점이 아쉽다. 수정해 보자면 다음과 같다.

    <header>
      <h1>
        <img src="./logo.png" alt="Coupang" />
      </h1>
    </header>
    <main>
      <h2>로그인</h2>
      <form></form>
    </main>
    <footer></footer>

원칙 2 운용의 용이성
2.4.6 Headings and Labels
웹 페이지의 헤딩과 라벨은 토픽과 목적을 묘사한다.

이런 식으로 헤딩 태그를 작성해 주면 보조 기기 이용자들이 문서 전체의 맥락을 살필 수 있을 뿐만 아니라 다른 헤딩으로 수월히 이동할 수 있다. 이때 h1은 페이지당 하나만 있어야 하며 하위 헤딩들은 건너뛰지 말고 반드시 연속적으로 사용되어야 한다. (h1 -> h2 -> h3)

마치며

오늘의 포인트 : 웹접근성의 중요성, WCAG2.1 웹접근성 대원칙, 쿠팡 예제 리팩토링

웹 접근성에 대한 공부를 위해 시작한 과제 리팩토링의 시작 포스팅이다. 항상 조급하게 따라가는 입장에서 알고리즘 보충 수업, js 프로젝트와 병행하며 작업하려면 많은 시간을 쏟기는 힘들 것 같다. 하지만 일주일에 하나라도, 완벽하다기보다 조금씩 개선해가는 UI를 만들어가는 것을 목표로 호기롭게 프로젝트를 시작하려 한다.

참고 링크

WCAG2.1
Web Accessibility Tutorials
[AOA11Y] 웹접근성을 고려한 HTML 마크업

profile
무럭무럭 자라는 주니어 프론트엔드 개발자입니다.

0개의 댓글