main-logo

실전 웹 접근성 마크 획득

접근성 마크를 획득하면서 더욱 주의해야 할 점

profile
TY
2025년 12월 25일 · 0 분 소요

들어가며

그동안 접근성에 관련하여 체크리스트적용 사례 그리고, 자가진단을 공유하였습니다.

웹 표준을 준수하고, 논리적인 마크업과 기능 구현을 하게 된다면 대부분의 접근성 관련한 항목은 신경쓰지 않아도 될 정도로 지켜지게 되는데요. 그럼에도 불구하고 작업 중 실수도 발생할 수 있고 미처 신경쓰지 못하는 부분도 있기 마련입니다.

더불어 현재 진행하고 있는 프로젝트는 매년 접근성 인증마크를 갱신하고 있긴 하나 굉장히 오래되고 규모가 큰 사이트로서 아무리 기존에 잘 운영해왔던 사이트라 하여도 문제가 되는 부분은 많을거라 생각이 되었습니다.

이번에 프로젝트의 PL이 되면서 25년도 접근성 인증마크 갱신을 진행 하면서 경험한 실무에서의 주의할 점과 좀 더 신경써야 할 부분을 정리해 보았습니다.

 

role="tab" 사용 시 키보드 탐색 처리


탭 메뉴를 구현할 때 흔히 사용되는 role="tab" 속성은 단순히 클릭 이벤트만으로 끝나지 않습니다.

방향키로 각 탭 메뉴를 탐색할 수 있도록 처리해야 하며, tab 키로는 탭 메뉴가 아닌 탭 컨텐츠 영역으로 초점이 이동해야 합니다.

이번 심사에서 role="tab"이  사용된 탭메뉴였으나 방향키로 탭 메뉴 탐색이 불가하여 오류 판정을 받았었습니다. 실제 코드를 봤을때는 WAI-ARIA와 함께 마크업 구조나 접근성 처리들이 매우 잘 되어 있던 영역이었으나 방향키로 메뉴를 탐색할 수 있는 기능이 누락되어 있었던게 발견 되었습니다.

아마도 ARIA나 역할, 구조적으로 접근성을 준수하였으나 탭 메뉴에는 방향키 조작이 필요하단 부분을 미처 생각하지 못했었던거 같습니다.

다음은 예시 코드 입니다.

<!-- 탭 리스트 -->
<div role="tablist" aria-label="사이트 주요 탭" class="tablist">
  <button
    role="tab"
    id="tab-home"
    aria-controls="panel-home"
    aria-selected="true"
    tabindex="0"
    class="tab"
  >
    소개
  </button>
  <button
    role="tab"
    id="tab-products"
    aria-controls="panel-products"
    aria-selected="false"
    tabindex="-1"
    class="tab"
  >
    서비스
  </button>
  <button
    role="tab"
    id="tab-contact"
    aria-controls="panel-contact"
    aria-selected="false"
    tabindex="-1"
    class="tab"
  >
    문의
  </button>
</div>

<!-- 탭 콘텐츠 패널 -->
<div role="tabpanel" id="panel-home" aria-labelledby="tab-home" tabindex="0" class="tabpanel">
  <h2>회사 소개</h2>
  <p>
    우리 회사는 혁신적인 웹 솔루션을 제공하는 국내 최고의 기업입니다. 전문 개발자들이 모여
    사용자 경험 중심의 서비스를 만듭니다.
  </p>
</div>
<div
  role="tabpanel"
  id="panel-products"
  aria-labelledby="tab-products"
  tabindex="0"
  class="tabpanel"
  hidden
>
  <h2>서비스 안내</h2>
  <ul>
    <li>웹사이트 퍼블리싱 서비스</li>
    <li>React 기반 웹 애플리케이션 개발</li>
    <li>접근성 인증 컨설팅</li>
  </ul>
</div>
<div
  role="tabpanel"
  id="panel-contact"
  aria-labelledby="tab-contact"
  tabindex="0"
  class="tabpanel"
  hidden
