웹 접근성의 개념과 핵심 원리
웹 접근성이란?
-모든 사용자가 특정 환경이나 신체적 장애에 상관없이 웹 사이트나 애플리케이션에서 제공하는 모든 정보에 동등하게 접근하고 이용할 수 있도록 보장해 주는 것이다.
-장애인뿐만 아니라 고령자, 비장애인도 접근성의 대상이 된다.
웹 접근성 핵심 원리
사실 핵심 원리는 글마다 조금씩 다르게 서술하고 있는데, 네이버의 웹 접근성 관련 문서가 가장 간결하면서도 이해가 쉽게 정리되어 있다고 생각하여 갖고 왔다.
1.인식의 용이성: 모든 콘텐츠는 사용자가 인식할 수 있어야 한다.
2.운용의 용이성: 사용자 인터페이스 구성 요소는 조작 가능하고 네비게이션할 수 있어야 한다.
3.이해의 용이성: 콘텐츠는 장애유무에 관계없이 이해할 수 있게 구성되어야 한다.
4.견고성: 웹 콘텐츠는 미래의 기술로도 접근할 수 있도록 견고하게 만들어야 한다.
접근성 지원 도구
1.스크린 리더: 컴퓨터나 모바일을 사용할 때 화면에 표시되는 입출력 정보를 음성으로 알려주는 프로그램
2.명도 대비: 전경색과 배경색의 명도 차이를 비교할 수 있게 도와주는 확장 프로그램과 화면을 고대비로 전환할 수 있는 프로그램
3.접근성 자동 진단: 접근성 개선이 필요한 부분을 자동으로 검출해주는 프로그램
- Web: https://wave.webaim.org/
4.웹 브라우저 개발자 도구: 웹 콘텐츠 구성 요소를 탐색할 수 있으며 대부분의 브라우저가 지원
- Chrome: https://chromewebstore.google.com/detail/web-developer/bfbameneiokkgbdmiekhjnmfkcnldhhm?utm_source=chrome-ntp-icon
5. 접근성 지원 앱: 접근성 향상을 위해 지원되는 서비스
- 접근성 검사기, Lookout, Google 점자지원, 음성 자막 변환 및 알림, Voice Access, Android 접근성 도구 모음, Speech Services by Google, Seeing AI, Envision AI, Supersense, Sullivan+
웹 접근성 개선을 위한 가이드 라인
웹 표준 준수 - 시맨틱 웹
시맨틱 태그를 사용하면 웹의 모든 데이터를 기계가 이해할 수 있는 형태로 제작할 수 있게 되며 이를 시맨틱 웹이라고 한다. 이는 웹 브라우징에 쓰이는 보조 과학기술인 스크린 리더, 화면 돋보기, 음성 인식, 키보드 오버레이 등의 기계가 웹을 좀 더 쉽게 이해할 수 있게 해주기 때문에 접근성을 높이는데 도움이 된다.
이미지 설명
이미지에 대한 대체 텍스트(alt 텍스트)는 시각 장애인들이 웹 페이지의 이미지를 이해하고 그 의미를 파악하는데 도움이 되는 중요한 요소이다. 시각 장애인들은 스크린 리더를 통해 이미지에 대한 설명을 듣고, 웹 페이지의 내용을 이해할 수 있다. 또한, 네트워크 오류, 콘텐츠 차단 등 서비스 관련 이미지를 표현할 수 없는 경우에는 서비스와 무관한 이미지의 alt값이 음성으로 출력되기 때문에 접근성 뿐만 아니라 다양한 환경의 사용자를 고려한다면 alt는 꼭 필요한 속성이다.
대체 텍스트는 이미지가 나타내는 내용이나 주요 정보를 간결하게 설명해야 한다. 이때 시맨틱 태그와 중복되는 내용은 넣지 않아야 한다.
예를 들어,
<img src="cat.jpg" alt="풀밭에 앉아있는 고양이 이미지">
🔊(스크린 리더): 풀밭에 앉아있는 고양이 이미지 이미지
<img src="cat.jpg" alt="풀밭에 앉아있는 고양이">
🔊(스크린 리더): 풀밭에 앉아있는 고양이 이미지
이렇게 스크린 리더는 대체 텍스트에 자신이 해석한 요소를 덧붙여서 설명하기 때문에 중복으로 설명할 필요가 없다. 시맨틱 태그는 암시적으로 role을 갖고 있으며, 스크린 리더는 <img>
를 “이미지”로 자동으로 결정하게 된다. 따라서 이미지의 존재 여부를 표현하는 “사진”, “이미지”, “아이콘” 등의 단어를 대체 텍스트에 포함하게 되면 스크린 리더가 기본적으로 해석한 “이미지"와 중복된 의미를 갖기 때문에 적합하지 않다.
버튼
버튼 태그에서도 스크린 리더가 해석하기 쉽도록 설명을 달아주어야 한다. 버튼은 어떻게 설명을 달아줄까?
우선 스크린 리더가 코드를 어떻게 해석하는지 알아야 한다. 브라우저는 DOM 트리에서 스크린 리더와 같은 보조기술에서 사용되는 데 유용한 요소만 뽑아내서 접근성 트리(Accessibility Tree)를 만든다. 스크린 리더는 이 접근성 트리의 요소를 순차 탐색하게 되는데, 접근성 트리에 표시되는 요소의 Name을 기반으로 해석한다. 여기서 말하는 Name은 Accessible Name이라고도 하며 스크린 리더가 요소를 포커스했을 때 읽는 값으로 author와 contents 중 하나로 결정된다. 이때 author가 contents보다 우선순위가 높다.
- author: aria-label, aria-labelledby, title 속성,
의 alt 속성, svg의
- contents: Text 노드
button에 author이 설정되지 않은 경우에는 자식 요소의 Accessible Name을 모아 contents로 사용하는 Children Presentational이라는 특징을 갖는다.
예시)
1.텍스트와 아이콘이 함께 있는 경우:
// ❌ 좋지 않은 예시
<button type="button">
<svg>...</svg>
Click me
</button>
// 스크린리더: "Click me 버튼"// 문제점: svg가 장식용인지 의미가 있는지 불분명
// ✅ 좋은 예시
<button type="button">
<svg aria-hidden="true">...</svg>
Click me
</button>
// 스크린리더: "Click me 버튼"
2.여러 텍스트 요소가 중첩된 경우:
// ❌ 좋지 않은 예시
<button type="button">
<span>Price:</span>
<span>$100</span>
<span>USD</span>
</button>
// 스크린리더: "Price: $100 USD 버튼"// 문제점: 읽었을 때 자연스럽지 않음
// ✅ 좋은 예시
<button type="button" aria-label="가격: 100달러">
<span>Price:</span>
<span>$100</span>
<span>USD</span>
</button>
// 스크린리더: "가격: 100달러 버튼"
3.상태를 포함하는 복잡한 구조:
// ❌ 좋지 않은 예시
<button type="button">
<span>카트</span>
<span className="badge">3</span>
</button>
// 스크린리더: "카트 3 버튼"// 문제점: 숫자의 의미가 불분명
// ✅ 좋은 예시
<button type="button" aria-label="카트 - 3개의 상품">
<span>카트</span>
<span className="badge" aria-hidden="true">3</span>
</button>
// 스크린리더: "카트 - 3개의 상품 버튼"
4.동적으로 변하는 콘텐츠:
// ❌ 좋지 않은 예시
<button type="button">
<span>{isPlaying ? '일시정지' : '재생'}</span>
<span className="status">{duration}초</span>
</button>
// ✅ 좋은 예시
<button
type="button"
aria-label={`${isPlaying ? '일시정지' : '재생'} (총 ${duration}초)`}
aria-pressed={isPlaying}
>
<span>{isPlaying ? '일시정지' : '재생'}</span>
<span className="status" aria-hidden="true">{duration}초</span>
</button>
표
표는 반드시 사용자가 정보를 이해하기 쉽도록 구성해야 한다. 이를 위해 개발자는 표의 형태를 보고 데이터 표인지, 레이아웃 표인지 구분하여 서로 다른 방법으로 마크업해야 한다. 만약 표를 레이아웃 용도로 생각해 <table>
그를 남용하면 스크린 리더는 데이터 추출의 어려움을 겪게 되고, 사용자도 정보 탐색의 어려움을 느끼게 된다.
스크린 리더는 레이아웃 표와 데이터 표를 다르게 취급한다. 레이아웃 표의 경우 소스 코드 순서에 따라 표의 내용을 간단히 읽는 반면, 데이터 표는 열 및 행 수를 포함하여 데이터의 존재를 식별하고, 표 탐색 기능을 제공해 행 및 열 머리글 읽기 등을 수행해 사용자가 좀 더 쉽게 데이터를 탐색할 수 있다.
데이터 표
데이터 표는 행 머리글, 열 머리글 또는 둘 다 있는 경우로 좌표(x, y)가 있는 슬롯의 2차원 그리드에 정렬된 셀로 구성된다. 데이터가 위에서 아래로 읽히거나 제목 셀: 내용 셀이 1:多로 대응된다.
// ❌ 접근성이 고려되지 않은 테이블
<table>
<tr>
<th>상품명</th>
<th>가격</th>
<th>수량</th>
</tr>
<tr>
<td>사과</td>
<td>1000원</td>
<td>5개</td>
</tr>
</table>
// 스크린리더: "테이블, 상품명, 가격, 수량, 사과, 1000원, 5개"
// 문제점: "1000원"이 뭘 의미하는지 모름 (사과의 가격인지 알 수 없음)
표를 볼 수 없는 사람은 표의 행과 열을 구분하기 어렵기 때문에 테이블 내 요소 간 구조에 대한 정보를 제공해 사용자가 표를 쉽게 이해할 수 있도록 해야 한다.
<caption>
표의 제목을태그로 제공해 표의 목적을 명확하고 상세하게 설명하여 사용자가 표 콘텐츠를 확인할지, 넘어갈지 정할 때 도움을 줄 수 있다. 보통태그를 불가피하게 숨기는 경우가 많은데, 이러한 경우 주의할 점은 display:none 혹은 visibility:hidden으로 숨기면 스크린 리더가 해당 내용을 읽을 수 없기 때문에 해당 숨김 속성은 사용하면 안된다.
2.scope
-요소: 제목 셀로 사용
-scope="row': 행
-scope="col": 열
이렇게 scope를 명시하여 행과 열을 구분할 수 있도록 한다.
만약 복잡한 구조의 표일 경우 id, header 속성을 추가로 이용하여 관계를 설명해야 한다. 보통 rowspan 속성과 colspan 속성을 사용하는 경우 복잡한 구조라고 할 수 있다.
❕colspan과 rowspan은 여러 열/행을 하나의 셀로 합칠 때 사용한다.
<table border="1">
<tr>
<th colspan="2">이름과 나이</th> <!-- 2개의 열을 병합 -->
</tr>
<tr>
<td>김철수</td>
<td>20세</td>
</tr>
</table>
결과:
┌─────────────────┐
│ 이름과 나이 │ <!-- 하나의 셀이 두 열을 차지 -->
├────────┬────────┤
│김철수 │20세 │
└────────┴────────┘`
<caption>
과 scope를 사용하여 위의 잘못된 예시를 고쳐보면 다음과 같다.
// ❌ 접근성이 고려되지 않은 테이블
<table>
<caption>상품 주문 정보</caption>
<tr>
<th scope="col">상품명</th>
<th scope="col">가격</th>
<th scope="col">수량</th>
</tr>
<tr>
<th scope="row">사과</td>
<td>1000원</td>
<td>5개</td>
</tr>
</table>
// 스크린리더:
// 상품 주문 정보 테이블
// 열 제목: 상품명, 가격, 수량
// 행 1: 사과
// 사과의 가격: 1000원
// 사과의 수량: 5개
레이아웃 표
레이아웃 표는 단순 디자인을 위해 사용하는 테이블로, 좌에서 우로 읽히거나 제목 셀:내용 셀이 1:1로 대응하는 경우에 해당한다.
레이아웃 테이블은 표의 의미를 갖지 않고 단순 모양을 잡기 위한 목적으로 사용해야 한다. <table>
태그를 사용하지 않고 CSS로 테이블 형태를 만들어서 사용하는 것을 권장하나, 불가피하게 <table>
태그를 사용해야 하는 경우라면 summary 속성, <caption>
, <thead>
, <tbody>
, <tfoot>
, <th>
요소 등 의미 있는 요소를 사용하지 않아야 한다.
참고 자료
- https://accessibility.naver.com/accessibility
- https://brunch.co.kr/@830bfa34e0894d6/77
- https://tech.kakaopay.com/post/accessibility-stories-for-everyone/
- https://www.wa.or.kr/m1/sub1.asp
- https://developer.chrome.com/blog/full-accessibility-tree?hl=ko
- https://ko.legacy.reactjs.org/docs/accessibility.html
'공부 > Web' 카테고리의 다른 글
[Firebase] 파이어베이스로 React 앱 호스팅하기 (0) | 2023.11.14 |
---|---|
[Flask/플라스크] VSCode에 가상환경 세팅 & Flask 설치 (0) | 2023.10.26 |
Webpack이란? (0) | 2023.05.15 |
면접 대비 정리 (0) | 2023.04.12 |
WEB / WAS (0) | 2022.10.18 |