2022-02-14 13:22 작성

HTML TABLE 심화 기능과 접근성

Table of contents
  1. HTML TABLE 심화 기능과 접근성
    1. Table에 <caption>을 이용해 caption 더하기
    2. <thead>, <tfoot>, 그리고 <tbody>로 구조 더하기
    3. 내포(Nesting) Tables
    4. 시각적 손상을 입은 사용자를 위한 Tables
      1. 행과 열 headers 사용하기
      2. scope 속성
      3. id와 headers 속성들
    5. 저작권

Table에 <caption>을 이용해 caption 더하기

<table> element에 <caption> element를 넣어 caption 기능을 넣을 수 있다.

Dinosaurs in the Jurassic period
Hello World!
<table>
	<caption>
		Dinosaurs in the Jurassic period
	</caption>

	...
</table>

상기의 간단한 에시에서 나타나는 것처럼, caption은 table 내용에 대해 기술하는 의미를 가진다. Caption은 사용자에게 필요한 정보가 있는지 빠르게 탐색할 수 있게 한다는 점에서 유용할 뿐 아니라 시각 장애를 가진 이용자들에게도 전체 내용을 간단하게 소개해준다는 점에서 유용하다.

Note: summary 속성도 설명 용도로 <table> element에 사용할 수 있으며, Screenreaders가 읽을 수 있다. 그러나 <caption> element를 사용하기를 권장한다. 그 이유는 HTML5가 시작되고 난 이후에 summary는 폐기되었고 시각이 정상인 사용자들은 해당 항목을 읽을 수 없기 때문이다(Web page에 시각적으로 나타나지 않음).

<thead>, <tfoot>, 그리고 <tbody>로 구조 더하기

Tables의 구조가 점점 더 복잡해질수록 구성요소에 좀 더 구조적인 정의를 사용해주는 것이 유용할 것이다. 이를 수행하는데 있어 깔끔한 방식 중 하나는 <thead>, <tfoot>, 그리고 <tbody>를 이용하는 방법이다. 각각 table의 header, footer, 그리고 body section을 mark up 한다.

이러한 elements는 screenreaders 사용자들의 접근성을 더 향상시키지도, 그 자체로서는 시각적으로 향상(디자인)이 되지도 않는다. 다만, 이 elements를 이용하면 styling과 layout을 하는데 있어 매우 유용하다(CSS를 Table에 적용할 수 있는 갈고리 역할). 흥미로울 법한 예시를 들자면, 데이터가 많은 tables에서 매 page마다 header와 footer가 반복되고 contents만 표시되게 한다면 사용자 입장에서 보기 편할 것이며 한 눈에 데이터가 들어올 것이다.

이러한 기능들을 사용하기 위해:

  • <thead> element는 table의 header 역할을 하는 부분을 감싸야 한다. 대개 열의 대표값을 포함하는 첫째 행이 되고는 하지만 항상 그렇지는 않다. 만약 <col>/<colgroup> element를 사용하고 있다면, table header는 <col>/<colgroup> element의 아래에 와야 한다.

  • <tfoot> element는 table의 footer 역할을 하는 부분을 감싸야 한다. 예를 들어, 이 부분은 이전의 행들의 값들이 더해진 마지막 행이 될 수 있다. Table footer는 table의 아래쪽에 포함할 수도 있고, table header의 바로 아래에 포함할 수도 있다(어느 곳에 위치시키던지 Browser는 footer를 table의 아래쪽에 배치).

  • <tbody> element는 table의 header와 footer에 포함되지 않는 table content의 다른 부분들을 감싼다. 이 부분은 때로의 table header의 아래에, 때로는 footer의 아래에 배치되는데 이 부분은 개발자가 구조를 어떻게 설계하는지에 따라 달려 있다.

Note: <tbody> element는 모든 table에 포함되는데, 이는 개발자가 code에 명시하지 않아도 절대적으로 포함된다. 이 부분을 확인하기 위해서 <tbody>가 포함되지 않은 table을 browser developer tools로 확인하면 browser가 이 tag를 추가한 것을 볼 수 있을 것이다.

