접근 가능한 테이블 만들기 by 백남중

2008년 시각장애인의 표 접근 문제라는 명칭 하에 테이블과 스크린 리더(센스리더)와의 관계에 관한 글을 올렸다.
그러나 2008년 WCAG2.0이 발표되고, 센스리더도 업그레이드 되면서 테이블 내에서 id, header등을 제대로 접근하고, 음성 출력 할 수 있게 됨에 따라 스크린 리더와 테이블의 음성 출력에 관한 내용을 다시 정리하였다.
특히 이번 글에서는 테이블에서 헤더 부분(<th scope="col"> <th scope="row">)을 잘못 정의한 경우의 예제를 중심으로 살펴 본다.

이번 글은 이해를 돕기 위하여 원래의 표는 그림으로 처리하였다. 또한 소스를 보여 주는 대신 WAT(Web Accessibility Toolbar)의 Tables 메뉴에서 Show Data Tables를 선택하여 Summary, caption, th, td, li를 보이게 하였다. 또한 Table Headers를 선택하여 th 셀을 검정색으로 처리하여 이해의 편리를 도모하였다.
(글 작성 일시: 2009년 12월 27일)

<차례>
1. 테이블 내에서 센스리더 이동시 음성 출력 방법
2. 관련 지침
3. <th scope="col"> <th scope="row">를 사용하였으나 셀의 내용을 목록으로 처리한 경우
4. <th scope="col"> <th scope="row">이 없고, 셀을 병합한 경우
5. 열 제목과 메일 목록을 별도의 테이블로 나누고, 셀 병합 후 목록으로 처리한 경우
6. <th scope="col">은 없고, <th scope="row">만 2개 있는 경우
7. <th scope="row">를 제공하지 않은 경우
8. <td scope="row"> 문제
9. Summary 문제

1. 테이블 내에서 센스리더 이동시 음성 출력 방법


현재 문서에서 테이블간 이동(ctrl+f3)을 실행하면 테이블에 위치한 후 다음과 같이 음성 출력한다.

▷ 도서 (2009. 8현재) 테이블시작 (4행 12열) (1/3)

caption으로 정의한 내용은 테이블의 제목처럼 시각적으로 나타나며, 스크린 리더는
- 먼저 caption을 음성 출력하고(▷ 도서(2009. 8현재)),
- 테이블 시작을 알리고
- 테이블의 행과 열의 수(4행 12열), 그리고 전체 테이블 수(3)과 현재 문서 내에서 몇 번째 테이블인지(1)를 음성 출력한다.

테이블에 위치한 상태에서 테이블 셀을 읽는 방법은 두 가지가 있다.
첫번째 방법은 ↓를 활용하여 이동하는 방법이다.
구분에 위치한 상태에서 ↓를 실행하면 다음과 같이 음성 출력한다.

구분
총류(000)
철학(100)
종교(200)
사회과학(300)
순수과학(400)
기술과학(500)
예술(600)
언어(700)
문학(800)
역사(900)
합계
빈줄
종합자료실
15,807
7,910
3,548
29,536
5,094
13,183
7,365
5,079
55,261
.....

위와 같이 이동하는 경우 행이 바뀌면 빈줄 이라고 음성 출력한다.
이 방법은 현재 셀의 아래 셀로 이동하는 방법이 없고, 음성 출력하는 셀의 갯수를 확인해야 한다는 어려움이 있어서 사실상 사용 불가능하다.

두번째 방법은 센스리더의 테이블 안에서의 이동 방법을 활용하는 것이다.
센스리더의 테이블 내에서의 이동은 Ctrl 키와 Alt 키를 누른 상태에서 방향키를 누르면 셀간 이동이 가능하다.
Ctrl+Alt+→ 오른쪽 셀로 이동
Ctrl+Alt+← 왼쪽 셀로 이동
Ctrl+Alt+↓ 아래 셀로 이동
Ctrl+Alt+↑ 윗 셀로 이동
Ctrl+Alt+Enter 테이블 현재 위치 읽기

