📝

3. 이해의 용이성

 

3.1. 가독성

3.1.1. [검사항목17] 기본 언어 표시

: 주로 사용하는 언어를 명시해야 한다.
여러분이 해외여행으로 외국을 가게 되었다고 가정해 볼게요. 외국인이 말을 걸어왔을 때, 한국말을 할 줄 안다면 굉장히 반갑겠죠? 서로 훨씬 수월하게 대화를 할 수 있게 될 겁니다. 이와 유사하게 웹 브라우저는 웹페이지를 보여주는 텍스트 언어 정보를 기본으로 텍스트를 화면에 표시하게 됩니다. 다양한 언어를 지원해 주는 스크린 리더를 이용하는 경우에는 텍스트 콘텐츠 언어 정보를 그대로 화면 스크린 리더에 전달하여 정확한 발음으로 읽어줍니다. 그렇게 된다면 기본적인 언어를 미리 저장해두었을 때, 이 창이 어떤 언어로 이루어져 있는지 파악하기 쉽겠죠?
웹 브라우저는 텍스트 상의 언어 정보를 기본으로 화면 상에 표시하고 전달합니다. 언어를 직접 명시하게 된다면 언어를 자동으로 전달해 주는 스크린 리더가 우리가 저장한 언어로 전환하여 읽어주는데요. 이러한 순서 때문에 웹페이지 상에 기본 언어나 자주 사용하는 언어를 기입해야 합니다.
 
문서 타입에 맞는 기본 언어를 적절하게 설정한 경우는 아래와 같은 예시가 있습니다.
 
HTML 문서가 어떤 언어로 작성되었는지 알려주기 위해서는 lang 속성 언어를 이용합니다. 영어로 작성된 문서라면 en을, 한글로 작성되었다면 ko라고 값을 주면 됩니다.
lang 속성은 기본적으로 아래의 예시와 같이 작성합니다. 아주 간단해 보이지만 이 속성을 통해 브라우저가 사용자들에게 페이지를 번역하여 보여 줄지 결정하는 기능 또한 제공합니다.
<!DOCTYPE html> <html> <head lang="ko"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title></title> </head> <body> </body> </html>
「한국형 웹 콘텐츠 접근성 지침2.1」 에는 웹페이지의 head 요소 안에 페이지의 기본 언어 선언을 규정하고 있습니다.
지침을 필수로 명시해 주어야 하는 이유는 lang 속성에서 명시된 값을 통해 스크린 리더가 인식하기 때문입니다.
 

3.2.예측 가능성

3.2.1. [검사항목18] 사용자 요구에 따른 실행

: 사용자가 의도하지 않은 기능은 실행되지 않아야 한다.
만약 여러분이 시각 장애를 가진 사람이라고 가정해 봅시다. 여러분은 인터넷 뱅킹 이용을 위해 주민번호를 입력하게 됩니다. 만약 주민번호 앞 6자리를 제대로 입력했는지도 모르는 상황에서 커서가 옆으로 이동한다면 여러분은 어떻게 알아차리실 건가요?
이런 불편함을 없애기 위해서 사용자가 의도하지 않은 기능이 실행 되어서는 안 됩니다. 사용자가 자발적으로 의도한 상황에서만 새 창을 뜨게 하거나, 새로운 창이 새로고침 되는 등의 기능이 실행되어야 합니다. 또한 발생할 수 있는 변화를 이전에 공지하거나, 사용자가 실행하고 있던 기능을 완료할 수 있는 실행 버튼을 별도로 제공해주는 것이 좋습니다.
 

3.2.1.1. 새 창

사용자가 마우스를 조작하지 않았는데도, 의도하지 않은 새로운 창이 뜨는 것은 오류입니다. 특히 시각 장애가 있는 환경에서는 예측 불가능한 변화가 번거로운 것이 아니라, 그 이후에 웹 탐색에 방해가 되는 결정적인 요인으로 작용합니다. 따라서 발생 가능한 변화를 사전에 알려주거나, 사용자가 실행하려던 창을 완료할 수 있는 버튼을 별도로 제공하는 것이 좋습니다.
 
  • 준수 사례
1) 새 창을 호출하는 <a> 요소에 target=”blank” 속성을 선언합니다.
<a href=”http://naver.com “target=”_blank”>네이버</a>
2) 자바스크립트의 window.open() 메서드를 이용해 새 창을 열었을 때 새 창을 호출하는 요소에 title=”새 창” 속성 선언합니다.
<script type="text/javascript"> var w = window.open('http://URL주소'); w.document.title = '새창'; </script>
 
  • 오류 사례
1) 새 창을 호출하는 <a>요소에 target=”_blank” 속성을 선언하지 않습니다.
<a href=”http://naver.com>네이버</a>
 

3.2.1.2. 사용자가 의도하지 않은 팝업 창 / 레이어 요소

사용자가 의도하지 않는 팝업 창이나 레이어 요소의 예시로는 페이지 접속 시 자동으로 열리는 공지사항 혹은 이벤트 프로모션 팝업이나 우편번호 입력란에 포커스를 맞췄을 때 자동으로 열리는 컴색창 등이 있습니다. 이 때 시각 장애 환경의 사용자는 자신이 버튼을 잘못 건드렸거나, 링크가 잘못 실행되었다고 오해할 수 있습니다.
 
  • 준수 사례
