화면 읽기 프로그램(screen reader — 자료에 따라 스크린 리더)은 화면의 글을 소리로 읽어 주는 프로그램입니다. 화면을 눈으로 보는 것이 아니라, 브라우저가 요소 나무에서 뽑아 준 요소의 역할과 이름을 차례로 읽습니다.
눈으로 보는 사람은 크고 굵은 글을 제목으로, 파란 밑줄 글을 링크로 알아봅니다. 화면을 듣는 사람에게는 그 모양이 전해지지 않습니다.
그 사람이 '여기는 제목, 여기는 누를 수 있는 링크'라고 알 길은 HTML에 적은 요소의 뜻뿐입니다. 이 레슨에서는 프로그램이 받는 역할과 이름, 페이지 안을 건너다니는 두 목록, 읽는 말을 정하는 lang을 봅니다.
이 단원을 마치면 레시피 노트 두 페이지를 점검 목록 한 장으로 고치고, 마우스 없이 키보드만으로 끝까지 다닐 수 있습니다. 이 단원(누구나 쓸 수 있는 HTML)을 이미 안다면 단원 연습 문제부터 풀고 틀린 레슨만 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다.
1읽는 것은 모양이 아니라 역할과 이름
<h2>재료</h2>
<ul>
<li>밥 2공기</li>
<li>김치 1컵</li>
</ul>
<a href="#steps">조리 순서</a>h2의 역할headingh2의 읽는 이름재료ul의 역할listli의 역할listitema의 역할linka의 읽는 이름조리 순서
역할(role)은 화면 읽기 프로그램이 그 요소를 무엇으로 받는지입니다. heading은 제목, list는 목록, listitem은 목록의 한 줄, link는 링크입니다.
읽는 이름은 그 요소를 부르는 이름입니다. 제목과 링크는 안의 글이 그대로 이름이 됩니다.
프로그램은 이 둘에 제목 단계 · 목록의 줄 수 같은 정보를 더해 읽습니다. 이 조각이라면 '제목 2단계, 재료' · '목록, 항목 2개' · '링크, 조리 순서'처럼 읽습니다. 읽는 말과 차례는 프로그램마다 다릅니다. 글자의 크기 · 굵기 · 색은 이 정보에 들지 않습니다. 역할은 요소 이름에서 나오고, 모양을 바꾸는 CSS는 역할을 바꾸지 않습니다(브라우저 규칙 3).
2제목 차례와 영역 목록으로 건너다니기
듣는 사람은 페이지를 처음부터 끝까지 다 듣지 않습니다. 프로그램은 제목만 모은 차례와 영역만 모은 목록을 만들어, 원하는 곳으로 바로 건너뛰게 합니다. 제목 차례는 제목 h1~h6에서 본 그 차례입니다. 영역 목록은 시맨틱 요소로 나눈 영역에서 나옵니다.
<header>
<p>레시피 노트</p>
<nav>
<a href="index.html">목록</a>
</nav>
</header>
<main>
<h1>김치볶음밥</h1>
</main>
<footer>
<p>내가 만든 요리를 기록하는 곳</p>
</footer>header의 역할bannernav의 역할navigationmain의 역할mainfooter의 역할contentinfo
시맨틱 요소 넷이 영역 목록의 네 줄이 됩니다. banner는 머리글, navigation은 내비게이션, main은 본문, contentinfo는 바닥글 영역입니다.
영역 목록에서 main을 고르면 머리글과 내비게이션을 건너뛰고 본문 첫 줄 '김치볶음밥'부터 듣습니다. 화면은 모두 div로 묶었을 때와 같지만, 읽는 쪽에는 이 넷이 길잡이가 됩니다(브라우저 규칙 3).
3lang — 어느 말의 소리로 읽을지
뼈대 첫 줄 <html lang="ko">의 lang은 이 페이지가 어느 말로 쓰였는지 적습니다. 화면 읽기 프로그램은 이 값을 보고 어느 말의 소리 규칙으로 읽을지 고르기도 합니다.
한 페이지 안에 다른 말로 쓴 부분이 있으면, 그 요소에 lang을 따로 적습니다.
<p lang="en">Kimchi rice</p>화면은 lang이 있든 없든 같습니다. 갈리는 것은 듣는 쪽뿐이라, 결과 화면으로는 볼 수 없습니다.
예제
레시피 페이지의 한 부분입니다. 화면 읽기 프로그램이 위에서부터 지나갈 요소의 역할과 이름을 차례로 적어 본 뒤 결과 화면을 펴 보세요.
<main>
<h1>김치볶음밥</h1>
<img
src="images/kimchi.svg"
alt="김치볶음밥 한 그릇"
width="200"
height="150"
/>
<h2>재료</h2>
<p>밥 2공기, 김치 1컵</p>
<a href="index.html">목록</a>
</main>
결과 화면 보기
main의 역할mainh1의 역할headingimg의 역할imageimg의 읽는 이름김치볶음밥 한 그릇h2의 역할headingp의 역할paragraphp의 읽는 이름(없음)a의 역할linka의 읽는 이름목록
- main — 본문 영역에 들어섭니다.
- heading '김치볶음밥' — 1단계 제목입니다.
- image '김치볶음밥 한 그릇' — 그림의 이름은
alt글입니다. - heading '재료' — 2단계 제목입니다.
- paragraph — 문단은 이름 없이 안의 글 '밥 2공기, 김치 1컵'을 읽습니다.
- link '목록'
어느 줄에도 글자 크기나 굵기는 나오지 않습니다. 예상과 다르면 그곳이 배울 곳입니다.
자주 틀리는 곳
틀린 생각: 화면 읽기 프로그램은 화면에 보이는 대로 읽는다 — 크고 굵게 쓴 글은 제목으로 읽는다.
화면에서 제목처럼 보이면, 듣는 사람에게도 제목으로 전해질 것 같습니다.
<p class="big">재료</p>
<p>밥 2공기</p>
.big {
font-size: 24px;
font-weight: 700;
}.big의 역할paragraph.big의font-size24px
'재료'는 제목처럼 크고 굵게 그려지지만 역할은 문단입니다. 제목 차례에 들지 않아, 제목으로 건너다니는 사람은 이 자리를 지나칩니다.
맞는 규칙: 프로그램은 모양이 아니라 나무의 역할과 이름을 읽습니다. 제목이면 제목 요소로 쓰고, 크기는 CSS로 맞춥니다(브라우저 규칙 3).
틀린 생각: lang은 화면에 아무것도 바꾸지 않으니 빼거나 아무 값이나 둬도 된다.
영어 페이지에서 뼈대를 복사해 와 첫 줄이 이렇게 남았습니다.
<html lang="en">
화면은 lang="ko"일 때와 하나도 다르지 않습니다. 그래도 프로그램은 이 값을 보고, 한국어 글을 영어의 소리 규칙으로 읽기도 합니다.
맞는 규칙: lang은 화면이 아니라 읽는 쪽을 위한 값입니다. 한국어 페이지는 lang="ko"로 두고, 다른 말로 쓴 부분에는 그 요소에 lang을 적습니다.
틀린 생각: section으로 묶은 칸은 모두 영역 목록에 든다.
<section>
<h2>재료</h2>
</section>
<section aria-label="영양 정보">
<p>열량 550 kcal</p>
</section>section의 역할genericsection[aria-label]의 역할regionsection[aria-label]의 읽는 이름영양 정보
이름 없는 section의 역할은 generic(이름 없는 묶음)이라 영역 목록에 들지 않습니다. aria-label로 이름을 붙인 둘째 section만 '영양 정보' 영역(region)이 됩니다. aria-label은 이 단원 글자 없는 단추와 숨긴 라벨에서 자세히 봅니다.
맞는 규칙: 영역 목록에는 페이지 전체의 header · footer와 nav · main · aside, 이름이 있는 section이 듭니다. 칸마다 section을 늘린다고 길잡이가 늘지 않습니다.
확인 문제
1. 예제의 링크 줄을 nav로 감쌌습니다. 이제 영역 목록에 드는 역할을 모두 고르세요. 기호를 다 쓰세요.
<main>
<h1>김치볶음밥</h1>
<img
src="images/kimchi.svg"
alt="김치볶음밥 한 그릇"
width="200"
height="150"
/>
<h2>재료</h2>
<p>밥 2공기, 김치 1컵</p>
<nav>
<a href="index.html">목록</a>
</nav>
</main>
- ㉠
main - ㉡
navigation - ㉢
heading - ㉣
link
힌트
요소마다 역할을 적고, 2절의 영역 목록 네 줄과 견줘 봅니다.
정답
㉠ ㉡ — main과 navigation입니다.
main의 역할mainnav의 역할navigationa의 역할link
nav는main안에 있어도navigation영역입니다. 영역 목록에서 고르면 '목록' 링크 앞으로 바로 건너뜁니다.- ㉢
heading은 영역 목록이 아니라 제목 차례에 듭니다. - ㉣
link는 영역이 아니라navigation영역 안의 요소입니다.nav가 링크를 감쌌다고 링크가 영역이 되지는 않습니다.
2. 레시피 노트 페이지의 맨 아래 줄입니다. 화면 읽기 프로그램의 영역 목록에 바닥글(contentinfo)로 들게, ____ 두 자리에 같은 요소 이름을 쓰세요.
<____>
<p>내가 만든 요리를 기록하는 곳</p>
</____>
힌트
2절 예제에서 바닥글 줄을 감싼 요소를 찾아봅니다.
정답
footer입니다.
<footer>
<p>
내가 만든 요리를 기록하는 곳
</p>
</footer>footer의 역할contentinfo
div로 감싸면 역할이 generic이라 영역 목록에 들지 않습니다. 이름 없는 section도 마찬가지입니다.
3. 카페 메뉴판 페이지입니다. 화면 읽기 프로그램의 영역 목록을 열면 banner 하나만 있고 본문 영역이 없습니다. 몇 번 줄을 어떻게 고칠까요?
<header>
<p>플로우 카페</p>
</header>
<div class="main">
<h1>메뉴</h1>
<p>커피 4000원</p>
</div>힌트
4번 줄 요소의 역할을 적어 봅니다.
힌트 둘
역할은 요소 이름과 클래스 이름 가운데 어느 쪽에서 나오는지 봅니다.
정답
4번 줄 <div class="main">을 <main>으로, 7번 줄 </div>를 </main>으로 고칩니다.
<header>
<p>플로우 카페</p>
</header>
<main>
<h1>메뉴</h1>
<p>커피 4000원</p>
</main>main의 역할main
- 고치기 전 4번 줄
div의 역할은generic입니다. 클래스 이름main은 이름표일 뿐이라 역할을 정하지 않습니다(브라우저 규칙 3). - 흔한 오답은
class="main"을id="main"으로 바꾼 답입니다. 이름표를 바꿔도 요소는 그대로div라 역할도 그대로입니다.