한 줄 요약 — 웹 접근성은 마우스를 못 쓰거나 화면이 잘 안 보이는 사람도 같은 페이지를 쓸 수 있게 만드는 일이다. 시맨틱 태그로 길에 이름표를 붙이고, 글자 없는 요소에만
aria-label을 달고, 색 대비를 충분히 주고, 키보드 포커스를 또렷하게 남겨 두면 대부분 챙겨진다. 오늘은 이 네 가지를 한 화면에 적용해 키보드만으로 페이지를 끝까지 다녀 본다.
학습 목표#
- 시맨틱 태그가 스크린 리더에게 어떤 이정표 역할을 하는지 이해할 수 있다.
- 글자가 없는 요소에만
aria-label을 달아 이름을 붙일 수 있다. - WCAG가 권하는 색 대비 기준을 알고 흐릿한 회색을 피할 수 있다.
:focus-visible로 키보드 사용자에게만 또렷한 포커스 표시를 줄 수 있다.- 키보드만으로 한 페이지를 처음부터 끝까지 사용해 볼 수 있다.
오늘의 비유 — 턱을 낮춘 길#
새로 길을 깐다고 해 보자. 보도와 차도 사이에 높은 경계석을 그대로 두면, 걷는 사람은 별 불편이 없지만 휠체어나 유모차, 무릎이 안 좋은 노약자는 그 턱 하나에 길이 끊긴다. 그래서 횡단보도 앞은 경계석을 비스듬히 낮춰 둔다. 이 턱 낮춤(curb cut) 하나가 휠체어도, 유모차도, 무거운 짐수레도 같은 길을 다닐 수 있게 한다. 길을 다시 깐 게 아니라, 끊기는 지점 하나를 손본 것이다.
웹 접근성도 똑같다. 페이지를 새로 만드는 게 아니라, 누군가에게 길이 끊기는 지점을 손보는 일이다. 마우스를 못 쓰는 사람에게는 키보드라는 길을, 화면이 잘 안 보이는 사람에게는 또렷한 대비라는 길을, 스크린 리더를 쓰는 사람에게는 이름표가 붙은 길을 내준다. 오늘 다루는 네 가지는 전부 "여기서 누구의 길이 끊기는가"를 찾아 턱을 낮추는 작업이다.
핵심 개념#
접근성을 챙기는 출발점은 거창한 도구가 아니라, 이미 배운 시맨틱 태그와 색·포커스를 제대로 쓰는 것이다. 네 갈래로 나눠 본다.
시맨틱 태그 — 길에 이름표를 붙이기#
8회에서 다룬 <header>, <nav>, <main>, <footer> 같은 시맨틱 태그는 눈에 보이는 모습은 <div>와 같지만, 화면을 읽어 주는 스크린 리더에게는 길 위의 이정표가 된다. 스크린 리더 사용자는 이 이름표를 따라 "본문으로 건너뛰기", "다음 구역으로" 같은 식으로 페이지를 훑는다.
<header>로고와 메뉴</header>
<main>
<h1>오늘의 메모</h1>
<p>본문 내용</p>
</main>
<footer>저작권 표시</footer>
같은 화면을 <div>만으로 짜면 보기엔 똑같지만, 스크린 리더에게는 이름표 없는 길이라 어디가 본문이고 어디가 메뉴인지 알 수 없다. 그래서 접근성의 첫걸음은 따로 속성을 더하는 게 아니라, 올바른 태그를 고르는 것이다.
aria-label — 이름표가 없는 곳에만 손으로 달기#
ARIA(Accessible Rich Internet Applications)는 시맨틱 태그만으로 부족할 때 요소에 역할이나 이름을 보태 주는 속성 묶음이다. 그중 가장 자주 쓰는 aria-label은 눈에 보이는 글자가 없는 요소에 이름을 붙여 준다. 돋보기 아이콘 하나만 든 검색 버튼이 대표적이다.
<button aria-label="검색">🔍</button>
화면에는 돋보기만 보이지만, 스크린 리더는 "검색, 버튼"이라고 읽어 준다. 핵심은 글자가 없을 때만 쓴다는 것이다. <button>검색</button>처럼 이미 글자가 있으면 그 글자가 곧 이름표라, aria-label을 또 달면 이름표를 두 개 붙이는 셈이 된다. 길에 이미 이름표가 있는데 그 위에 똑같은 표지판을 덧대는 격이다.
색 대비 — 표지판이 흐릿하면 안 보인다#
길에 이름표를 붙여도 글씨가 배경에 묻혀 흐릿하면 못 읽는다. 화면도 마찬가지라, 글자색과 배경색의 밝기 차이(대비)가 충분해야 한다. WCAG(Web Content Accessibility Guidelines, 웹 콘텐츠 접근성 지침)는 본문 글자는 배경과 4.5:1 이상, 큰 글자(대략 24px 이상 또는 굵은 18.66px 이상)는 3:1 이상의 대비를 권한다.
/* (옅은 회색 글자는 흰 배경에서 대비가 약 2.8:1로 기준에 못 미칩니다) */
.note {
color: #aaaaaa;
background: #ffffff;
}
#aaaaaa처럼 옅은 회색은 디자인상 차분해 보여도 흐린 날 안내판처럼 잘 안 읽힌다. 한 톤 진하게 내리면 같은 회색 계열이라도 기준을 넘긴다.
.note {
color: #595959; /* 흰 배경 대비 약 7:1 */
background: #ffffff;
}
대비 값은 눈대중으로 맞히기 어렵다. 브라우저 개발자 도구의 색 선택기나 WebAIM 대비 검사기에 두 색을 넣으면 비율을 바로 알려 준다.
키보드 포커스 — 휠체어로도 길 끝까지#
마우스 없이 Tab 키만으로 페이지를 다니는 사람이 적지 않다. 이들에게는 "지금 내가 어느 버튼 위에 있는가"를 보여 주는 포커스 표시가 길을 비추는 가로등이다. 브라우저는 기본으로 포커스된 요소에 외곽선(outline)을 그려 주는데, 이걸 지워 버리면 키보드 사용자는 캄캄한 길을 더듬는 꼴이 된다.
마우스 사용자에게는 이 외곽선이 거슬릴 수 있어서, 둘을 가르는 :focus-visible을 쓴다. 키보드로 이동했을 때만 표시를 켜 준다.
:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 2px;
}
이러면 마우스로 클릭할 때는 외곽선이 안 뜨고, Tab으로 옮겨 다닐 때만 또렷한 파란 테가 따라붙는다. 참고로 <a>, <button>, <input> 같은 요소는 원래 키보드로 닿지만, <div>에 클릭 기능을 얹은 경우엔 tabindex="0"을 줘야 Tab 순서에 낀다. 다만 가능하면 처음부터 <button>을 쓰는 편이 손이 덜 간다.
함께 따라하기 — 키보드만으로 페이지 끝까지#
링크 하나와 버튼 두 개를 두고, 마우스를 치워 둔 채 Tab 키만으로 끝까지 다녀 본다.
<header>
<a href="#main">본문으로 건너뛰기</a>
</header>
<main id="main">
<h1>오늘의 메모</h1>
<button>저장</button>
<button aria-label="삭제">🗑️</button>
</main>
body {
color: #1a1a1a;
background: #ffffff;
}
:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 2px;
}
button {
padding: 8px 16px;
font-size: 16px;
}
저장하고 열어 페이지 안을 한 번 클릭한 뒤, 마우스에서 손을 떼고 Tab을 눌러 본다. 첫 Tab에서 "본문으로 건너뛰기" 링크에 파란 테가 뜨고, 다시 누르면 저장 버튼, 한 번 더 누르면 삭제 버튼으로 또렷한 테가 차례로 옮겨 간다. Enter나 Space로 버튼이 눌리는 것까지 확인되면, 마우스 없이도 길이 끊기지 않는 페이지가 된 것이다. 스크린 리더를 켜 두면 마지막 버튼은 이모지 대신 "삭제, 버튼"으로 읽힌다.
흔한 실수 3가지#
1. 디자인 깔끔하게 한다고 outline:none만 주고 끝낸다#
기본 외곽선이 투박해 보인다고 outline: none으로 지워 버리는 경우가 가장 많다. 마우스 화면은 깔끔해지지만, 키보드 사용자는 자기가 지금 어디 있는지 알 수 없게 된다. 가로등을 다 꺼 버린 길과 같다.
/* (포커스 표시가 사라져 키보드 사용자가 위치를 잃습니다) */
button:focus {
outline: none;
}
지우고 끝내지 말고, 더 보기 좋은 표시로 바꿔 준다. :focus-visible로 키보드일 때만 또렷한 테를 주면 마우스 화면도 깔끔하고 키보드 길도 살아 있다.
button:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 2px;
}
2. aria-label을 시맨틱 태그가 있는데도 덧붙인다#
aria-label이 접근성에 좋다는 말만 듣고, 이미 글자가 있는 버튼에까지 습관처럼 다는 경우가 있다. 이름표가 둘이 되면 오히려 스크린 리더가 우리가 단 라벨로 글자를 덮어, 화면 글씨와 읽히는 말이 어긋날 수 있다.
<!-- (화면엔 "저장"인데 스크린 리더는 "보관"으로 읽어 둘이 어긋납니다) -->
<button aria-label="보관">저장</button>
글자가 보이는 요소는 그 글자가 곧 이름표다. aria-label은 돋보기·휴지통 같은 아이콘 버튼처럼 읽어 줄 글자가 없을 때만 쓴다.
<button>저장</button>
<button aria-label="삭제">🗑️</button>
3. 색 대비를 검사하지 않고 회색을 남발한다#
요즘 디자인이 옅은 회색을 즐겨 쓰다 보니, 보조 설명이나 안내 문구를 #cccccc 같은 흐린 회색으로 두기 쉽다. 만든 사람의 좋은 모니터에선 읽히지만, 밝은 야외나 저가 화면에선 글자가 배경에 묻힌다. 흐린 날 빛바랜 안내판과 같다.
/* (대비가 약 1.6:1로, 기준 4.5:1에 크게 못 미칩니다) */
.hint {
color: #cccccc;
background: #ffffff;
}
색을 정하기 전에 대비 검사기로 비율을 확인하고, 본문은 4.5:1을 넘기게 한 톤 진하게 내린다. 굳이 회색을 쓰고 싶다면 읽히는 선까지만 옅게 둔다.
.hint {
color: #6b7280; /* 흰 배경 대비 약 4.8:1 */
background: #ffffff;
}
오늘 배운 것 체크리스트#
- 시맨틱 태그가 스크린 리더에게 이정표가 된다는 것을 안다.
-
aria-label은 글자가 없는 요소에만 단다. - 본문 색 대비를 4.5:1 이상으로 맞추고 검사기로 확인한다.
-
:focus-visible로 키보드 사용자에게 또렷한 포커스 표시를 준다. - 마우스 없이
Tab키만으로 페이지를 끝까지 다녀 봤다.
자주 묻는 질문#
Q. WCAG 색 대비는 최소 얼마로 맞춰야 하나요?
A. 일반 본문 글자는 배경과 4.5:1 이상, 큰 글자(대략 24px 이상이거나 굵은 18.66px 이상)는 3:1 이상이 기준입니다. 눈대중으로는 맞히기 어려우니 브라우저 개발자 도구의 색 선택기나 WebAIM 대비 검사기에 글자색과 배경색을 넣어 비율을 확인하는 게 안전합니다.
Q. aria-label은 언제 쓰고 언제 안 쓰나요?
A. 돋보기·휴지통 아이콘만 든 버튼처럼 읽어 줄 글자가 없는 요소에만 씁니다. <button>저장</button>처럼 이미 보이는 글자가 있으면 그 글자가 이름표 역할을 하므로 aria-label을 덧붙이지 않습니다. 잘못 달면 화면 글씨와 스크린 리더가 읽는 말이 어긋날 수 있습니다.
Q. 키보드 포커스 표시는 어떻게 남기나요?
A. 기본 외곽선을 outline: none으로 지우지 말고, :focus-visible로 키보드 이동일 때만 또렷한 외곽선을 주면 됩니다. 이러면 마우스 클릭 때는 표시가 안 뜨고 Tab으로 옮겨 다닐 때만 테가 따라붙어, 디자인과 접근성을 둘 다 지킬 수 있습니다.
다음 시간 예고#
내일은 폼 스타일링 — input, button, focus-visible, :invalid를 다룬다. 오늘 익힌 :focus-visible을 그대로 입력창에 이어 붙이고, :valid·:invalid로 입력 상태에 따라 폼의 모습을 바꿔 본다.