접근성은 기능을 더하는 일이 아니라 더 많은 사람이 쓰게 만드는 일입니다.
이번 글에서 새로 나오는 용어
- 포커스: 키보드 탐색 중 현재 조작 가능한 요소를 가리키는 상태로,
tabindex로 순서를 조절합니다. - aria-label: 화면에는 보이지 않지만 스크린 리더에게 버튼 목적을 설명하는 속성입니다.
- 모달(dialog): 페이지 위에 겹쳐 뜨는 대화 상자로, 열렸을 때 포커스가 내부에만 머물러야 합니다.
- 대비 미디어 쿼리:
@media (prefers-contrast: more)처럼 사용자 설정에 따라 더 강한 윤곽을 적용하는 CSS 규칙입니다.
개념
포커스(focus)는 키보드로 이동할 때 어느 요소가 선택되는지를 나타내는 상태입니다. 버튼이 아닌 요소를 클릭용으로 사용할 때는 role="button"과 tabindex="0"를 지정해 포커스를 허용해야 합니다. 스크린 리더 레이블은 화면에 글자가 없더라도 버튼의 의도를 설명하는 텍스트입니다. aria-label 또는 aria-labelledby로 제공할 수 있습니다. 모달(modal, 겹쳐 뜨는 대화 상자)은 페이지 위에 떠 있는 UI입니다. 열리는 동안 포커스가 내부에만 머물러야 하며 닫을 때 이전 위치로 돌아가야 합니다.
코드
카드 토글, 모달, 대비 설정을 차례로 살펴봅니다.
<div
role="button"
tabindex="0"
on:click={() => toggle(task)}
on:keydown={(event) => {
if (event.key === 'Enter' || event.key === ' ') toggle(task);
}}
>
<h3>{task.title}</h3>
</div>
<button aria-label={`${task.title} 완료 상태 전환`}>
✔
</button>
<dialog bind:open={open} aria-labelledby={labelId} aria-describedby={descId}>
<h2 id={labelId}>과제 상세</h2>
<p id={descId}>상태, 담당자, 첨부 파일을 확인하세요.</p>
<button on:click={() => (open = false)}>닫기</button>
</dialog>
:global(.card) {
background: var(--surface);
}
@media (prefers-contrast: more) {
:global(.card) {
border: 2px solid var(--outline-strong);
}
}
아이콘 버튼에는 aria-label을 붙이고, dialog 요소에는 제목과 설명을 연결해 스크린 리더가 내용을 읽어 주도록 합니다. 대비 미디어 쿼리를 활용하면 고대비 모드를 선호하는 사용자에게 더 강한 윤곽을 제공합니다.
왜 중요한가
학교 프로젝트는 다양한 상황의 학생이 사용합니다. 키보드만 사용하는 친구도 있어야 하고, 화면 확대나 고대비 모드를 켠 사용자도 서비스에 접근할 수 있어야 합니다. 기본적인 ARIA 속성과 포커스 순서를 점검하는 것만으로도 문의와 버그를 크게 줄일 수 있습니다.
실습
- 따라 하기: 카드 토글 컴포넌트에
role,tabindex, 키보드 핸들러를 추가해 Tab 키로 조작한다. - 확장하기:
dialog기반 모달을 만들어bind:open상태와 닫기 버튼을 테스트한다. - 디버깅: 스크린 리더가 조용하면
aria-live영역과aria-label연결이 올바른지 확인한다. - 완료 기준: Tab 키로 주요 기능에 접근할 수 있고 고대비 모드에서도 카드 윤곽이 유지된다.
마무리
접근성 체크는 꾸준히 반복해야 합니다. 다음 편에서는 이러한 컴포넌트를 테스트 자동화 도구로 검증해 품질을 높여 봅니다.
💬 댓글
이 글에 대한 의견을 남겨주세요