페이지에 접속할 때 팝업이나 레이어가 자동으로 열리지 않아야 합니다. 하지만 대부분의 사이트에선 이러한 기능이 추가되어 있는 걸 심심치 않게 확인할 수 있습니다. 대부분 필요한 정보를 알려주기 위함인데, 그럼에도 시각 장애 환경에서는 불편함을 주는 요소가 될 수 있습니다. 그러므로 입력 서식에 입력할 때 필요한 팝업이나 레이어는 링크 또는 버튼을 눌렀을 때 호출해야 합니다.
ex) 우편번호 검색 : ‘우편번호’ 버튼을 클릭했을 때, 우편번호 검색 팝업이 열립니다.
notion imagenotion image
notion imagenotion image
 
 
 
  • 오류 사례
1) 페이지에 접속했을 때 팝업이나 레이어가 자동으로 열리는 경우가 있습니다. 입력 서식에 포커스가 있을 경우도 자동으로 열립니다.
ex) 아래와 같은 코드 실행 시 입력 박스를 클릭하면 새 창이 자동으로 발생하게 됩니다.
<input type="text" onfocus="window.open('zipcode.html')" />
출처 : http://image.kyobobook.co.kr/ink/html/guide/guide_access.html#wa-3
 
 
2) selectonchange 이벤트가 적용되어 option 선택을 하자마자 페이지가 이동된 경우도 오류입니다. 이런 경우는 키보드로 접근하자마자 페이지가 변경될 수 있기 때문에 그 이후의 콘텐츠 키보드 접근이 불가능해집니다. 이러한 점을 고려해서, 사용자가 의도하지 않은 기능이 실행되지 않도록 구현되어야 합니다.
 
 

3.2.1.3. 텍스트 입력란의 포커스 자동 변경과 기능 실행

텍스트 입력란의 포커스 자동 실행이란 텍스트 자릿수가 정해져 있는 주민등록번호와 같은 칸을 입력할 때, 앞자리 6개를 입력하고 나면 자동으로 다음 텍스트 입력란으로 포커스가 이동하는 것을 말합니다. 시각 장애 환경에서는 포커스가 변경됐다는 사실을 알 수가 없습니다.
 
 
  • 준수 사례
1) 텍스트 입력란에 지정된 자릿수의 값을 모두 입력한 후에도 포커스가 이동하지 않습니다.
2) 입력 서식 포커스란에는 사용자가 키보드의 탭 키 혹은 방향 키를 입력할 때에만 이동이 가능합니다.
3) 사용자 편의를 위하여 이전의 텍스트 입력란으로 포커스를 이동하였을 때 다시 다음 텍스트로 이동하지 않게끔 합니다.
예시) 아래와 같은 사진일 때, 인증번호 첫 번째 칸을 모두 작성해도 옆자리인 2번째 칸으로 이동하지 않습니다.
 
notion imagenotion image
사업자등록번호 <input type="text" name="reg_no1" onKeyUp="javascript:auto_next_focus( this, 3, "reg_no2" );"> - <input type="text" name="reg_no2" onKeyUp="javascript:auto_next_focus( this, 2, "reg_no3" );"> - <input type="password" name="reg_no3" > <input type="image" src="" alt="확인">
 
  • 오류 사례
1) 텍스트 입력란에 지정되어 있는 자릿수 값을 입력하면 다음 포커스가 텍스트 입력란으로 자동으로 이동합니다.
2) 포커스가 자동으로 이동한 후에 이전 텍스트 입력란으로 포커스가 다시 이동할 수 없습니다.
 
notion imagenotion image
 
<label for="sort_option">조회기간:</label> <select id="sort_option"> <option value="1" selected="selected">최근 3개월</option> <option value="2">최근 6개월</option> </select> <input type="submit" value="이동" />
 
 

3.2.1.4. 입력 서식 값 자동 전송

입력 서식 값 자동 전송이란 선택 목록 값을 선택하거나 변경하기만 해도 선택된 값이 전송되거나 페이지가 이동하는 것을 말합니다. 시각 장애 환경에서는 전송 기능을 실행하기 전의 화면 변화를 인식할 수 없으며, 값을 선택한 것만으로 페이지가 변경되면 혼란스러울 수 있습니다.
사용자가 콤보 박스나 체크 상자 등을 선택했을 때 기능이 바로 실행되어선 안됩니다. 이를 준수하기 위해선 제출 버튼을 따로 제공하여 체크한 후, 제출 버튼을 따로 눌러줘야 팝업이 닫히게끔 구현하여야 합니다.
 
notion imagenotion image
 
  • 준수 사례
입력 서식 값을 선택하거나 변경했을 때 값을 전송하거나 페이지가 이동했을 때 상당히 당황스러울 것입니다. 때문에 입력 서식은 제출 버튼을 눌렀을 때 실행되어야 합니다.
ex) querySelector() 는 선택한 라디오 버튼을 가져오는 메서드입니다. Email, Phone, Mail 중 하나를 선택하고 Submit 버튼을 눌러야 창을 나갈 수 있습니다.
 