>
  <h2>고객 문의</h2>
  <p>이메일: support@example.com</p>
  <p>전화: 02-1234-5678</p>
</div>
const tablist = document.querySelector('[role="tablist"]');
const tabs = Array.from(tablist.querySelectorAll('[role="tab"]'));
const panels = Array.from(document.querySelectorAll('[role="tabpanel"]'));

// 키보드 탐색 핸들러
tabs.forEach((tab, idx) => {
  tab.addEventListener('keydown', (e) => {
    let newIdx = idx;
    switch (e.key) {
      case 'ArrowRight':
        newIdx = (idx + 1) % tabs.length;
        break;
      case 'ArrowLeft':
        newIdx = (idx - 1 + tabs.length) % tabs.length;
        break;
      case 'Home':
        newIdx = 0;
        break;
      case 'End':
        newIdx = tabs.length - 1;
        break;
      case 'Tab':
        // 기본 Tab 동작으로 포커스가 탭 콘텐츠로 이동
        return;
      default:
        return;
    }
    e.preventDefault();
    tabs[newIdx].focus();
  });

  // 클릭 또는 Enter/Space 로 선택 처리
  tab.addEventListener('click', () => activateTab(idx));
  tab.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      activateTab(idx);
    }
  });
});

function activateTab(activeIdx) {
  tabs.forEach((t, i) => {
    const sel = i === activeIdx;
    t.setAttribute('aria-selected', sel);
    t.setAttribute('tabindex', sel ? '0' : '-1');
    panels[i].hidden = !sel;
  });
  tabs[activeIdx].focus();
}

 

이처럼 탭 메뉴 사용시에는 키보드 방향키로 탐색이 가능해야 한다는걸 항상 생각해야 할 거 같습니다.

 

활성/비활성 상태에서의 title 누락


버튼이나 링크 등의 요소가 활성 또는 비활성 상태일 때 스크린 리더기를 사용하는 사용자를 위한 보조 텍스트(title 속성)를 누락하는 경우가 많습니다.

시각적 상태 변경뿐 아니라 접근성 측면에서도 반드시 상태에 따라 적절한 보조 텍스트를 제공하여야 합니다.

 

sample1.png

명확한 타이틀을 제공해야 한다

 

테이블 caption 내용 불일치


생각보다 흔하게 발생하는 오류였습니다.

보통 공통 테이블이나 비슷한 유형의 테이블 활용하여 복사, 붙혀넣기 식으로 작업을 하게되는 경우가 많은데요. 이때 복사했던 대상 테이블의 제목 역할을 하는 caption의 내용을 미처 수정하지 않아 실제 테이블의 데이터나 목적과 맞지 않아 오류로 발견되었습니다.

caption의 경우 시각적으로 보이지 않는 부분이다 보니 좀 더 꼼꼼하게 체크해야 하는 부분으로 여겨집니다.

<table>
  <caption>주문 내역</caption>  <!-- ❌ 실제 내용과 맞지 않음 -->
  <thead>
    <tr>
      <th scope="col">회원 ID</th>
      <th scope="col">이름</th>
      <th scope="col">가입일</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>u1001</td><td>홍길동</td><td>2025-01-15</td></tr>
    <tr><td>u1002</td><td>John Doe</td><td>2025-02-20</td></tr>
    <tr><td>u1003</td><td>김아무개</td><td>2025-03-05</td></tr>
  </tbody>
</table>

<table>
  <caption>회원 목록</caption>  <!-- ✔️ 데이터와 일치 -->
  <thead>
    <tr>
      <th scope="col">회원 ID</th>
      <th scope="col">이름</th>
      <th scope="col">가입일</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>u1001</td><td>홍길동</td><td>2025-01-15</td></tr>
    <tr><td>u1002</td><td>John Doe</td><td>2025-02-20</td></tr>
    <tr><td>u1003</td><td>김아무개</td><td>2025-03-05</td></tr>
  </tbody>
</table>

 

논리적 구조와 시각적 구조의 불일치


