1. 웹 콘텐츠 접근성 지침?
- 이번 시간에는 웹 콘텐츠 접근성 지침, 즉 WCAG(Web Content Accessibility Guidelines)에 대해 알아보고자 한다. WCAG는 모든 사용자, 특히 신체적 제약이 있는 사용자들이 웹 콘텐츠에 쉽게 접근할 수 있도록 설계된 권장 사항이다. 웹 콘텐츠 접근성은 단순히 법적 요구사항을 충족하는 것을 넘어, 모든 사람이 디지털 정보에 평등하게 접근할 수 있는 권리를 보장하는 매우 중요한 요소이다.
- 예를 들어, 시각 장애를 가진 사용자가 웹사이트를 이용할 때 화면 읽기 프로그램(screen reader)을 사용해 콘텐츠를 음성으로 들을 수 있다. 하지만, 웹사이트가 WCAG 지침을 따르지 않는다면 이 프로그램이 제대로 작동하지 않는다. 또한 텍스트가 아닌 이미지나 그래프에 중요한 정보가 담겨 있고, 그에 대한 대체 텍스트가 제공되지 않는다면, 시각 장애 사용자는 그 내용을 알 수 없게 된다. 이러한 문제를 해결하기 위해 WCAG는 모든 이미지에 대체 텍스트를 제공하도록 권장한다.
- WCAG는 실명, 저시력, 청각 장애, 운동 기능의 제한을 가진 사용자들뿐만 아니라, 일시적으로 불편을 겪는 사용자들까지 모두를 아우르는 포괄적인 웹 접근성을 목표로 하고 있다.
- 이번 시리즈에서는 WCAG의 핵심 원칙 중 하나인 POUR 원칙을 차례대로 소개할 예정이다.
POUR 원칙
POUR 원칙은 웹 접근성을 보장하기 위해 중요한 네 가지 요소를 다루며, 각 원칙은 사용자 경험을 개선하는 데 중대한 역할을 한다:
4가지 원칙 | 설명 |
---|---|
지각 가능(Perceivable) | 정보는 다양한 방식으로 제공되어야 한다. ex) 점자, 다른 크기의 텍스트, 텍스트 음성 변환 등 |
조작 가능(Operable) | 기능은 다양한 도구로 사용할 수 있어야 한다. ex) 키보드, 마우스, 터치 등 |
이해 가능(Understandable) | 정보와 기능은 사용자가 이해할 수 있어야 한다. ex) 일관된 탐색, 간단한 언어 등 |
견고(Robust) | 콘텐츠는 다양한 브라우저, 미디어 플레이어, 보조 기술에 의해 신뢰성 있게 해석되어야 한다. |
- 이번 시간에는 POUR 원칙 중, 그 첫번째인 “지각 가능(Perceivable)원칙”를 살펴보고자 한다.
- 각 원칙별 내용이 많기 때문에 각 원칙 별로 2 ~ 3개의 포스팅으로 소개할 예정이다.
- 이 시리즈에서 소개하는 모든 내용은 w3c 공식 내용을 기반으로 작성했다. (perceivable, perceivable)
1. Perceivable
💡 정보와 사용자 인터페이스 구성요소는 사용자가 지각할 수 있는 방식으로 제공되어야 한다.
- 사용자가 지각할 수 있도록 정보를 제공하기 위해 어떤 처리를 해야할까? 한 번 알아보자!
1) 콘텐츠는 다양한 방식으로 제공되어야 한다.
(1) 설명
- 모든 정보는 구조를 잃지 않되, 사용자의 요구에 따라 다양한 방식으로 콘텐츠를 제공해야 한다.
- 텍스트를 예로 들면, 저시력 사용자는 전자 텍스트를 확대할 수 있어야 하고 읽기 장애가 있는 사용자는 전자 텍스트를 소리로 제공받을 수 있어야 한다.
- 또한 콘텐츠를 [화면 읽기 모드]로 전환할 때, 해당 화면에서 정보의 관계가 명확히 드러나야 한다.
정보의 관계가 명확히 드러나야 한다? 그게 무슨 말일까?
- 콘텐츠를 사이트에서 지정한 스타일로 볼 수 있지만, [화면 읽기 모드]로 전환하면 프레젠테이션 형식으로 볼 수 있다.
- 프레젠테이션 형식의 경우, 오로지 html 태그와 role 형식 등을 탐색해 컨텐츠의 위계 질서와 관계를 나타낸다.
- IOS의 경우, safari 브라우저에서 [읽기 도구 보기]로, 프레젠테이션 모드에 접근할 수 있다.
- 아래 이미지는 위키피디아의 “연필의 역사”에 대한 컨텐츠이다.
- 만약 [읽기 도구 보기]를 실행하면, 콘텐츠의 h1 ~ h4, p, a 태그 등을 인식해 아래와 같이 프레젠테이션 형식으로 변경된다.
- 이미지를 보면 알 수 있듯이, 제목, 링크, 참조 등의 역할이 명확히 표현되어 있는 걸 볼 수 있다.
- 이처럼 [화면 읽기 모드]에서 정보의 관계가 명확하면, 시각적으로 콘텐츠의 관계는 물론 청각적으로도 위계를 확인할 수 있다.(스크린리더는 “역사”라는 글자를 “역사 제목”이라고 읽음)
- 그럼, 시각으로 정보를 탐색하는 사용자 그리고 청각으로 정보를 탐색하는 사용자는 콘텐츠의 관계를 주로 어떻게 인식할까?
사용자 | 시각으로 정보 관계를 인식하는 사용자 | 청각으로 정보를 탐색하는 사용자 |
---|---|---|
콘텐츠 인식 방식 | 제목은 큰 굵은 글꼴로 되어 있고 단락과 빈 줄로 구분된다. | 새로운 섹션의 시작을 알리는 차임 소리가 난다. |
목록은 중앙점 기호로 표시되며, 들여쓰기가 되어 있다. | 중요한 정보를 강조하거나 인용 텍스트를 나타내기 위해 음성 피치 또는 음성 속도가 변경된다. | |
단락은 빈 줄로 구분된다. | ||
공통 특성을 공유하는 항목은 표의 행과 열로 구성된다. | ||
특수한 상태인 단어는 다른 글꼴로 표현되거나 굵게, 기울임꼴, 밑줄로 표시된다. |
2) ARIA로 페이지 영역을 지정해야한다.
(1) ARIA란?
이미지: 검색창에 aria로 ‘검색’이라는 역할을 지정한 모습(role=”search”)
- ARIA(Accessible Rich Internet Applications) 랜드마크는 페이지의 섹션에 역할을 지정하는 HTML 속성이다.
- ARIA 랜드마크를 사용하면 보조 기술(예: 스크린 리더) 사용자가 페이지의 구조를 이해하고, 탐색할 수 있다.
- 또한 웹 페이지의 다양한 섹션을 구분할 수 있어, 사용자가 원하는 정보에 쉽게 접근할 수 있다.
- ARIA 랜드마크는 필요에 따라 페이지에서 콘텐츠 블록을 건너뛰게 도와준다.
(2) 랜드마크 종류와 의미
역할 종류 | 의미 |
---|---|
배너 (banner) | 페이지의 주요 제목이나 큰 제목이 있는 영역 |
내비게이션 (navigation) | 다른 페이지나 같은 페이지의 다른 부분으로 이동할 수 있는 링크들이 모여 있는 영역 |
메인 (main) | 페이지의 주요 내용을 포함하는 영역 |
지역 (region) | 중요한 콘텐츠가 포함된 영역 중요한 콘텐츠가 있어, 사용자가 이 영역으로 이동할 수 있다고 알려줌 |
폼 (form) | 입력한 값을 서버로 제출할 수 있는 폼 요소들이 모여 있는 영역 |
검색 (search) | 검색 기능이 있는 페이지 영역 |
보조 (complementary) | 주요 내용을 보완하지만, 독립적으로도 의미가 있는 영역 |
콘텐츠 정보 (contentinfo) | 저작권 정보나 개인정보 보호정책 링크와 같은 정보가 포함된 영역 |
(3) 기본 랜드마크 예시
<div role="banner">사이트 로고 및 이름 등</div>
<div role="search">검색 기능</div>
<div role="navigation">네비게이션 링크 목록</div>
<div role="form">가입 양식</div>
<div role="main">페이지의 주요 콘텐츠</div>
<div role="region">스폰서 프로모션</div>
<div role="complementary">사이드바 콘텐츠</div>
<div role="contentinfo">사이트 연락처 정보, 저작권 정보 등</div>
- 이 경우 스크린 리더는 내용 + 역할 조합으로 텍스트를 읽는다. (ex. 사이드 로고 및 이름 등 배너)
(4) 같은 유형의 랜드마크가 여러 개 있는 경우 1
- 때로는 특정 랜드마크
role
이 한 페이지에서 여러 번 사용될 수 있다. - 한 예로 추가적인 보조 네비게이션 블록이 있는 경우,
navigation
역할이 여러 요소에 지정된다. - 이때, 이 둘을 구분하기 위해,
aria-labelledby
로 역할을 구체화시킬 수 있다. aria-labelledby
는 주로 다른 요소의 내용으로 지정할 때 쓰인다.id
속성으로 라벨로 사용할 요소를 참조한다.
<div aria-labelledby="site-nav-heading" role="navigation">
<h2 id="site-nav-heading">사이트 네비게이션</h2>
<ul>
<li><a href="...">네비 링크 1</a></li>
<li><a href="...">네비 링크 2</a></li>
<li><a href="...">네비 링크 3</a></li>
</ul>
</div>
<div aria-labelledby="related-nav-heading" role="navigation">
<h2 id="related-nav-heading">관련 주제 네비게이션</h2>
<ul>
<li><a href="...">주제 링크 1</a></li>
<li><a href="...">주제 링크 2</a></li>
<li><a href="...">주제 링크 3</a></li>
</ul>
</div>
- 각 섹션을 클릭하면, 스크린 리더는
aria-labeledby
와 같은 값을 가진h2
의 텍스트와 역할을 함께 읽는다.
(5) 같은 유형의 랜드마크가 여러 개 있는 경우 2
- 위와 유사한 예시로,
aria-labelledby
대신aria-label
로 동일한 역할을 가진 섹션을 구분할 수 있다. aria-label
는 요소에 대한 간결한 설명을 직접 지정하는 속성이다. 그래서 속성 값 자체가 라벨로 사용된다.
<div aria-label="사이트 네비게이션" role="navigation">
<ul>
<li><a href="...">네비 링크 1</a></li>
<li><a href="...">네비 링크 2</a></li>
<li><a href="...">네비 링크 3</a></li>
</ul>
</div>
<div aria-label="태그 네비게이션" role="navigation">
<ul>
<li><a href="...">태그 링크 1</a></li>
<li><a href="...">태그 링크 2</a></li>
<li><a href="...">태그 링크 3</a></li>
</ul>
</div>
- 각 섹션을 클릭하면, 스크린 리더는
aria-label
값과 역할을 함께 읽는다.
3) 시맨틱 태그로 페이지 영역을 지정해야한다.
(1) 설명
- 시맨틱 태그(
semantic tags
)는 웹 페이지의 구조와 의미를 담은 HTML 태그이다. - 이 태그들은 브라우저와 검색 엔진, 보조 기술(예: 스크린 리더)이 콘텐츠의 구조와 의미를 더 정확하게 해석할 수 있게 도와준다.
- 시맨틱 태그는 또한 페이지 섹션의 랜드마크 역할도 겸하기에, 페이지의 섹션을 프로그램적으로 식별할 수 있게 해준다. 그래서 사용자가 페이지의 다양한 섹션으로 쉽게 탐색할 수 있게 된다.
(2) 시맨틱 태그의 종류
다음의 의미론적 HTML 요소를 사용하면 랜드마크 영역이 자동으로 생성된다:
시맨틱 태그 | 설명 |
---|---|
<header> |
사이트의 로고, 이름 그리고 전반의 콘텐츠를 포함 |
<nav> |
네비게이션 링크를 포함하는 영역 |
<main> |
페이지의 주요 콘텐츠를 포함하는 영역 |
<section> |
문서나 애플리케이션의 일반적인 섹션을 포함하는 영역 접근 가능한 이름이 있어야 랜드마크 영역으로 노출됨 |
<aside> |
주요 콘텐츠를 지원하지만 독립적이고 의미 있는 문서의 섹션 |
<footer> |
저작권 정보 및 개인정보 보호정책 링크와 같은 페이지에 대한 정보를 포함 |
(3) 기본 랜드마크 예시
<header>사이트 로고 및 이름 등</header>
<form aria-label="사이트 검색">검색 기능</form>
<nav>네비게이션 링크 목록</nav>
<main>페이지의 주요 콘텐츠</main>
<section>스폰서 프로모션</section>
<aside>사이드바 콘텐츠</aside>
<footer>사이트 연락처 정보, 저작권 정보 등</footer>
(4) 같은 유형의 랜드마크가 여러 개 있는 경우
<nav aria-labelledby="site-nav-heading">
<h2 id="site-nav-heading">사이트 네비게이션</h2>
<ul>
<li><a href="/news">뉴스</a></li>
<li><a href="/weather">날씨</a></li>
<li><a href="/sport">스포츠</a></li>
</ul>
</nav>
<nav aria-labelledby="related-nav-heading">
<h2 id="related-nav-heading">관련 주제</h2>
<ul>
<li><a href="/local-news">지역 뉴스</a></li>
<li><a href="/local-weather">지역 날씨</a></li>
<li><a href="/local-sport">지역 스포츠</a></li>
</ul>
</nav>
- 각 섹션을 클릭하면, 스크린 리더는
aria-labeledby
와 같은 값을 가진h2
의 텍스트와nav
역할(탐색)을 함께 읽는다.
4) role=heading를 지정해 제목임을 명시해야한다.
(1) 설명
role=heading
은 콘텐츠 일부를 제목으로 식별할 수 있도록 바꿔준다 .- 요소에
role="heading"
을 적용하면 AT(예: 화면 읽기 프로그램)가 해당 요소를 제목으로 취급한다. role="heading"
속성은 제목 수준을 정의하는aria-level
속성과 함께 사용해야 한다.
<!-- recommand -->
<h1>제목</h1>
<!-- good -->
<div role="heading" aria-level="1">제목</div>
- 하지만 가능하다면, 네이티브 헤더 마크업을 사용하는 것이 좋은데, 네이티브 HTML 요소는 암시적 스타일링과 기능을 가지기 때문이다. (ex. h1 태그의 경우, 큰 글자와 두꺼운 글자 굵기 스타일이 적용됨)
- 반면
<div role="heading" aria-level="1">
는div
요소이기 때문에 암시적 스타일링이 적용되지 않는다. 결국, ARIA는 요소가 보조 기술에 노출되는 방식일 뿐, 요소의 암시적 스타일이나 기능을 변경하지 않는다.
(2) 제목을 표현한 예시
- 다음 예시는
role="heading"
과aria-level
으로 제목을 선언한 모습이다.
<div role="heading" aria-level="2">전세계 뉴스 항목</div>
<div role="heading" aria-level="3">정치</div>
- 각 영역을 선택하면, 스크린 리더는 콘텐츠와 역할(제목)을 함께 읽는다.
(3) 추가적인 제목 레벨로 표현한 예시
- 다음 예시는
role="heading"
과aria-level
속성으로 7단계 제목을 구현한 모습이다. - HTML은 최대 6단계 제목만 지원하므로 이러한 의미를 제공하는 네이티브 요소는 없다.
- 이처럼
aria-level
을 사용하면, 추가적인 레벨을 지정할 수 있으나 10단계 이상의aria-level
은 사용자에게 어려움을 줄 수 있다.
<h5>과일 나무</h5>
<h6>사과</h6>
<div role="heading" aria-level="7">조나골드</div>
<p>조나골드는 골든 딜리셔스와 조나단 품종의 교배종입니다...</p>
- 각 영역을 선택하면, 스크린 리더는 콘텐츠와 역할(제목)을 함께 읽는다.
5) aria-labelledby로 영역이나 랜드마크에 이름 지정해야한다.
(1) 설명
aria-labelledby
속성은 다른 페이지 영역의 id를 값으로 지정해, 해당 영역을 가리킬 수 있다.aria-labelledby
는 공백으로 구분된 여러 개의 id를 지정할 수도 있다.
(2) 제목 텍스트로 랜드마크를 식별한 예시
aria-labelledby
속성값으로 헤더의 Id 값을 지정해, 해당 영역을 식별할 수 있다.
<div role="complementary" aria-labelledby="hdr1">
<h1 id="hdr1">최신 뉴스 기사</h1>
</div>
- 스크린 리더는
<div>
요소를 읽을 때,aria-labelledby
에 지정된<h1>
요소의 텍스트를 라벨로 읽고, - 그 다음에
role="complementary"
로 지정된 보조 콘텐츠 영역임을 설명한다. - 따라서 최종적으로 사용자에게는 "제목 1 최신 뉴스 기사 상호보완"와 같이 읽는다.
(3) 설명 텍스트로 랜드마크를 식별한 예시
- 설명 텍스트가 있는 애플리케이션 랜드마크에 대한 예시이다.
- 애플리케이션 랜드마크에
aria-describedby
의 값으로 설명 텍스트의 id를 지정해, 애플리케이션과 정적 텍스트를 연관시킬 수 있다.
<div role="application" aria-labelledby="p123" aria-describedby="info">
<h1 id="p123">달력</h1>
<p id="info">이 달력은 보스턴 레드삭스의 경기 일정을 보여줍니다.</p>
<div role="grid">
...
</div>
</div>
- 이 경우, 접근성 도구가 애플리케이션 랜드마크를 읽을 때 관련 설명 텍스트를 함께 읽는다.
- 스크린 리더는 먼저 "달력"이라는 제목을 읽고,
- 이어서 "이 달력은 보스턴 레드삭스의 경기 일정을 보여줍니다."라는 설명을 읽은 후,
- 그리드 내부의 콘텐츠를 탐색한다.
6) role="group”으로 폼 컨트롤 영역을 지정해야한다.
(1) 설명
- form의 관련된 컨트롤 세트를 그룹으로 표시한다.
- 보조 기술은 그룹 내로 들어가거나 나갈 때, 그룹의 시작과 끝 그리고 그룹의 라벨을 표시할 수 있다.
- 이 기술은 사용자 인터페이스 디자인상
fieldset
/legend
기술을 사용하기 어려운 경우에 폼 컨트롤을 프로그래밍적으로 그룹화하는 대안이다. - 그룹은
aria-labelledby
를 사용하여 라벨링할 수 있다. - 단, 라디오 버튼 그룹은
role="group"
대신role="radiogroup"
을 사용해야 한다.
(2) 사회보장번호 입력폼 예시
- 이 필드는 9자리 숫자라서 세 개의 세그먼트로 나눌 수 있다.
role="group"
을 사용하면 하나의 그룹으로 만들 수 있다.
<div role="group" aria-labelledby="ssn1">
<span id="ssn1">사회보장번호</span>
<span style="color: #D90D0D;"> (필수)</span>
<input size="3" type="text" aria-required="true" title="첫 3자리">-
<input size="2" type="text" aria-required="true" title="다음 2자리">-
<input size="4" type="text" aria-required="true" title="마지막 4자리">
</div>
(3) 라디오 그룹 예시
<h3>계정 알림 설정</h3>
<div role="radiogroup" aria-labelledby="alert1">
<p id="alert1">$3,000을 초과하는 잔액이 있을 때 알림 보내기</p>
<div>
<span role="radio" aria-labelledby="a1r1" name="a1radio"></span>
<span id="a1r1">예</span>
</div>
<div>
<span role="radio" aria-labelledby="a1r2" name="a1radio"></span>
<span id="a1r2">아니오</span>
</div>
</div>
- 각 영역을 선택하면, 스크린 리더는 라디오인지 라디오 그룹인지 역할도 함께 읽어준다.
7) role=”region”로 페이지의 중요 영역을 지정해야한다.
(1) 설명
region
은 중요한 콘텐츠를 포함하는 페이지의 세그먼트를 구분한다.- 표준 문서 랜드마크 역할로 표시할 수 없는 섹션에는
region
을 사용한다. - 영역에 이름을 지정하는 것이 중요한데, 사용자가 자신이 어느 영역에 있는지 알려주기 위함이다.
- 영역은
aria-labelledby
,aria-label
로 이름을 지정할 수 있는데, 그러면 콘텐츠와 정보 관계를 더 잘 드러낼 수 있다. - 단,
region
을 남용하면, 스크린 리더 사용자가 페이지가 지나치게 장황하다는 인식을 받게 된다.
(2) 웹사이트의 특정 영역에 적용한 예시
- 만약 어떤 웹사이트에 매주 진행하는 설문 조사 섹션이 있다 가정하자.
- 이 설문조사 섹션은 사용자에게 어떤 정보를 가졌는지, 알려줄 필요가 있지만
nav
도 그렇다고section
도 아니다. - 이처럼, 사용자에게 중요하지만 표준 문서 역할로 규정하기 어려운 경우
role="region"
을 사용하면 된다.
<div role="region" aria-labelledby="pollhead">
<h3 id="pollhead">이번 주 설문 조사</h3>
<form>
<fieldset>
<legend>세법이 개정되어야 한다고 생각하십니까?</legend>
<input type="radio" id="r1" name="poll">
<label for="r1">아니요, 현재 상태가 좋습니다</label>
<input type="radio" id="r2" name="poll">
<label for="r2">전반적으로 변화가 필요합니다</label>
</fieldset>
</form>
<a href="">설문 조사 결과 보기</a>
</div>
region
영역을 선택하면, 스크린 리더는 “이번주 설문조사 지역” 이라고 읽는다.
반응형
댓글