<html> <body> <div id="container"> <p>Select your preferred contact method:</p> <div> <input type="radio" id="email" name="contact" value="email"> <label for="email">Email</label> <input type="radio" id="phone" name="contact" value="phone"> <label for="phone">Phone</label> <input type="radio" id="mail" name="contact" value="mail"> <label for="mail">Mail</label> </div> <button id="submit">Submit</button> </div> </body> </html>
document.getElementById('submit').onclick = function() { var radio = document.querySelector('input[type=radio][name=contact]:checked'); if (radio.value === 'email') { alert('Email is selected'); } }
출처 : https://lynmp.com/en/article/em811c9dc5o4
 

3.3. 콘텐츠의 논리성

3.3.1. [검사항목19] 콘텐츠의 선형 구조

: 콘텐츠는 논리적인 순서로 제공해야 한다.
 
여러분은 웹사이트에 회원 가입을 해 본 경험이 있으신가요? 회원 가입을 할 때를 한 번 떠올려봅시다. 먼저 아이디, 비밀번호, 개인정보 등 가입에 필요한 항목을 확인하고, 정보를 입력한 후 가장 하단에 있는 ‘가입하기’ 버튼을 눌러 가입을 진행합니다. 이와 마찬가지로 설문 조사를 하거나, 물건을 결제할 때도 필요한 정보를 순차적으로 입력한 후, 마지막으로 ‘완료’ 버튼을 눌러 기능을 마무리합니다. 이처럼 우리가 평소에 사용하는 대부분의 기능은 논리적인 순서를 보장하여 구현되어 있습니다.
그렇다면 ‘가입하기’ 버튼이 페이지의 최상단에 있다고 가정해 봅시다. 물론 불편하기는 하겠지만 스크롤을 움직여 쉽게 버튼을 찾아 다음 단계로 이동할 수 있을 것입니다. 하지만 시각 장애를 가진 사용자는 어떨까요? 시각 장애를 가진 사용자의 경우 스크린 리더, 점자 정보 단말기와 같은 보조 기구를 이용하여 HTML 요소들에 유형과 선언 순서에 따라 순차적으로 접근합니다. 따라서 버튼이 최상단에 위치한다면 입력했던 항목들을 다시 지나 ‘가입하기’ 버튼에 접근해야 하기 때문에 많은 시간이 소요됩니다. 만약 버튼이 ‘가입하기’가 아닌 ‘완료’로 작성되어 있었다면 사용자는 해당 버튼이 가입을 완료하는 버튼인지 인지할 수 없을 것입니다.
따라서 우리는 사용자가 웹 콘텐츠의 의미를 그 자체로 이해하고, 기능을 올바르게 사용할 수 있도록 논리적인 순서를 보장해야 합니다. 즉, 스타일링 없이 마크업만으로 웹콘텐츠를 이해할 수 있어야 합니다. 웹 접근성 실태 조사 보고서에 따르면 콘텐츠의 논리성의 준수율은 95.7%로 높은 편에 속합니다. 하지만 시각적인 배치에 따라 코드를 작성하여 기능의 논리성을 지키지 못하는 경우도 있습니다. 어떤 상황이 있는지 알아보고, 코드를 올바르게 작성하는 방법에 대해 알아보겠습니다.
 
 
1. 전후 맥락
1-1. 기능의 순서
notion imagenotion image
<label for="id">아이디</label> <input type="text" id="id" /> <label for="pw">비밀번호</label> <input type="text" id="pw" /> <label for="pw">비밀번호 확인 </label> <input type="text" id="pw" /> ... <button>가입하기</button>
사용자가 기능을 이해하기 쉽도록 기능을 처리하는 논리적인 순서에 따라 요소를 배치합니다.
 
1-2. 더보기
예시) 이달의 행사 및 축제 (출처: 서울시청)예시) 이달의 행사 및 축제 (출처: 서울시청)
예시) 이달의 행사 및 축제 (출처: 서울시청)
‘더보기’는 공지사항과 같은 게시판에서 쉽게 찾아볼 수 있습니다. 위의 예시처럼 제목 옆에는 ‘더보기’ 링크를, 하단에는 글 목록을 배치하는 경우가 많습니다. 이 순서를 고려하여 마크업을 작성해 보겠습니다.
 
  • 오류 사례
    • 제목, 더보기, 글 목록 순으로 마크업을 작성하는 경우