채팅 상담과 같은 부분에서 사용자가 입력창에 값을 입력 할 때 입력된 값을 기반으로 자동완성 되는 컨텐츠를 입력창 윗쪽에 노출하는 UI이고, 실제 HTML구조도 자동완성 컨텐츠 다음으로 입력창이 존재하는 어찌보면 시각적으로는 별 다른 문제가 없는 구조였습니다.

다만 실제 키보드로 탐색시 tab키로 자동완성 컨텐츠를 탐색하려면 shift + tab키를 눌러야 하는 번거로움이 있으며, 별다른 안내가 없다면 키보드 사용자들은 자동완성 기능을 활용하지 못하는 문제도 발생합니다.

그러므로 시각적으로 논리적인 구조로 되어 있다고 하여도 키보드 사용자를 위해 입력창 다음으로 자동완성 컨텐츠를 위치시켜 tab키 만으로도 자동완성 기능에 초점이동이 되도록 해야 합니다.

 

sample2.png

HTML의 위치에 주의하자

 

URL 파라미터에 따라 바뀌는 화면에서 #링크 예외처리 누락


단일 페이지 애플리케이션(SPA)이나 특정 파라미터에 따라 동적으로 화면을 구성한 페이지에서 URL에 앵커(#)를 사용하여 특정 컨텐츠로 바로 접근하는 경우나 '본문 바로가기'를 선택하여 URL에 #container가 추가되는 있습니다.

이때 이런 앵커에 대한 예외 처리가 누락되면 사용자가 원하는 컨텐츠로 직접 이동하지 못하게 되는 경우도 있고, 더 좋지 않은 상황에서는 페이지가 초기화 되거나 하는 경우가 발생하여 만약 스텝성 페이지를 탐색하는 키보드 사용자에게는 좋지 않은 사용자 경험을 주게 됩니다.

이번 프로젝트에서는 좀 더 심각한 증상으로 URL에 예상치 못한 파라미터나 값이 추가되면 화면의 컨텐츠가 사라져버려 더이상 화면을 조작 할 수 없는 증상이 발견되어 관련 로직을 수정하게 되었습니다. 

sample3.png

사이드 이펙트를 생각해서 오류를 미리 방지해야 한다

 

초점 이동 및 회귀


이 글을 쓰게된 결정적인 케이스 입니다.

동적으로 팝업이나 모달 창 등을 구현할 때 초점 이동과 동적으로 열려진 팝업이나 모달 창 등을 닫았을 시 초점의 원래 위치로의 회귀 처리가 누락되는 경우가 매우 많습니다.

팝업이나 모달이 닫힌 후에는 초점이 원래 있던 위치로 정확히 복귀하도록 구현해야 합니다. 이는 접근성 심사에서 매우 중요한 평가 항목이고 생각보다 많은 부분에서 초점 이동이나 회귀가 지켜지지 않았습니다.

이는 UI구현은 퍼블리싱 파트에서 구현하고, 기능적인 부분은 개발측에서 구현하는 예전 방식에서 흔하게 발생하는 오류로 생각 되므로 특히나 신경써서 확인해봐야 할 항목으로 생각 됩니다.

 

sample4.png

초점 이동에 항상 주의하자

 

마치며


실제로 이번 접근성 인증마크 갱신 심사에서도 7~80%의 오류건이 모두 초점이동이었습니다.

특히 초점이동의 경우 우리쪽에서 관리되는 로직이아닌 개발측에서 관리하고 있는 로직이 대부분이라 개발측과의 커뮤니케이션을 하며 개선을 하는 부분에서 많은 시간이 소요되었습니다.

초점 이동에 대한 부분 외에는 대부분 금새 해결이 가능하고, 그다지 많지 않은 오류건이어서 큰 문제가 되지 않았는데요. 초점이동의 경우 개발과 여러 서드파티 업체가 엮여 있어 수정 개선에 더욱 어려움이 많았던거 같습니다.

접근성 인증마크 신규 심사나 갱신을 앞두고 계신 분들이 있다면 제 글이 조금이라도 도움이 되었길 바라며 이 글을 마칩니다.