들어가며#
ChatGPT, Claude, Gemini… 생성형 AI가 우리 일상 깊숙이 들어온 시대입니다. 웹사이트마다 AI 챗봇이 자리를 잡았고, 콘텐츠 자동 생성도 이제 낯설지 않죠. 이렇게 빠르게 변화하는 기술 환경 속에서, 한 가지 중요한 질문을 던져보고 싶습니다.
“AI가 만든 웹, 과연 모든 사람이 사용할 수 있을까요?”
웹접근성(Web Accessibility)이란 장애를 가진 분들, 어르신들, 느린 인터넷 환경의 사용자 등 모든 사람이 웹을 동등하게 이용할 수 있도록 보장하는 것입니다. AI 시대에도, 아니 AI 시대이기에 더욱 웹접근성은 중요해지고 있습니다.
이 글에서는 AI 기술의 발전이 웹접근성에 어떤 영향을 미치는지, 그리고 개발자로서 우리가 꼭 알아야 할 핵심 원칙들을 실전 예제와 함께 살펴보겠습니다.
AI 시대, 웹접근성이 더 중요해진 이유#
1. AI 인터페이스가 점점 복잡해지고 있어요#
AI 챗봇, 음성 인터페이스, 제스처 기반 UI… 새로운 방식의 사용자 경험이 계속 등장하면서 웹은 점점 더 복잡해지고 있습니다.

사진: Zulfugar Karimov / Unsplash
<!-- 잘못된 예: AI 챗봇 버튼 -->
<div class="chat-button" onclick="openChat()">
<img src="chat-icon.png">
</div>
<!-- 올바른 예: 접근 가능한 AI 챗봇 버튼 -->
<button
type="button"
aria-label="AI 채팅 도우미 열기"
aria-expanded="false"
aria-controls="chat-widget"
onclick="openChat()">
<img src="chat-icon.png" alt="채팅 아이콘">
</button>스크린 리더를 사용하는 분들은 <div>로 만든 버튼을 버튼으로 인식하지 못합니다. 시맨틱 HTML과 ARIA 속성을 함께 사용해야 모두가 사용할 수 있는 인터페이스가 됩니다.
2. AI가 만든 코드, 겉만 번지르르할 수 있어요#
AI가 생성한 HTML은 시각적으로는 완벽해 보일 수 있습니다. 하지만 접근성 측면에서는 허점이 많은 경우가 많아요. AI는 이런 것들을 자주 놓칩니다:
- 대체 텍스트(alt) 누락
- 엉성한 헤딩 구조
- 키보드 포커스 순서 무시
- 색상 대비 부족
- ARIA 속성 잘못 사용
<!-- AI가 만든 코드 (문제가 있어요) -->
<div class="card">
<img src="product.jpg">
<div class="title">제품명</div>
<div class="price">29,900원</div>
<div class="button" onclick="buy()">구매하기</div>
</div>
<!-- 접근성을 고려한 코드 -->
<article class="card">
<img src="product.jpg" alt="무선 이어폰 블랙 색상">
<h3>무선 이어폰</h3>
<p><strong>가격:</strong> 29,900원</p>
<button type="button" onclick="buy()">구매하기</button>
</article>3. 자동화의 역설#
AI는 웹 개발을 자동화할 수 있지만, 접근성 테스트는 완전히 자동화하기 어렵습니다.
자동화 도구(Lighthouse, axe 등)는 기술적인 오류는 잘 찾아내지만, 이런 문제들은 발견하지 못합니다:
- 맥락에 맞지 않는 alt 텍스트
- 혼란스러운 네비게이션 구조
- 모호한 에러 메시지
- 시각적으로만 전달되는 중요한 정보
결국 사람의 판단이 꼭 필요합니다.
웹접근성의 핵심 원칙: WCAG 2.2#
W3C의 WCAG(Web Content Accessibility Guidelines) 2.2는 4가지 핵심 원칙을 제시합니다. 2023년 10월에 발표된 WCAG 2.2는 이전 버전(2.1)에 모바일 접근성과 저시력 사용자를 위한 기준을 추가로 강화했습니다.
1. 인식 가능성 (Perceivable)#
모든 사용자가 콘텐츠를 인식할 수 있어야 합니다.
대체 텍스트 제공하기#
<!-- 나쁜 예 -->
<img src="chart.png">
<!-- 좋은 예 -->
<img
src="chart.png"
alt="2024년 월별 매출 추이: 1월 100만원부터 12월 300만원까지 지속 상승">적절한 색상 대비 유지하기#
/* 나쁜 예: 대비율 2.5:1 (WCAG AA 기준 미달) */
.text {
color: #999999;
background: #ffffff;
}
/* 좋은 예: 대비율 4.5:1 이상 (WCAG AA 통과) */
.text {
color: #595959;
background: #ffffff;
}색상 대비율은 WebAIM Contrast Checker에서 확인할 수 있습니다.
멀티미디어에 자막 제공하기#
<video controls>
<source src="tutorial.mp4" type="video/mp4">
<track
kind="captions"
src="captions-ko.vtt"
srclang="ko"
label="한국어 자막">
<track
kind="captions"
src="captions-en.vtt"
srclang="en"
label="English Captions">
</video>2. 운용 가능성 (Operable)#
모든 기능을 마우스 없이 키보드만으로 조작할 수 있어야 합니다.