<section class="board-festival"> <h2>이달의 행사 및 축제</h2> <a href="..." class="more"><img src="more.png" alt="더보기"/ ></a> <ul> <li> <p>문화</p> <a href="...">'책 읽는 서울광장' 육아정보 프로그램</a> </li> <li> <p>환경</p> <a href="...">서울의 공원에서 '나만의 쉼표'를 찾아보세요!</a> </li> ... </ul> </section>
더보기 - 오류 사례 실행 결과더보기 - 오류 사례 실행 결과
더보기 - 오류 사례 실행 결과
콘텐츠의 논리성을 판단하기 위해 스타일 요소를 제외하고 마크업 결과를 살펴보겠습니다. 위의 경우 스크린 리더는 제목인 ‘이달의 행사 및 축제’를 읽은 후 바로 ‘더보기’ 링크를 읽게 됩니다. 따라서 시각 장애 환경의 사용자는 어떤 내용이 있는지 알지 못하고 ‘더보기’ 링크를 마주하게 됩니다. 우리가 게시판을 확인하는 순서를 다시 생각해 봅시다. 먼저 제목을 확인하고, 해당하는 내용을 살펴 본 후, 필요한 내용이 없는 경우 ‘더보기’ 링크로 이동하여 추가적인 내용을 확인합니다. 우리는 이러한 기능의 논리적인 순서를 지켜서 제목, 글 목록, 더보기 링크 순으로 마크업을 작성해야 합니다.
 
  • 준수 사례
    • 제목, 내용, 더보기 순으로 마크업을 작성
<section class="board-festival"> <h2>이달의 행사 및 축제</h2> <ul> <li> <p>문화</p> <a href="...">'책 읽는 서울광장' 육아정보 프로그램</a> </li> <li> <p>환경</p> <a href="...">서울의 공원에서 '나만의 쉼표'를 찾아보세요!</a> </li> ... </ul> <a href="..." class="more"><img src="more.png" alt="더보기"/ ></a> </section>
더보기 - 준수 사례 실행 결과더보기 - 준수 사례 실행 결과
더보기 - 준수 사례 실행 결과
 
 
2. 메뉴 항목
웹사이트는 다양한 메뉴를 제공하고 있습니다. 여러가지 메뉴를 탭 메뉴로 묶거나, 상위-하위의 관계로 메뉴를 나타내기도 합니다. 이 때 메뉴와 콘텐츠를 연결지어 제공하지 못하여 논리성을 위배하는 경우가 있습니다.
 
2-1. 탭 메뉴
예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)
예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)
위와 같이 여러 메뉴를 탭으로 묶어 나타내는 것을 탭 메뉴라고 합니다. 선택한 메뉴에 따라 내용 부분이 바뀌면서 메뉴에 해당하는 내용을 보여주게 됩니다. 탭 메뉴를 리스트 요소로 작성한다면 어떤 문제가 있을까요?
 
  • 오류 사례
<ul> <li><a href="...">베스트</a></li> <li><a href="...">패션잡화</a></li> <li><a href="...">가구/인테리어</a></li> </ul> <div>상품 정보</div> <div>상품 정보</div> <div>상품 정보</div>
notion imagenotion image
 
위와 같이 메뉴를 리스트로 묶고, 내용을 하단에 작성하게 되면 스크린 리더가 상품 정보( <div> 상품 정보 </div>)를 출력했을 때, 해당 상품들이 베스트 상품인지 패션잡화에 해당하는 상품인지 알기 어렵습니다. 따라서 내용이 어떤 메뉴의 내용인지 알 수 있도록 코드를 작성해야 합니다.
 
  • 준수 사례