1. 먼저 1행 1열에 위치한다. 구분 이라고 음성 출력한다.
2. 1에서 오른쪽 셀로 이동(Ctrl+Alt+→)을 실행한다. 총류(100)이라고 음성 출력한다.
3. 2에서 아래 셀로 이동(Ctrl+Alt+↓)을 실행한다. 행(row) 값이 바뀌기 때문에 바뀐 행 제목과 값을 종합자료실 15,807이라고 음성 출력한다.
4. 3에서 오른쪽 셀로 이동(Ctrl+Alt+→)을 실행한다. 열(column) 값이 바뀌기 때문에 바뀐 열 제목과 값을 철학(100) 7,910이라고 음성 출력한다.
만일 현재 셀의 위치를 알고 싶으면 Ctrl+Alt+Enter을 실행한다. 센스리더는
현재 위치는 3행 12열 중 2행 3열 위치입니다
라고 음성 출력한다.
5. 4에서 오른쪽 셀로 이동(Ctrl+Alt+→)을 실행한다. 열(column) 값이 바뀌기 때문에 바뀐 열 제목과 값을 종교(200) 3,548이라고 음성 출력한다.
행 제목이 같은 상태에서 열 제목만 바뀌었기 때문에 행 제목은 음성 출력하지 않는다.
6. 5에서 아래 셀로 이동(Ctrl+Alt+↓)을 실행한다. 행(row) 값이 바뀌기 때문에 바뀐 행 제목과 값을 어린이 자료실 835라고 음성 출력한다.
현재 셀의 열 제목을 확인하려면 Ctrl+Alt+Shift+PgUp를 실행하면 열 제목 종교(200)이라고 음성 출력한다. 열 제목 읽기를 하면 가상 커서의 위치는 이동하지 않는다.

2. 관련지침


WCAG 1.0: - 지침 5에서 표는 표를 지원하지 않는 환경에서도 유연하게 변경될 수 있도록 만든다
- 5.1 데이터가 들어있는 표에는 제목행과 제목열(통칭하여 header)을 명시한다

WCAG 2.0

1.3.1 Info and Relationships: Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)


Techniques of WCAG 2.0:
H39: Using caption elements to associate data table captions with data tables
H43: Using id and headers attributes to associate data cells with header cells in data tables
H51: Using table markup to present tabular information
H63: Using the scope attribute to associate header cells and data cells in data tables
H73: Using the summary attribute of the table element to give an overview of data tables

인터넷 웹 콘텐츠 접근성 지침(국가표준 2005.12.21):
항목 3.1 데이터 테이블 구성:
데이터 테이블은 테이블을 구성하는 데이터 셀의 내용에 대한 정보가 충분히 전달될 수 있어야 한다


3. <th scope="col"> <th scope="row">를 사용하였으나 셀의 내용을 목록으로 처리한 경우



위 테이블의 경우에는 <th scope="col"> <th scope="row">를 사용하였으나 <td> 내의 값을 <ul> 처리하였다. 단순하게 처리할 수 있는 것을 복잡하게 설계하여 오히려 셀 내의 내용을 이해하기 힘들게 만든 경우이다.

4. <th scope="col"> <th scope="row">이 없고, 셀을 병합한 경우




첫번째 편지에서 스크린 리더의 테이블 내에서의 오른쪽 셀로 이동(ctrl+alt+→)을 하면 다음과 같이 음성 출력한다

>
해제 체크상자
별표시 이미지
새 메일 이미지
2009년 12월 23일 11시

위의 소리만 듣고 보낸 사람과 편지 제목을 알수 있겠는가?
어떤 이유에서 이렇게 구현했는지는 몰라도 각각의 아이템을 한 개의 셀로 나누어 제공해야 한다.