How I chose to spend my money
Purchase Location Date Evaluation Cost (€)
SUM 118
Haircut Hairdresser 12/09 Great idea 30
Lasagna Restaurant 12/09 Regrets 18
Shoes Shoeshop 13/09 Big regrets 65
Toothpaste Supermarket 13/09 Good 5
<table>
	<caption>
		How I chose to spend my money
	</caption>
	<thead>
		<tr>
			<th>Purchase</th>
			<th>Location</th>
			<th>Date</th>
			<th>Evaluation</th>
			<th>Cost (€)</th>
		</tr>
	</thead>
	<tfoot>
		<tr>
			<td colspan="4">SUM</td>
			<td>118</td>
		</tr>
	</tfoot>
	<tbody>
		<tr>
			<td>Haircut</td>
			<td>Hairdresser</td>
			<td>12/09</td>
			<td>Great idea</td>
			<td>30</td>
		</tr>
		<tr>
			<td>Lasagna</td>
			<td>Restaurant</td>
			<td>12/09</td>
			<td>Regrets</td>
			<td>18</td>
		</tr>
		<tr>
			<td>Shoes</td>
			<td>Shoeshop</td>
			<td>13/09</td>
			<td>Big regrets</td>
			<td>65</td>
		</tr>
		<tr>
			<td>Toothpaste</td>
			<td>Supermarket</td>
			<td>13/09</td>
			<td>Good</td>
			<td>5</td>
		</tr>
	</tbody>
</table>

내포(Nesting) Tables

하나의 table 안에 다른 table을 내포하는 것도 가능하다. 물론 이 경우, <table> element를 포함시켜 완전한 구조로서 포함해야 한다. Mark up 표시를 혼란스럽게하고 screenreaders 사용자들에게 덜 접근적이라는 점에서 일반적으로 조언하는 방법은 아니다. 게다가 많은 경우, 추가 cells/rows/columns를 이미 존재하는 table에 추가하는 형태로 해결되기 때문이다. 그럼에도 불구하고 필요하다면 이 기능을 사용할 수 있다. 예를 들어 다른 sources에서 content를 쉽게 가져오는 경우를 들 수 있다.

다음의 markup은 간단한 내포 table을 보여준다:

title1 title2 title3
cell1 cell2 cell3
cell2 cell3
cell4 cell5 cell6
<table id="table1">
	<tr>
		<th>title1</th>
		<th>title2</th>
		<th>title3</th>
	</tr>
	<tr>
		<td id="nested">
			<table id="table2">
				<tr>
					<td>cell1</td>
					<td>cell2</td>
					<td>cell3</td>
				</tr>
			</table>
		</td>
		<td>cell2</td>
		<td>cell3</td>
	</tr>
	<tr>
		<td>cell4</td>
		<td>cell5</td>
		<td>cell6</td>
	</tr>
</table>

시각적 손상을 입은 사용자를 위한 Tables

어떻게 data tables를 이용하는지 간단히 상기해보자. Table은 데이터에 빠르게 접근해 다른 값들을 찾을 수 있는 간편한 도구다. 예를 들어, 2016년 8월에 Gent에서 얼만큼의 반지가 팔렸는지 찾는 것은 한 번의 눈흘김으로도 찾을 수 있을 정도로 간단하다. 정보를 이해하기 위해서 우리는 table에 있는 data의 행과 열 headers 교차점을 시각적으로 연합한다.

Items Sold August 2016
Clothes Accessories
Trousers Skirts Dresses Bracelets Rings
Belgium Antwerp 56 22 43 72 23
Gent 46 18 50 61 15
Brussels 51 27 38 69 28
The Netherlands Amsterdam 89 34 69 85 38
Utrecht 80 12 43 36 19

그러나 이러한 시각적 연합을 사용할 수 없다면? 위의 table을 어떻게 읽을 것인가? 시각에 손상을 입은 이용자들은 종종 web pages에 있는 정보를 탐색하기 위해 screenreader를 사용한다. 해당 이용자들이 일반적인 text를 읽는 것에는 문제가 없다. 그러나 table을 해석하는 것은 꽤 도전을 요구하는 일일 것이다. 그럼에도 불구하고 적절한 markup을 사용해서 시각적 연합을 컴퓨터 연산을 통한 요소로 전환할 수 있다.