1) 메뉴와 내용을 순차적으로 제공
첫 번째 해결 방법은 메뉴와 내용을 순차적으로 제공하는 것입니다.
<a href="...">베스트</a> <div>상품 정보</div> <a href="...">패션잡화</a> <div>상품 정보</div> <a href="...">가구/인테리어</a> <div>상품 정보</div>
2) 내용 항목에 제목을 입력
예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)
예시) 우당탕탕 라이캣의 실험실 (출처 : https://smartstore.naver.com/weniv_store)
또 다른 해결 방법으로는 예시 화면처럼 내용을 출력할 때 메뉴를 제목으로 함께 출력하는 것입니다. 이 경우 사용자는 메뉴를 전체적으로 확인한 후, 각 메뉴에 해당하는 내용이 무엇인지 연결지어 이해할 수 있습니다.
<ul> <li><a href="...">베스트</a></li> <li><a href="...">패션잡화</a></li> ... </ul> <div> <h2>베스트</h2> 상품 정보 </div> <div> <h2>패션잡화</h2> 상품 정보 </div>
 
추가적으로 ir 기법을 이용하여, 제목 요소가 출력되지 않도록 할 수 있습니다. 결과가 오류 사례와 동일해 보이지만, 스크린 리더가 <h2> 태그 안의 메뉴를 읽어주기 때문에 사용자는 메뉴와 내용을 연결지을 수 있습니다.
<ul> <li><a href="...">베스트</a></li> <li><a href="...">패션잡화</a></li> ... </ul> <div> <h2 class="txt-hide">베스트</h2> 상품 정보 </div> <div> <h2 class="txt-hide">패션잡화</h2> 상품 정보 </div>
notion imagenotion image
 
2-2. 중첩 메뉴
notion imagenotion image
중첩 메뉴는 상위 메뉴와 하위 메뉴로 이뤄져 있습니다. 탭 메뉴와 마찬가지로 하위 메뉴들이 어떤 상위 메뉴에 속하는지를 명시하여, 메뉴 간의 관계를 이해할 수 있도록 코드를 작성해야 합니다.
 
  • 오류 사례
<ol class="mainChapter"> <li><a href="...">인식의 용이성</a></li> <li><a href="...">운용의 용이성</a></li> <li><a href="...">이해의 용이성</a></li> <li><a href="...">견고성</a></li> </ol> <ol class="subChapter"> <li><a href="...">대체 택스트 제공</a></li> <li><a href="...">멀티미디어 대체 수단</a></li> <li><a href="...">명료성</a></li> </ol>
위와 같이 상위 메뉴와 하위 메뉴를 나눠 코드를 작성하면 계층 관계를 파악하기 어렵습니다.
 
  • 준수 사례
<ol class="mainChapter"> <li> <a href="...">인식의 용이성</a> <ol class="subChapter"> <li><a href="...">대체 택스트 제공</a></li> <li><a href="...">멀티미디어 대체 수단</a></li> <li><a href="...">명료성</a></li> </ol> </li> <li><a href="...">운용의 용이성</a></li> ... </ol>
상위 메뉴와 하위 메뉴 간의 계층 관계를 쉽게 이해할 수 있도록 상위 메뉴에 하위 메뉴 항목을 넣어 작성합니다.
 

3.3.2. [검사항목20] 표의 구성

: 표는 이해하기 쉽게 구성해야 한다.
테이블을 이용하면 자료들 간의 논리적인 관계를 나타낼 수 있습니다. 웹 페이지에서는 테이블을 나타내기 위해서 <table> 요소를 사용합니다. 올바른 테이블을 작성하는 방법에 대해 들어가기 앞서 <table>에는 어떤 요소들이 있는지 간단하게 살펴보겠습니다.
notion imagenotion image
<table> <caption> <strong>웹접근성 집필 관리</strong> <span>챕터 담당 인원과 진행 상태 정보를 제공하는 표 입니다.</span> </caption> <thead> <tr> <th scope="col">번호</th> <th scope="col">챕터명</th> <th scope="col">담당 인원</th> <th scope="col">진행 상태</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>웹접근성의 이해</td> <td>2명</td> <td>완료</td> </tr> <tr> <td>2</td> <td>웹접근성 기본 4원칙</td> <td>10명</td> <td>진행 중</td> </tr> </tbody> <tfoot> <tr> <th colspan="2">총 인원</th> <td>14명</td> </tr> </tfoot> </table>
 
다음으로는 스크린 리더 환경에서도 데이터의 관계를 쉽게 이해할 수 있는 올바른 데이터 테이블을 작성하기 위해 지켜야할 항목들을 알아보겠습니다.
 
1. 테이블의 제목과 요약정보
사용자가 테이블에 대해 쉽게 이해할 수 있도록 제목과 요약 정보를 제공해야 합니다. 제목은 <caption> 태그를 사용합니다. <caption> 태그를 사용하는 경우 사용자가 표를 읽을지, 넘어갈지도 결정할 수 있습니다.
요약정보는 <table>summary 속성으로 작성합니다. 주의해야 할 점은 HTML Living Standard에서는 summary 속성을 더 이상 제공하지 않는다는 것 입니다. 따라서 <caption> 요소 안에 제목과 요약정보를 제공합니다.
<!-- HTML Living Standard --> <table> <caption> <strong>웹접근성 집필 관리</strong> <span>챕터 담당 인원과 진행 상태 정보를 제공하는 표 입니다.</span> </caption> ... </table> <!-- HTML4, XHTML --> <table summary = "챕터 담당 인원과 진행 상태 정보를 제공하는 표 입니다."> <caption> <strong>웹접근성 집필 관리</strong> <span>챕터 담당 인원과 진행 상태 정보를 제공하는 표 입니다.</span> </caption> ... </table>
 
2. 제목과 내용 구분
제목은 <th>로, 내용은 <td>로 작성하여 구분합니다. 테이블에서 <thead>는 기본적으로 열 제목 속성으로 작성됩니다. 제목 열의 방향은 <th>scope 속성을 이용하여 변경할 수 있습니다. 열 제목의 경우 col을, 행 제목의 경우 row 를 주어 방향을 설정할 수 있습니다.
notion imagenotion image
<table> <caption> <strong>이번주 날씨 정보</strong> </caption> <thead> <tr> <th></th> <th scope="col">월요일</th> <th scope="col">화요일</th> <th scope="col">수요일</th> </tr> </thead> <tbody> <tr> <th scope="row">날씨</th> <td>비옴</td> <td>흐림</td> <td>맑음</td> </tr> <tr> <th scope="row">습도</th> <td>높음</td> <td>적당함</td> <td>낮음</td> </tr> </tbody> </table>
 
3. 복잡한 표의 경우 headers, id 속성을 이용
notion imagenotion image
<table> <caption> <strong>202X년 부서별 입퇴사자 관리</strong> </caption> <thead> <tr> <th rowspan="2" scope="col" id="depart">부서명</th> <th colspan="2" scope="col" id="employee">입퇴사 정보</th> </tr> <tr> <th scope="col" id="entrant">입사 인원</th> <th scope="col" id="retiree">퇴사 인원</th> </tr> </thead> <tbody> <tr> <th scope="row" id="develop">개발팀</th> <td headers="depart develop employee entrant">2</td> <td headers="depart develop employee retiree">4</td> </tr> <tr> <th scope="row" id="design">디자인팀</th> <td headers="depart design employee entrant">3</td> <td headers="depart develop employee retiree">2</td> </tr> </tbody> </table>
rowspancolspan 속성을 통해 다단, 병합 등을 사용하는 복잡한 표의 경우에는 headersid 속성을 사용하여 데이터 간의 관계를 명시합니다. 제목 셀에 id 값을 주고, 내용 셀의 headers에 연관된 제목 셀의 id를 나열합니다. 스크린 리더는 headers에 명시된 id에 해당하는 값을 순서대로 읽어줍니다. 따라서 디자인 팀의 입사자 수는 “3”이 아닌 “부서명 디자인팀 입사인원 3”으로 읽어 사용자가 데이터 간의 관계를 쉽게 이해할 수 있습니다.
 
지금까지 데이터를 다루는 테이블인 데이터 테이블을 올바르게 작성하는 법에 대해 알아보았습니다. <table> 요소는 보통 데이터를 다루기 위해 사용되지만, 격자형 레이아웃을 만들기 위하여 사용하는 경우도 있습니다. 이를 레이아웃 테이블 또는 배치 테이블이라고 합니다.
 
레이아웃 테이블
예시) 영화 정보 (출처 : 다음)예시) 영화 정보 (출처 : 다음)
예시) 영화 정보 (출처 : 다음)
레이아웃을 위하여 위와 같은 자료를 <table> 요소로 사용한다고 가정해 봅시다. 어떤 문제가 발생할 수 있을까요? 보조 기기가 열과 행의 정보를 가져오거나, 콘텐츠 간의 관계를 인식하는데 혼란을 줄 수 있습니다. 따라서 격자 배치는 CSS 속성으로 컨트롤 해야 하며, 불가피하게 <table> 요소를 사용해야 하는 경우에는 데이터를 다루는데 사용되는 <caption>, <thead>, <th>를 사용하지 않아야 합니다.
 