위 경우는
- 기본적으로 열 제목 <th scope="col">과 행 제목 <th scope="row">를 제공하지 않았으며
- 기본적으로 나누어야 할 받은 사람과 편지 제목을 한 셀로 병합하였으며,
- 더 나아가 병합한 셀을 5개의 div로 나누었으며,

- 받은 날짜와 편지 크기도 한 셀로 병합하여 접근을 어렵게 한 경우이다.

5. 열 제목과 메일 목록을 별도의 테이블로 나누고, 셀 병합 후 목록으로 처리한 경우



메일의 정렬옵션(보낸 사람, 제목, 날짜, 크기)을 설정하기 위한 이유에서 인지는 몰라도 테이블의 열 제목 부분을 별도의 테이블로 나누었으며, 나눈 열 제목 테이블은 <th>를 사용하였다.
한 개의 테이블을 제목과 목록을 별도의 테이블로 나눈 것이 문제가 되며, <th>를 사용하였어도 메일 목록 부분이 별도의 테이블로 되어 있어 사용한 효과가 전혀 없다.
또한 보낸 사람과 제목 그리고 날짜와 크기를 한 개의 셀로 병합한 것도 문제가 된다.
위와 같은 경우 각종 정렬옵션을 구현하기 위해서는 다른 방법을 구현해야 하며, 각각의 항목을 하나의 셀로 나누고, 행에도 <th scope="row">를 사용하여 접근성을 도모해야 한다.

6. <th scope="col">은 없고, <th scope="row">만 2개 있는 경우



위의 경우는 열 제목 <th scope="col">은 없이 행 제목 <th scope="row">만 2번 제공하여 접근성을 떨어뜨린 경우이다.
시장 구분의 인정시장에서 셀 아래로 이동 ctrl+alt+↓을 실행하면 다음과 같이 음성 출력한다.

소재지 시장유형 생활권중심시장
소재지 시장 개설년도 1959년

즉 현재 셀의 헤더를 정확히 정의하지 않았기 때문에 나타난 결과이다.
'소재지 시장유형 생활권중심시장'에서는 시장유형으로서 생활권중심시장을 의미하는 것이기 때문에 소재지는 필요없다.
'소재지 시장 개설년도 1959년'에서는 시장 개설년도가 1959년임을 의미하는 것으로서 소재지는 필요없다.
이러한 경우에는 테이블을 새로 정의하고 열 제목과 행제목을 제대로 구분하여 제공해 주어야 한다.

7. <th scope="row">를 제공하지 않은 경우



위 테이블은 행의 첫 셀 부정불량식품을 다시 2개의 제목(보라색 부분. 법 제4조, 제5조, 제6조, 제22조, 제74조의 위반행위, 무허가(신고)식품 등의 제조·가공·운반 및 소분·판매하는 행위)으로 나누었으나 제대로 표현하지 않아서 접근성을 떨어뜨린 경우이다.
예를 들어 부정 불량 식품과 관련하여 법 제4조, 제5조, 제6조, 제22조, 제74조의 위반행위 중 소해면상뇌증, 탄저병 등 질병에 걸린 동물을 사용 식품 등을 제조·가공· 조리한 자를 신고한 경우 포상금으로 1,000만원을 받는다는 내용이다.
그러면 포상금 1,000만원에 위치한 상태에서 아래 셀로 이동(ctrl+alt+↓)하여 100만원에 위치하면 다음과 같이 음성 출력해야 한다.

부정불량식품, 법 제4조, 제5조, 제6조, 제22조, 제74조의 위반행위, 마황, 부자, 천오, 초오 등을 사용 식품 등을 제조·가공·조리한 자 100만원
그러나 현재 행 제목을 제대로 사용하지 않아 그냥 100만원이라고만 음성 출력하여 무슨 내용인지 어렵게 하고 있다.

8. <td scope="row"> 문제



