접근성 콘텐츠 제작 기법은 모든 사용자, 특히 장애가 있는 사용자가 웹과 모바일 콘텐츠에 접근하고 사용할 수 있도록 보장하는 방법입니다. 이 기법은 웹 접근성 지침(WCAG: Web Content Accessibility Guidelines)과 모바일 접근성 표준을 따르는 것이 중요합니다. 각각의 영역에 대해 접근성 작업 시 도움이 될 수 있도록 작업되었습니다. 접근성은 법적 요구사항일 뿐만 아니라 사용자를 위한 기본적인 배려이기도 합니다.
사용자가 장애를 가지고 있거나 특정 기능적 제한을 겪는 경우에도 원활하게 모바일 앱을 이용할 수 있도록 하는 방법을 의미합니다. 이러한 접근성을 고려한 콘텐츠 제작은 다양한 사용자들의 요구를 충족시키며, 앱의 사용성을 크게 향상시킵니다.
관련 지침 : 텍스트 콘텐츠는 운영체제에서 제공하는 폰트 관련 기능을 활용할 수 있는 방법을 제공해야 한다.
모바일 앱의 폰트 관련 기능 활용은 사용자가 운영체제(OS)에서 제공하는 폰트 크기 조절 및 텍스트 스타일 옵션을 앱 내에서 사용할 수 있도록 보장하는 중요한 접근성 요소입니다. 이를 통해 시력 저하, 인지 장애, 노화로 인한 가독성 저하 등을 겪는 사용자가 텍스트를 보다 쉽게 읽고 이해할 수 있습니다.
WCAG 2.2 Quick Reference - Text Resize
키워드
#모바일 앱 접근성, #모바일 앱 접근성 콘텐츠 제작 기법, #WCAG2.2, #폰트 관련 기능의 활용, #시각 장애인, #고령 사용자, #인지 장애인, #비장애인 포함 전체 사용자, #폰트 크기 조절, #가독성, #사용자 정의 폰트, #Dynamic Type, #Accessibility Text Scaling
폰트 크기와 스타일 조절 기능은 다양한 사용자 그룹의 접근성과 가독성을 보장하는 데 필수적입니다. 운영체제의 기본 텍스트 조절 기능을 무시하거나 앱 내에서 비활성화하면 사용자가 자신에게 편한 크기와 스타일로 텍스트를 읽지 못할 수 있습니다. 특히 시각 장애인, 고령 사용자, 인지 장애를 가진 사용자는 더 큰 글씨와 명확한 글꼴을 통해 앱을 더 잘 이용할 수 있습니다.
iOS
Android
하이브리드 (HTML, Vue, React)
iOS에서 Dynamic Type 적용 방법
UILabel 및 UITextView에 Dynamic Type 활성화
let label = UILabel()
label.font = UIFont.preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true
Interface Builder에서 텍스트 스타일을 설정하고 Dynamic Type 지원 옵션을 활성화합니다.
Android에서 폰트 크기 조절 기능 구현 방법
TextView에서 글꼴 크기 반영
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
android:textSize="16sp" />
글꼴 크기 조절 기능을 지원하도록 설정
textView.textSize = resources.getDimension(R.dimen.default_text_size) * context.resources.configuration.fontScale
HTML
<div id="content">텍스트 콘텐츠 예제</div>
<button onclick="changeFontSize('small')">폰트 작게</button>
<button onclick="changeFontSize('medium')">기본 크기</button>
<button onclick="changeFontSize('large')">폰트 크게</button>
<div id="toast" aria-live="polite" class="toast-message"></div>
<script>
function changeFontSize(size) {
const content = document.getElementById('content');
if (size === 'small') {
content.style.fontSize = '12px';
showToast('폰트가 작게 설정되었습니다.');
} else if (size === 'medium') {
content.style.fontSize = '16px';
showToast('기본 폰트 크기가 설정되었습니다.');
} else if (size === 'large') {
content.style.fontSize = '20px';
showToast('폰트가 크게 설정되었습니다.');
}
}
function showToast(message) {
const toast = document.getElementById('toast');
toast.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
toast.textContent = '';
}, 3000);
if (window.speechSynthesis) {
const utterance = new SpeechSynthesisUtterance(message);
window.speechSynthesis.speak(utterance);
}
}
</script>
<style>
.toast-message {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 5px;
display: none;
}
.toast-message.show {
display: block;
}
</style>
Vue
<template>
<div>
<p :style="{ fontSize: fontSize }">텍스트 콘텐츠 예제</p>
<button @click="changeFontSize('small')">폰트 작게</button>
<button @click="changeFontSize('medium')">기본 크기</button>
<button @click="changeFontSize('large')">폰트 크게</button>
<div ref="toast" aria-live="polite" class="toast-message"></div>
</div>
</template>
<script>
export default {
data() {
return {
fontSize: '16px',
toastMessage: ''
};
},
methods: {
changeFontSize(size) {
if (size === 'small') {
this.fontSize = '12px';
this.showToast('폰트가 작게 설정되었습니다.');
} else if (size === 'medium') {
this.fontSize = '16px';
this.showToast('기본 폰트 크기가 설정되었습니다.');
} else if (size === 'large') {
this.fontSize = '20px';
this.showToast('폰트가 크게 설정되었습니다.');
}
},
showToast(message) {
this.toastMessage = message;
setTimeout(() => {
this.toastMessage = '';
}, 3000);
if (window.speechSynthesis) {
const utterance = new SpeechSynthesisUtterance(message);
window.speechSynthesis.speak(utterance);
}
}
}
};
</script>
<style>
.toast-message {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 5px;
display: none;
}
.toast-message:empty {
display: none;
}
</style>
React
import React, { useState } from 'react';
function App() {
const [fontSize, setFontSize] = useState('16px');
const [toastMessage, setToastMessage] = useState('');
const changeFontSize = (size) => {
if (size === 'small') {
setFontSize('12px');
showToast('폰트가 작게 설정되었습니다.');
} else if (size === 'medium') {
setFontSize('16px');
showToast('기본 폰트 크기가 설정되었습니다.');
} else if (size === 'large') {
setFontSize('20px');
showToast('폰트가 크게 설정되었습니다.');
}
};
const showToast = (message) => {
setToastMessage(message);
setTimeout(() => {
setToastMessage('');
}, 3000);
if (window.speechSynthesis) {
const utterance = new SpeechSynthesisUtterance(message);
window.speechSynthesis.speak(utterance);
}
};
return (
<div>
<p style=>텍스트 콘텐츠 예제</p>
<button onClick={() => changeFontSize('small')}>폰트 작게</button>
<button onClick={() => changeFontSize('medium')}>기본 크기</button>
<button onClick={() => changeFontSize('large')}>폰트 크게</button>
<div aria-live="polite" className="toast-message">{toastMessage}</div>
</div>
);
}
export default App;
<style>
.toast-message {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 5px;
display: none;
}
.toast-message:empty {
display: none;
}
</style>
오류 유형
주의사항
iOS
Android
NULI 모바일 앱 접근성 (17. 폰트 관련 기능의 활용)
Lighthouse
Lighthouse is an open-source, automated tool for improving the quality of web pages.
Lighthouse는 구글에서 제공하는 웹 페이지 품질 개선을 위한 오픈 소스로 자동화 도구입니다. Lighthouse는 사이트의 성능, 접근성, SEO 등에 대한 전반적인 진단을 해줍니다.
상세 설명 Lighthouse Overview 공식 문서 참조
WAVE
WAVE는 WebAIM에서 만든 확장 프로그램으로 현재 화면의 각 요소가 접근성을 준수하는지 평가합니다. 각 요소가 위반한 내용에 대한 이유와 해결 방법을 제시하여 접근성을 준수하는 개발을 쉽게 할 수 있도록 돕습니다.
Accessibility Scanner (Android)
Accessibility Scanner는 Android 기기에서 접근성 문제를 탐지하는 Google Play의 앱입니다.
접근성 트리 뷰(Accessibility Tree)
스크린 리더와 같은 보조 기술은 크로미움의 접근성 API를 사용해 웹콘텐츠와 상호 작용합니다. 접근성 API의 기본 모델은 접근성 트리입니다. 접근성 객체의 트리를 통해 보조 기술은 각 속성과 실제 속성값을 탐색하고 필요한 작업을 수행할 수 있습니다. 웹 개발자는 주로 HTML에서 ARIA 속성과 같은 DOM 속성값을 통해 접근성 트리를 만들고 이를 다룹니다.
크롬 개발자 도구에서는 개발자에게 콘텐츠가 보조 기술에 어떤 식으로 전달되는지 이해할 수 있게 접근성 창을 제공하고 있습니다. DOM 트리 뷰어에서 노드를 선택하면 해당하는 접근성 노드의 속성 정보가 상위 노드, 직계 자식 노드와 함께 창에 표시됩니다.
Accessibility Scanner (Android)
Accessibility Scanner는 Android 기기에서 접근성 문제를 탐지하는 Google Play의 앱입니다.
VSCode 확장 접근성 검사(axe Accessibility Linter)
VSCode 사용 시 별도 확장 설치 후 소스 코드에서 잘못 작성된 부분을 사전에 감지하여 수정할 수 있습니다.
eslint-plugin-jsx-a11y(ReactJS + ESLint)
접근성 오류 부분이 있는지 분석해 주는 플러그인이며 서비스 개발 환경이 React라면 실시간으로 JSX 요소에 대한 접근성 규칙을 확인하고 준수할 수 있도록 돕는 패키지를 설치해 개발할 수 있습니다. 기본적으로 추천되는 규칙 외에 예외로 사용하고 싶은 부분이 있다면 같이 서비스를 개발하는 개발자들과 협의하면서 lint 규칙을 만들어가다 보면 접근성을 준수하는 서비스 개발에 도움이 될 것입니다.
규칙 상세 설명 : jsx-eslint/eslint-plugin-jsx-a11y
사용법
eslint를 전역 설치했다면, eslint-plugin-jsx-a11y 플러그인도 전역으로 설치.
npm install eslint-plugin-jsx-a11y
// 또는
yarn add eslint-plugin-jsx-a11y
.eslintrc.json 파일에 다음과 같이 추가한다.
{
"extends": "plugin:jsx-a11y/recommended",
"plugins": "jsx-a11y",
"rules": {
"jsx-a11y/aria-role": [
"error",
{
"allowedInvalidRoles": ["text"],
"ignoreNonDOM": true
}
]
}
}
iOS : Accessibility Inspector
iOS 앱 개발도구인 xcode에는 Accessibility Inspector 툴을 통해 접근성을 수동 검사할 수 있습니다.
Android : Lint
Android 앱 개발도구인 Android Studio 의 Lint를 통해 개발과정에서 접근성을 수동 검사할 수 있습니다.
접근성은 시작은 있지만 끝이 없는 작업입니다.
오류 항목을 정기적으로 점검하여 접근성 개선을 한다면 점차 검사를 할 항목이 줄어들게 될 것입니다. 모두가 차별 없이 서비스를 이용할 수 있도록 접근성 유지를 위한 모두의 노력이 필요합니다. 무엇보다 접근성 작업은 서비스를 제공한다면 선택이 아닌 필수로 지켜야하는 항목임을 잊지 말아야 합니다.
접근성 작업 시 점검 필수사항