이 기사의 이번 section은 더 접근가능한 tables를 만들기 위한 기술에 대해 설명할 것이다.

행과 열 headers 사용하기

Screenreaders는 모든 headers를 인식하여, 관계된 각각의 headers와 cells 사이에서 프로그램적 연합을 만들어 낸다. 행과 열 headers의 연합은 각각의 cell에 있는 특정 data를 해석하고 인식하게 하므로, screenreader 사용자들은 정상 시각을 가진 사용자들과 비슷한 형태의 table을 해석할 수 있게 된다.

scope 속성

scope 속성은 <th> element에 추가할 수 있는 속성으로, screenreaders가 특정 header가 어떤 형태의 header로 cells를 가리키고 있는지 알 수 있게 한다. 다시 말하자면, 한 header가 행의 header인지, 열의 header인지 구분한다. 이전에 사용했던 예시로 돌아가 이 속성을 사용하게 되면 열의 headers를 보다 명확하게 명시할 수 있게 된다.

<thead>
  <tr>
    <th scope="col">Purchase</th>
    <th scope="col">Location</th>
    <th scope="col">Date</th>
    <th scope="col">Evaluation</th>
    <th scope="col">Cost (€)</th>
  </tr>
</thead>

각각의 열은 header를 아래와 같이 가질 수 있다.

<tr>
  <th scope="row">Haircut</th>
  <td>Hairdresser</td>
  <td>12/09</td>
  <td>Great idea</td>
  <td>30</td>
</tr>

Screenreaders는 이렇게 구조화된 markup을 인식할 것이며, 사용자들이 전체 행과 열을 한 번에 인식할 수 있게 한다.

scope는 두 가지 더 가능한 값을 가진다 - colgrouprowgroup. 이 값들은 복수의 행과 열을 대표하는 상위 headings에 사용된다. “Items Sold August 2016” table로 돌아가서 보면 “Clothes” cell이 “Trousers”, “Skirts”, 그리고 “Dresses” cells 위에 안착 되어 있는 것을 볼 수 있을 것이다. 이러한 cells 모두 headers(<th>)로 markup 되어 있어야 한다. 그러나 “Clothes”는 세 개의 subheadings를 정의하는 상위 heading이다. 그러므로 “Clothes”는 ``scope=”col” 보다는 scope=”colgroup”`이라는 속성을 가져야 한다.

id와 headers 속성들

scope 속성의 대안은 idheaders 속성들을 사용하여, headers와 cells 간 연합을 생성해주는 방법이 있다. 사용하는 방법은 다음과 같다:

  1. <th> element에 고유한 id를 추가한다.

  2. 각각의 <td> element에 headers 속성을 추가한다. 각각의 headers 속성에 해당 cell의 header 역할을 하는 모든 <th> elements의 id들을 space로 구분하여 각각 포함시키도록 한다.

이 방법은 spreadsheet과 같이 HTML table이 각각의 cell 위치를 명확하게 정의할 수 있도록 해준다. 이 방법이 잘 작동하기 위해서는 행과 열의 headers가 모두 필요하다. 위에 제시된 두 개의 snippets는 아래와 같이 다시 작성할 수 있다:

<thead>
  <tr>
    <th id="purchase">Purchase</th>
    <th id="location">Location</th>
    <th id="date">Date</th>
    <th id="evaluation">Evaluation</th>
    <th id="cost">Cost (€)</th>
  </tr>
</thead>
<tbody>
  <tr>
    <th id="haircut">Haircut</th>
    <td headers="location haircut">Hairdresser</td>
    <td headers="date haircut">12/09</td>
    <td headers="evaluation haircut">Great idea</td>
    <td headers="cost haircut">30</td>
  </tr>
  
  ...

</tbody>

Note: 이 방법은 headers와 data cells 간에 매우 정확한 연합을 생성하지만, 더 많은 markup을 사용하며 errors에 대한 표시가 되지 않는다. 대개 대부분의 tables에는 scope 접근방식만으로 충분하다.

저작권


Mozilla 기여자가 작성한 MDN에 대해는 CC-BY-SA 2.5 라이선스에 따라 사용할 수 있습니다.


크리에이티브 커먼즈 라이선스
이 저작물은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.