3.4. 입력도움

3.4.1 [검사항목21] 레이블 제공

: 사용자 입력에는 대응하는 레이블을 제공해야 한다.
 
레이블은 ‘이것’을 위해 사용한다.
여러분은 심심찮게 라벨이 부착된 물건을 보셨을 거예요. 왜 라벨을 부착할까요?
실생활에서 볼 수 있는 라벨사용 (출처 : Unsplash)실생활에서 볼 수 있는 라벨사용 (출처 : Unsplash)
실생활에서 볼 수 있는 라벨사용 (출처 : Unsplash)
라벨은 상표나 품명을 통하여 식별이 가능 하게 하는, 하나의 배려로 볼 수 있습니다. 나는 알아도 다른 이는 사용 용도를 모를 수 있기 때문이죠. 웹 또한 마찬가지입니다. 웹에서 요소마다 식별이 가능한 라벨을 부착해 두었을 경우, 화면을 볼 수 없는 상황이 발생했더라도 스크린리더 혹은 점자 정보 단말기를 통해 용도의 인식이 가능합니다. 이러한 요소를 웹에서는 “레이블 태그”라고 합니다.
 
웹에서 사용하는 레이블은 이러한 것이 있다.
조금 더 느낌이 와닿을 수 있도록 예시를 살펴보겠습니다. 대표적인 예시는 아래와 같습니다.
앞서 말씀드린 내용을 이해하셨다면, 웹상에서 레이블 태그를 사용해야할 요소들이 조금은 생각이 나실수도 있습니다. 그러면 이제 생각 해본 예시들이 알맞은지, 본격적으로 웹에서 사용하는 레이블의 예시를 이미지를 통해 살펴보도록 하겠습니다.
 
네모 박스안에 입력되어지는 텍스트가 ‘이름’ 이라는 용도에 사용한다는 것을 인지할 수 있습니다.
 
네모 박스의 상태는 선택이 되었을 때와 그렇지 않았을 때로 나눌 수 있으며, 위 이미지처럼 다중 선택이 가능합니다. 우리는 이러한 수많은 선택 사항중 여러개 선택가능 하도록 하는 것을 체크박스 라고 부릅니다. 이러한 체크 박스가 텍스트를 선택하는 것에 있어 제어하는 용도로 사용된다는 것을 인지할 수 있습니다.
 
‘네이버페이’ 와 ‘신용카드’ 설정된 두 가지의 선택 중 하나만을 고를 수 있도록 설정되어 있습니다. 우리는 이렇게 미리 정의된 다수 선택 사항의 모임 중 단 하나만 선택할 수 있게 하는 버튼을 라디오 버튼 이라고 부릅니다. 이러한 라디오 버튼이 텍스트를 제어하는 용도로 사용된다는 것을 인지할 수 있습니다.
 
네모 박스안에 입력되어진 ‘abcd’ 가, 박스 우측에 보여지는 눈 모양 아이콘을 누르게 되면 내용을 확인할 수 없게 점으로 바뀌어보입니다. 우리는 이러한 미리 정의된 두가지 선택 사항의 모임 중 단 하나만 선택할 수 있게하는 버튼을 토글 버튼 이라고 부릅니다. 이러한 토글 버튼이 네모 박스 창 안의 텍스트를 제어하는 용도로 사용된다는 것을 인지할 수 있습니다.
 