사진: BoliviaInteligente / Unsplash
키보드 포커스 잘 관리하기#
// AI 모달 열기
function openModal() {
const modal = document.getElementById('modal');
const closeButton = modal.querySelector('.close-button');
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
// 모달이 열리면 첫 번째 포커스 가능한 요소로 포커스 이동
closeButton.focus();
// 모달 내부에서만 탭 이동 (포커스 트랩)
trapFocus(modal);
}
// 포커스 트랩 함수
function trapFocus(element) {
const focusableElements = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
element.addEventListener('keydown', function(e) {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
// Shift + Tab: 역방향 이동
if (document.activeElement === firstElement) {
lastElement.focus();
e.preventDefault();
}
} else {
// Tab: 정방향 이동
if (document.activeElement === lastElement) {
firstElement.focus();
e.preventDefault();
}
}
});
}본문 바로가기 링크 만들기#
<!-- 페이지 최상단에 배치 -->
<a href="#main-content" class="skip-link">
본문으로 바로가기
</a>
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
z-index: 9999;
}
.skip-link:focus {
top: 0; /* 포커스 시 나타남 */
}
</style>WCAG 2.2 신규: 포커스 표시 강화 (2.4.11, 2.4.13)#
WCAG 2.2에서는 포커스 인디케이터의 최소 크기와 명확성을 규정하는 기준이 추가되었습니다.
/* 포커스 표시 최소 기준 충족 */
button:focus,
a:focus,
input:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
/* 최소 2px 두께, 요소 경계에서 2px 떨어진 위치 */
}
/* 대비율 3:1 이상 확보 */
.dark-theme button:focus {
outline-color: #4d94ff; /* 어두운 배경에서도 충분한 대비 */
}3. 이해 가능성 (Understandable)#
콘텐츠와 인터페이스가 명확하고 예측 가능해야 합니다.
명확한 에러 메시지 제공하기#
<!-- 나쁜 예 -->
<form>
<input type="email" required>
<span class="error">잘못된 입력</span>
</form>
<!-- 좋은 예 -->
<form>
<label for="email">이메일 주소</label>
<input
type="email"
id="email"
aria-describedby="email-error"
aria-invalid="true"
required>
<span id="email-error" class="error" role="alert">
올바른 이메일 형식이 아닙니다. 예: [email protected]
</span>
</form>WCAG 2.2 신규: 일관된 도움말 (3.2.6)#
웹사이트 전반에 걸쳐 도움말이나 연락 방법을 일관된 위치에 제공해야 합니다.
<!-- 모든 페이지에서 동일한 위치에 도움말 배치 -->
<nav aria-label="주요 메뉴">
<ul>
<li><a href="/">홈</a></li>
<li><a href="/about">소개</a></li>
<li><a href="/services">서비스</a></li>
<li><a href="/help">도움말</a></li> <!-- 항상 동일한 순서 -->
</ul>
</nav>4. 견고성 (Robust)#
다양한 보조 기술과 호환되어야 합니다.
시맨틱 HTML 사용하기#
<!-- 나쁜 예: div 남발 -->
<div class="header">
<div class="nav">...</div>
</div>
<div class="main">
<div class="article">...</div>
</div>
<div class="footer">...</div>
<!-- 좋은 예: 시맨틱 HTML -->
<header>
<nav aria-label="주요 메뉴">...</nav>
</header>
<main>
<article>...</article>
</main>
<footer>...</footer>ARIA를 올바르게 사용하기#
<!-- ARIA 사용 원칙: 시맨틱 HTML이 우선 -->
<!-- 나쁜 예: 불필요한 ARIA -->
<button role="button">클릭</button>
<!-- 좋은 예: 시맨틱 HTML만으로 충분 -->
<button>클릭</button>
<!-- ARIA가 필요한 경우: 커스텀 위젯 -->
<div
role="tablist"
aria-label="계정 설정">
<button
role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1">
프로필
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2">
보안
</button>
</div>AI 시대 웹접근성 체크리스트#
AI와 함께 웹을 개발할 때 이 체크리스트를 확인해보세요:

사진: Jakub Żerdzicki / Unsplash
HTML 구조#
- 모든 이미지에 의미있는
alt텍스트 제공 - 헤딩(
<h1>~<h6>)이 논리적 순서로 구성됨 - 시맨틱 HTML 사용 (
<header>,<nav>,<main>,<article>,<footer>) - 폼 요소에
<label>연결 (for/id또는 중첩) - 링크 텍스트가 명확함 (“여기 클릭” 같은 모호한 표현 지양)
키보드 접근성#
- 모든 인터랙티브 요소가 키보드로 접근 가능
- 포커스 순서가 논리적
- 포커스 표시가 명확 (최소 2px, 대비율 3:1 이상 - WCAG 2.2)
- 모달/드롭다운에서 포커스 트랩 구현
- Esc 키로 닫기 기능 구현
ARIA 사용#
-
role,aria-label,aria-labelledby적절히 사용 - 동적 콘텐츠 변경 시
aria-live사용 - 확장/축소 상태를
aria-expanded로 표시 - 에러 메시지에
role="alert"사용
시각적 디자인#
- 색상 대비율 WCAG AA 기준 충족 (4.5:1 이상)
- 색상만으로 정보 전달하지 않음
- 텍스트 크기 조정 가능 (최소 200%까지)
- 포커스 인디케이터가 시각적으로 명확 (WCAG 2.2 강화)
멀티미디어#
- 비디오에 자막 제공
- 오디오 콘텐츠에 대본 제공
- 자동 재생 금지 또는 제어 옵션 제공
모바일 접근성 (WCAG 2.2 강화)#
- 터치 타겟 크기 최소 24x24px (2.5.8)
- 드래그 동작에 대한 대체 방법 제공 (2.5.7)
테스트#
- 키보드만으로 전체 사이트 탐색 테스트
- 스크린 리더(NVDA, JAWS, VoiceOver)로 테스트
- 자동화 도구(Lighthouse, axe DevTools) 실행
- 가능하다면 실제 사용자 테스트
AI를 활용한 웹접근성 개선#
AI는 양날의 검입니다. 잘못 사용하면 접근성을 해치지만, 올바르게 활용하면 접근성을 크게 향상시킬 수 있어요.
1. AI로 대체 텍스트 생성하기#
// OpenAI Vision API를 활용한 alt 텍스트 생성
async function generateAltText(imageUrl) {
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "user",
content: [
{
type: "text",
text: "이 이미지를 시각장애인이 이해할 수 있도록 상세히 설명해주세요. 100자 이내로 작성하세요."
},
{
type: "image_url",
image_url: { url: imageUrl }
}
]
}
]
});
return response.choices[0].message.content;
}
// 사용 예시
const altText = await generateAltText("https://example.com/chart.png");
// 결과: "2024년 매출 추이를 보여주는 선 그래프. 1월 100만원에서 시작하여 12월 300만원까지 꾸준히 증가하는 추세를 나타냄"
주의할 점: AI가 생성한 alt 텍스트는 반드시 사람이 검토해야 합니다. 맥락을 놓치거나 중요한 정보를 빠뜨릴 수 있거든요.
2. 접근 가능한 AI 챗봇 만들기#
<!-- 접근 가능한 AI 챗봇 위젯 -->
<div
id="chat-widget"
role="region"
aria-label="AI 고객 지원 채팅"
aria-live="polite">
<div
id="chat-messages"
role="log"
aria-live="polite"
aria-atomic="false">
<!-- 메시지가 여기에 추가됨 -->
</div>
<form onsubmit="sendMessage(event)">
<label for="chat-input" class="visually-hidden">
메시지 입력
</label>
<input
type="text"
id="chat-input"
aria-describedby="chat-help"
placeholder="메시지를 입력하세요">
<span id="chat-help" class="visually-hidden">
AI 봇과 대화할 수 있습니다. 엔터키를 눌러 전송하세요.
</span>
<button type="submit">전송</button>
</form>
</div>
<style>
/* 시각적으로 숨기지만 스크린 리더는 읽을 수 있는 텍스트 */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
</style>3. 스크린 리더를 위한 음성 안내#
// Web Speech API를 활용한 음성 안내
function announceToScreenReader(message) {
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', 'polite');
announcement.classList.add('visually-hidden');
announcement.textContent = message;
document.body.appendChild(announcement);
// 1초 후 제거 (스크린 리더가 읽을 시간 확보)
setTimeout(() => {
document.body.removeChild(announcement);
}, 1000);
}
// 사용 예시
announceToScreenReader('새 메시지가 도착했습니다.');법적 요구사항과 비즈니스 가치#
법적 의무#
한국에서는 장애인차별금지법에 따라 다음 웹사이트는 웹접근성 준수가 의무입니다:
- 공공기관 웹사이트
- 일정 규모 이상의 법인 (매출액 또는 사업체 규모 기준)
- 특수학교, 장애인 복지시설
위반 시 과태료 및 시정 명령을 받을 수 있습니다.
비즈니스 가치#
웹접근성은 단순히 법적 의무만이 아닙니다. 실제 비즈니스 가치도 제공해요:
- 더 많은 사용자 확보: 전 세계 인구의 약 15%(약 10억 명)가 어떤 형태로든 장애를 가지고 있습니다.
- SEO 향상: 시맨틱 HTML과 명확한 구조는 검색 엔진 최적화에도 도움이 됩니다.
- 모바일 UX 개선: 터치 타겟 크기, 명확한 라벨 등은 모바일 사용성도 높여줍니다.
- 유지보수 용이: 잘 구조화된 코드는 수정과 확장이 훨씬 쉽습니다.
- 브랜드 이미지: 포용적인 브랜드 이미지를 구축할 수 있습니다.
실전 예제: AI 검색 인터페이스 개선하기#
실제 사례로 AI 검색 기능의 접근성을 개선해볼게요.
Before: 접근성 문제가 있는 코드#
<div class="search-container">
<div class="search-icon">🔍</div>
<div class="search-input" contenteditable="true">검색어 입력</div>
<div class="ai-suggestions">
<div onclick="selectSuggestion('React')">React</div>
<div onclick="selectSuggestion('Vue')">Vue</div>
<div onclick="selectSuggestion('Angular')">Angular</div>
</div>
</div>문제점:
- 시맨틱 HTML을 사용하지 않음
- 키보드로 조작할 수 없음
- 스크린 리더가 상태 변화를 인지하지 못함
- ARIA 속성이 없음
After: 접근성 개선 코드#
<div class="search-container" role="search">
<label for="search-input" class="visually-hidden">
AI 검색
</label>
<div class="search-wrapper">
<span aria-hidden="true">🔍</span>
<input
type="text"
id="search-input"
role="combobox"
aria-expanded="true"
aria-autocomplete="list"
aria-controls="suggestions-list"
aria-activedescendant="suggestion-0"
placeholder="검색어를 입력하세요"
onkeydown="handleKeyNavigation(event)"
oninput="updateSuggestions()">
</div>
<ul
id="suggestions-list"
role="listbox"
aria-label="AI 추천 검색어">
<li
id="suggestion-0"
role="option"
aria-selected="true"
onclick="selectSuggestion('React')"
onkeydown="handleSelection(event)">
React
</li>
<li
id="suggestion-1"
role="option"
aria-selected="false"
onclick="selectSuggestion('Vue')">
Vue
</li>
<li
id="suggestion-2"
role="option"
aria-selected="false"
onclick="selectSuggestion('Angular')">
Angular
</li>
</ul>
</div>
<script>
function handleKeyNavigation(event) {
const list = document.getElementById('suggestions-list');
const options = list.querySelectorAll('[role="option"]');
const currentIndex = Array.from(options).findIndex(
opt => opt.getAttribute('aria-selected') === 'true'
);
let newIndex = currentIndex;
switch(event.key) {
case 'ArrowDown':
newIndex = Math.min(currentIndex + 1, options.length - 1);
event.preventDefault();
break;
case 'ArrowUp':
newIndex = Math.max(currentIndex - 1, 0);
event.preventDefault();
break;
case 'Enter':
selectSuggestion(options[currentIndex].textContent);
event.preventDefault();
return;
case 'Escape':
document.getElementById('search-input').setAttribute('aria-expanded', 'false');
list.style.display = 'none';
return;
}
// 선택 상태 업데이트
options.forEach((opt, idx) => {
opt.setAttribute('aria-selected', idx === newIndex ? 'true' : 'false');
});
// aria-activedescendant 업데이트
document.getElementById('search-input').setAttribute(
'aria-activedescendant',
options[newIndex].id
);
// 스크린 리더 안내
announceToScreenReader(options[newIndex].textContent);
}
function selectSuggestion(value) {
document.getElementById('search-input').value = value;
document.getElementById('search-input').setAttribute('aria-expanded', 'false');
document.getElementById('suggestions-list').style.display = 'none';
announceToScreenReader(`${value} 선택됨`);
}
</script>개선 사항:
- ✅ 시맨틱 HTML 사용 (
<input>,<ul>,<li>) - ✅ 키보드 내비게이션 (화살표, Enter, Esc)
- ✅ ARIA 속성으로 상태 전달
- ✅ 스크린 리더 안내 (
aria-live) - ✅ 명확한 레이블
마치며: 기술과 인간성의 균형#
AI 기술은 정말 빠르게 발전하고 있습니다. 하지만 웹의 본질은 변하지 않았어요. 웹은 정보와 서비스를 모든 사람에게 평등하게 제공하기 위해 만들어졌습니다.

사진: Possessed Photography / Unsplash
웹접근성은 선택이 아닌 필수입니다. 몇 가지만 기억해주세요:
- 시맨틱 HTML이 기본: AI가 만든 코드를 맹신하지 말고 항상 시맨틱 HTML을 우선하세요.
- 키보드 접근성: 모든 기능이 마우스 없이도 작동해야 합니다.
- 명확한 피드백: 사용자 행동에 대한 피드백을 시각적, 청각적으로 제공하세요.
- 테스트는 필수: 자동화 도구와 실제 사용자 테스트를 병행하세요.
- 지속적인 개선: 웹접근성은 한 번 구현하고 끝이 아니라 계속 개선해나가는 과정입니다.
AI 시대에도, 아니 AI 시대이기에 사람 중심의 웹을 만들어야 합니다. 우리가 만드는 웹이 누군가의 세상을 열어줄 수 있다는 것, 잊지 말았으면 좋겠습니다.