위의 경우는 세번씩이나 행을 병합하여 id, headers로 각각의 셀에 대해 정확하게 정의를 해주어야 하는데도 불구하고 첫번째 병합된 셀에만 <td scope="row">를 제공하여 접근성을 떨어뜨린 경우이다.
<td scope="row">로 정의한 경우에도 센스리더 프로페쇼날 1.2.0.3의 경우에는 출판연도가 오래된 자료나 가치 있는 자료보관에서 아래 셀로 이동하면 737.50㎡ 도서 수서라고 음성 출력한다.
위 테이블의 경우에는 테이블의 목적이 층별안내인데도 불구하고 대지면적, 층별면적이 먼저 나와 테이블 자체를 새로 구성할 필요가 있다.

9. Summary 문제


< a herf="http://www.w3.org/TR/WCAG20-TECHS/H73.html">Techniques of WCAG 2.0의 H73에서는 데이터 테이블의 개관을 제공하기 위하여 summary 속성을 사용하라고 권고하고 있다.
즉 테이블의 행, 열을 2단계, 3단계로 정의하는 경우 summary에서 그 구조에 관한 것을 언급해 주어야 한다는 것이다.


위의 경우처럼 열 제목을 2단계, 행 제목을 3단계로 나누었음에도 불구하고 summary에서는 그 구조에 관한 내용을 전혀 정의하지 않았다. 현재 표의 개관을 읽지 못하는 시각장애인 사용자들이 테이블의 내용을 알지 못하기 때문에 summary에서 다음과 같이 정의해 주면 훨씬 접근하기 용의하다.
<table summary="축종(1단계)의 지역별 호수, 두수(2단계) 현황">
<table summary="보험별 차종(3단계)의 지연 기간별(10일 이내, 10일 초과 매 1일, 최고액, 2단계) 과태료 부과 기준">

이 글을 쓰기 위해 도움을 주신 방미희님, 장성민님 그리고 정태영님께 감사를 드립니다.


덧글

  • 신현석 2009/12/28 12:15 # 삭제

    6, 8번의 경우는 scope 문제가 아니라 표 구성 자체에 문제가 있네요. 기획이나 디자인 단계에서 콘텐츠를 엉망으로 만들어서 접근성있게 구현하는 것이 불가능한 경우입니다. 기획/디자인 단계에서 접근성을 고려하는것이 매우 중요하다는 것을 보여주는 사례로 생각됩니다.
  • 스마일맨 2009/12/31 12:06 # 삭제

    http://www.wah.or.kr/Example/wcag_exam.asp?cate=53#Main_183
    웹접근성 연구소에 있는 글입니다.
    여기보면 해결방안에 -내용셀의 콘텐츠 형식에 맞게 ul, li를 적용하여 목록으로 개선.

    이글의 3번을 보년 ul 불필요한 구조를 사용 - 진짜 불필요한 구조인가요? 컨텐트 형식은 목록 형태가 맞고 ul로 쓴것이 크게 잘못된 방식이 아닌듯 한데..

    헷갈리네요. 이글로 보면 td내에는 구조를 쓰지말란 이야기 같은데.. 표내에는 구조를 나타내는 마크업을 해서는 안되는 것인지 잘 모르겠습니다.
  • 2010/01/07 14:11 # 삭제 비공개

    비공개 덧글입니다.
  • rlrldp 2010/02/05 16:34 # 삭제

    글을 읽다가 이해되지 않는 단락이 있어서 글 남깁니다.
    보신다면 답변 좀 해주세요~^^

    3.<th scope="col"> <th scope="row">를 사용하였으나 셀의 내용을 목록으로 처리한 경우 이게 잘못된 건지 모르겠습니다.
    <td>안에 리스트 형식의 텍스트가 있을때 당연히 <ul>이나 <ol>을 썼는데,
    접근성면에서 잘못된라고 하니 개인적으로는 뭐가 문제 되는건지 모르겠습니다.
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.


me2day