레이블 태그는 어떻게 사용하는 것일까?
레이블 태그는 쉽게 말해,input 혹은 selector 태그를 제어 하면서 조금 더 나은 사용자 경험을 제공하고자 나타난 태그라고 생각하시면 됩니다. 레이블 태그의 사용 방법과 유형을 예시와 코드를 통해 간략하게 살펴보겠습니다.
 
<label> 태그의 형제 요소가 input 혹은 selector 태그인 경우 먼저 설명해 드리겠습니다. <label for=""> <태그 id=""> 를 동일하게 맞춰 주어서 레이블 태그와 입력 서식과의 관계를 명확히 알 수 있게끔 해 줍니다. 아래의 코드를 보면 직관적으로 이해가 가실 겁니다.
<label for="userId">likelion</label> <input type="text" id="userId" name="userId"/>
 
위에 설명한 것과는 조금 다른 예시를 보여드리겠습니다.
<form name="educationList"> <ul> <li> <input type="checkbox" id="option1"/><label for="option1">프론트엔드 스 쿨</label> </li> <li> <input type="checkbox" id="option2"/><label for="option2">백엔드 스쿨</label> </li> <li> <input type="checkbox" id="option3"/><label for="option3">앱 스쿨</label> </li> </ul> </form>
아까 본 코드와 다르게, input 태그와 label 태그의 서순이 바뀌어 있죠? 서순이 바뀌어서 달라졌다고 생각할 수도 있습니다. 이러한 경우는 단지 스크린리더가 읽을 경우, 무엇을 먼저 읽게끔 하냐 의 차이일 뿐 기능적인 측면으로는 크게 달라진 부분이 없습니다. 
 
자, 본론으로 돌아오겠습니다. 만약 li 태그가 많아진다면 우리는 고민할 것이 생기게 됩니다. 엄청난 수의 li 태그를 사용할 때, 비례하게 엄청난 수의 <label for=""><input id="">가 생기기 때문이죠. 이럴 경우 불필요한 코드를 간소화할 해결할 방법으로서, label 태그 안에 input 혹은 selector 태그를 위치시키는 방법이 존재합니다. 이 방법의 가장 큰 특징으로는 label 요소로 별도의 <label for=""> 을 설정할 필요가 없다는 겁니다. 자식 요소인 <input> 또는 <selector> 태그가 부모 요소인 <label>로 부터 상속받기 때문에 별도로 관계를 연결할 필요가 없기 때문입니다. 이렇게 된다면 자연스럽게 불필요한 코드가 간소화되겠죠?<label for=""> 을 별도로 설정하지 않아도 되는 이유로는 자식 요소 input 혹은 selector 태그는 부모 요소인 label 태그로부터 상속받고 있기 때문에 별도로 관계를 연결할 필요가 없기 때문입니다. 체크박스를 구현한 아래 코드를 보시면 이해가 쉬울 것으로 예상됩니다.
 
<form name="educationList"> <ul> <li> <label><input type="checkbox" />프론트엔드 스쿨</label> </li> <li> <label><input type="checkbox" />AI 스쿨</label> </li> <li> <label><input type="checkbox" />스타트업 스쿨</label> </li> <li> <label><input type="checkbox" />앱 스쿨</label> </li> </ul> </form>
위 코드를 보시면, label 태그가 input 요소를 감싸고 있는 부분을 직관적으로 확인하실 수 있습니다. 이를 보고 우리는 레이블을 클릭하면 체크박스가 반응을 한다는 것을 머리로 상상하고 받아들일 수 있습니다.
 
실제 운영하는 사이트에서 사용하는 레이블을 코드를 뜯어보자.
  • <label for=""><input id=""> 일치 예시
<input type="checkbox" id="checkboox-check_all" class="inp_choice" name="check_all" value="true"> <label class="lab_choice" for="checkboox-check_all"><span class="ico_comm ico_check"></span>모두 동의합니다.</label>
위 이미지에 적용된 HTML 코드
위에서 제공한 사진을 보면, 각 영역이 초록색과 파란색으로 표시되어 있습니다. 체크박스를 누르지 않고, 레이블안에 설정된 텍스트를 눌러도 label 의 for 속성과 input 의 id 속성이 일치하기 때문에 체크박스가 반응을 하는것을 알 수 있는 코드입니다.
 
  • 동일한 <label for=""><input id=""> 사용하여 여러 개의 유사한 입력 서식 그룹핑
