앱 접근성에서 중요한 역할인 초점 이동에 대해 글을 쓰려고 한다!
사실 우리 모두 접근성 접근성 하지만 시간에 쫓기다 보면 다 맞추지 못하고 작업을 하게 된다. 그리고 개발자의 경우는 접근성에 대해 지식이 더 부족하기 떄문에 각 태그가 가진 고유 기능을 활용하지 않고 유사 태그를 사용하여 접근성 위배가 되는 경우도 있다.
(이 부분은 개발자를 뭐라고 하는 것이 아닌, 관점 차이입니다. )
예시로 든다면 내가 담당한 앱에서는
뒤로가기 이동 버튼을 모~두 a 태그에 href는 아예 없는 상태로 onclick으로 기능을 제어하여 약 300페이지 가량을 모두 바꾸는 일이 있었다....
1️⃣ 링크(a)와 버튼(button)은 구분하여 사용하자
🤔 왜?
먼저, 링크와 버튼을 선택하여 스크린리더가 읽어줄때 다음과 같이 들린다.
요소 이름이 산토미 라고 가정했을 때
a: 산토미, 링크
button: 산토미, 버튼
의미부터 달라지기 때문에 사용하는 의도에 맞게 써야한다. (이게 접근성 위배가 되지는 않지만 그래도~)
이동을 하는 경우 <a> 사용
<a href="/detail" class="btn-like">상세보기</a>
링크이지만 기능을 써야하는 경우 <a>사용
<a href="/detail" class="btn-like" id="goDetail">상세보기</a>
/* onclick 기능 */
<script>
document.getElementById('goDetail').addEventListener('click', () => {
// 보조 동작 (예: analytics)
});
</script>
href는 반드시 둔다.
href="#"으로 사용하고 onclick으로 제어할 경우 role="button"을 붙인다.
쓰면 안되는 유형
<a onclick="openModal()">필터</a>
이동도 아니고 버튼도 아닌 너는 무엇?
이 경우 초점과 역할이 불명확하여 접근성에 위배된다.
2️⃣ tabindex, tab으로 이동할 수 있는 요소를 제어하는 속성
탭과 아코디언, 스와이퍼에서 많이 사용했다.
- 스와이퍼의 경우 이전/다음 슬라이드에 초점이 가지 않아야 한다.
<div role="tablist">
<button role="tab" aria-selected="true" tabindex="0">탭1</button>
<button role="tab" aria-selected="false" tabindex="-1">탭2</button>
</div>
이런 식으로 초점이동이 되지 말아야 하는 곳에 -1을 사용한다.
3️⃣ focusable: 초점 가넝한 요소 만들기
1과 관련된 내용이다.
일단 focusable이 되지 않는 케이스를 살펴보겠다.
case1. 가야하는 데 갈 수가 없어요
<a onclick="open()">열기</a>
<a>에 onclick만 있을 시 링크로 취급되지 않기 때문에 초점 이동이 되지 않는다.
불가피하게 이렇게 써야 할 경우 role="button"을 넣어준다.
<div onclick="open()">열기</div>
이런 경우도 있지... 왜 이렇게 쓰는지 모르겠지만 있다.. 있을거다.. role과 tabindex를 넣어주자
참 잘했어요!
<button type="button" class="btn" onclick="open()">열기</button>
이렇게 마크업 해주시면 안되는걸끼니?
case2. 가지말라고 했는데 말 안듣고 꼭 가는 것들이 있어
<style>
.drawer.is-closed { opacity: 0; height: 0; }
</style>
<div class="drawer is-closed">
<a href="/x">닫기</a>
</div>
이 경우 요소가 있다고 인식하기 때문에 display:none 으로 처리하거나 컨트롤하는 화면이라면 tabindex="-1"으로 제어한다.

현재 Slide 1에 active가 되어 있는 상태. 그 다음 (또는 이전) 슬라이드에 초점이 가지 않게 하려면 나머지 슬라이드에 대해 tabindex="-1"를 설정한다. 필요 시 aria-hidden="true"도 같이 해준다.
case3. 왔는데 뭐가 없어
<button type="button" class="icon-btn">
<span class="icon-search"></span>
</button>
뭐가 없을까요? 레이블이 없습니다.
버튼이라고는 하지만 버튼의 용도를 알 수가 없다. 이 경우 접근성에 위배된다. aria-label="검색" 이라는 문구를 넣거나 span안에 의미를 적어준다.
이렇게요.
<!-- aria 속성 사용 -->
<button type="button" class="icon-btn" aria-label="검색">
<span class="icon-search" aria-hidden="true"></span>
</button>
<!-- 스크린 리더 스타일 사용 -->
<button type="button" class="icon-btn">
<span class="icon-search" aria-hidden="true"></span>
<span class="sr-only">검색</span>
</button>
이렇게 했는데도 초점이 안가는 경우가 있다.
*:focus { outline: none; }

:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
꼭 요렇게 outline을 넣어주자!
4️⃣ 김대리님,,, 모달에서 초점 이동이 하고 싶어요,,,,
5️⃣ 스와이퍼에서 보이지 않는 슬라이드에 초점이동이 안가게 하기(이거 너무 중요해서 알려주고 싶어 미칠 지경)
6️⃣ aria 없이 못살아
7️⃣ 안보이는데 있습니다
8️⃣ 안보이는데 초점 이동 시에는 보여야 해(7번과 다름)