로그인 UI(출처 : 포털사이트 ‘NATE’)로그인 UI(출처 : 포털사이트 ‘NATE’)
로그인 UI(출처 : 포털사이트 ‘NATE’)
<label for="ID" class="label_id nHide">아이디 or @이하 모두 입력</label> <input type="text" id="ID" name="ID" class="input_id" title="아이디 or @이하 모두 입력" style="ime-mode:disabled;" value="" autocomplete="off"> <label for="PASSDM" class="label_pw nHide">비밀번호</label> <label for="PASSDM" id="lb_passdm" class="label_pw nHide">비밀번호</label> <input type="text" name="PASSDM" id="PASSDM" value="비밀번호" maxlength="20" class="input_pw" readonly="readonly"> <label for="PASSWD" id="lb_passwd" class="label_pw nHide">비밀번호</label> <input type="password" name="PASSWD" id="PASSWD" class="input_pw" maxlength="20" style="display:none;ime-mode:disabled;" onblur="vBlurPassInput();" enc="on" autocomplete="off">
위 이미지에 적용된 HTML 코드
<label for="PASSDM"><input id="PASSDM"> 을 사용하여, 2개의 label 중 어떠한 것을 클릭하더라도 하나의 input 이 컨트롤이 되도록 설정되어 있습니다. 이러한 유사한 서식을 그룹핑 한 모습을 위 코드에서 확인이 가능합니다.
 

3.4.2 [검사항목22] 오류 정정

: 입력 오류를 정정할 수 있는 방법을 제공해야 한다.
 
입력 오류를 정정할 방안을 제시해야 한다.
내용설명에 앞서, 여러분이 병원에 간다고 하셨을 때 가장 먼저 하시는 일이 무엇일까요? 먼저 접수를 하기 위해서 인적 사항을 기입하고, 안내데스크 쪽으로 향해야 합니다. 그 후, 인적 사항을 기재한 용지를 제출했다고 칩시다. 여러분은 혹시 안내원이 용지를 받고 아무 말 없이 용지를 다시 건네주신 경험이 있으신가요?
안내데스크에서 발생하는 소통 속 오류정정 (출처 : Unsplash)안내데스크에서 발생하는 소통 속 오류정정 (출처 : Unsplash)
안내데스크에서 발생하는 소통 속 오류정정 (출처 : Unsplash)
아마 일반적인 경우에는 어느 부분에 수정을 요구하거나, 추가로 작성을 해 달라고 요구해 주는 방향이 자연스러울 것입니다. 이러한 요구를 하지 않는다면 어떻게 될까요. 안내원 입장에서는 일 처리에 있어서 지연되는 느낌을 받을 것이며, 사용자 입장에서는 잘못된 부분을 인지하기 힘들어 답답해하며 안내원이 불친절하다고 느낄 겁니다. 웹 또한 마찬가지입니다. 오히려 소통이 불가능하니 더욱더 그렇게 생각하실 수 있습니다. 특히나 화면을 볼 수 없는 상황이라면요. 이러한 불상사를 막기 위해, 입력 오류를 정정할 방안을 제시해야 합니다. 또한 정정 방안을 제시하는 경우에는 화면을 보지 못하는 사용자도 인지할 수 있도록, 스크린 리더가 읽을 수 있는 텍스트로 명확히 표현해 주는 것이 좋습니다.
 
웹에서 볼 수 있는 오류 정정 방법은 이러한 것들이 있습니다.
앞서 간략하게 오류 정정 방법의 필요성과 관련하여 설명을 드렸습니다. 이제 오류 정정 방법의 필요성을 아셨다면, 웹에서는 어떤 형식으로 정정 방법들이 존재하는지 살펴보도록 하겠습니다. 이해를 돕기위해 이미지를 활용하여 설명드리겠습니다.
 
입력 시 갖추어야 할 조건을 보여줌으로써, 오류 정정할 방법을 제시해 주고 있습니다. 붉은 계열을 통해 사용자가 오류를 인식한다는 점을 활용하여 더욱 명확하게 오류 정정 방안을 인식할 수 있게 해주는 점도 보입니다.
 
텍스트 입력창에 정보를 입력 후, 로그인 버튼을 누르면, 오류가 생겼을 경우에는 첫번째 이미지와 같이 경고창이 나타납니다. 이때 확인을 누르게 되면 두번째 이미지와 같이, 아이디 입력창에 포커싱되는 모습을 볼 수 있어요.
 
위의 예시 외에도 많은 곳에서 오류 정정을 할 수 있는 여러 방안을 볼 수 있습니다. 그럼 조심하거나 지양해야 할 오류 정정 방법 제시를 이야기해 보겠습니다.
 
지양해야 할 오류 정정 방법 제시안에 대해 살펴보자.
앞서 살펴보았던 내용을 토대로, 사용자들에게 입력 오류에 관련하여 정정할 방법을 제시할때 주의해야할 사항을 간략화 하여 리스트로 적어봤습니다.
  • 아무 반응 없이 창이 그대로일 경우
  • 오류가 발생한 지점을 포커싱 해주지 않았을 경우
  • 오류 안내 텍스트가 불명확할 경우
  • 작성한 모든 내용이 초기화되었을 경우
위와 같은 주의사항을 인지한다면, 더 나은 경험을 사용자들에게 자연스럽게 제공할 수 있을 것이라 생각합니다. 또한 사용자의 흐름이 어떤 식으로 진행되는지를 잘 파악한 후, 오류를 정정할 방법을 제시한다면 사용자들은 더욱 만족감을 느낄 수 있으실 겁니다.