색상만으로 정보를 전달하고 있지 않은가?
이전 글에서 스크린 리더와 키보드 내비게이션을 다뤘습니다. 하지만 접근성은 시각 장애에만 국한되지 않습니다. 저시력 , 색맹 , 전정 장애 등 시각적 요소와 관련된 접근성 문제도 중요합니다.
이번 글에서는 세 가지 질문을 던집니다.
- 텍스트를 읽을 수 있는가?, 대비 비율
- 색을 구분하지 못해도 정보를 얻을 수 있는가?, 색맹 고려
- 움직이는 요소가 불편하지 않은가?, 모션 감소
색 대비 기준: WCAG AA와 AAA
WCAG (Web Content Accessibility Guidelines) 는 텍스트와 배경 사이의 대비 비율 (contrast ratio) 을 구체적인 숫자로 규정합니다.
| 수준 | 일반 텍스트 | 큰 텍스트 (24px+ 또는 18.66px 볼드) | UI 컴포넌트 |
|---|---|---|---|
| AA | 4.5 : 1 | 3 : 1 | 3 : 1 |
| AAA | 7 : 1 | 4.5 : 1 | - |
대비 비율의 범위는 1:1 (동일 색상) 에서 21:1 (흰색 위 검정) 까지입니다. 비율이 높을수록 읽기 쉽습니다.
대비 비율 = (밝은 색의 상대 휘도 + 0.05) / (어두운 색의 상대 휘도 + 0.05)
예) 흰색(#fff)과 회색(#767676)
L_white = 1.0, L_gray = 0.176
비율 = (1.0 + 0.05) / (0.176 + 0.05) = 4.54:1 → AA 통과아래 시각화에서 각 대비 수준이 실제로 어떻게 보이는지 확인하세요. 마지막 단계에서는 색상만으로 정보를 전달할 때의 문제도 함께 보여줍니다.
색맹 고려
전 세계 남성의 약 8% , **여성의 약 0.5%**가 색각 이상을 가지고 있습니다. 가장 흔한 유형은 적록 색맹으로, 빨간색과 초록색을 구분하기 어렵습니다.
| 유형 | 영향 | 비율 (남성) |
|---|---|---|
| 제1색맹 (Protanopia) | 빨간색 인식 불가 | ~1% |
| 제2색맹 (Deuteranopia) | 초록색 인식 불가 | ~1% |
| 제1색약 (Protanomaly) | 빨간색 인식 감소 | ~1% |
| 제2색약 (Deuteranomaly) | 초록색 인식 감소 | ~5% |
실무에서의 원칙:
- 색상에만 의존하지 말 것 , 아이콘, 패턴, 텍스트를 함께 사용
- 성공/실패를 빨강/초록으로만 표시하지 말 것, ✓/✕ 아이콘 병행
- 그래프에서 색 구분이 어려우면 패턴 (빗금, 점선) 을 추가
- 링크를 색상만으로 구분하지 말 것, 밑줄을 함께 사용
/* ❌ 색상만으로 링크 구분 */
a { color: blue; text-decoration: none; }
/* ✅ 밑줄 + 색상으로 구분 */
a { color: blue; text-decoration: underline; }대비 검사 도구
대비 비율을 직접 계산할 필요는 없습니다. 도구를 사용하세요.
Chrome DevTools , Elements 패널에서 색상 값을 클릭하면 대비 비율이 표시됩니다. AA/AAA 통과 여부도 함께 보여줍니다.
WebAIM Contrast Checker , 전경색과 배경색을 입력하면 즉시 대비 비율을 계산합니다. 가장 많이 사용되는 온라인 도구입니다.
Lighthouse , Chrome DevTools의 Lighthouse 탭에서 접근성 감사를 실행하면 대비 문제를 자동으로 찾아줍니다.
// 프로그래밍 방식으로 대비 비율 계산
function relativeLuminance(hex) {
const [r, g, b] = [1, 3, 5].map((i) => {
const c = parseInt(hex.slice(i, i + 2), 16) / 255;
return c <= 0.04045
? c / 12.92
: Math.pow((c + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
function contrastRatio(hex1, hex2) {
const l1 = relativeLuminance(hex1);
const l2 = relativeLuminance(hex2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
contrastRatio("#ffffff", "#767676"); // 4.54 → AA 통과모션 감소: prefers-reduced-motion
일부 사용자는 화면의 움직임으로 인해 어지러움, 메스꺼움, 두통을 겪습니다. 전정 장애 (vestibular disorders) 를 가진 사용자가 대표적입니다.
OS에서 "모션 줄이기" 설정을 켜면 CSS 미디어 쿼리 prefers-reduced-motion으로 감지할 수 있습니다.
/* 기본: 애니메이션 적용 */
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: scale(1.05);
}
/* 모션 줄이기 설정 시: 애니메이션 제거 또는 대체 */
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
.card:hover {
transform: none;
/* 대신 opacity 변경 같은 부드러운 대안 사용 */
opacity: 0.9;
}
}JavaScript에서도 확인할 수 있습니다.
// JS에서 모션 감소 설정 감지
const motionQuery = window.matchMedia(
"(prefers-reduced-motion: reduce)"
);
if (motionQuery.matches) {
// 애니메이션을 비활성화하거나 간소화
document.documentElement.classList.add("reduce-motion");
}
// 설정 변경 감지
motionQuery.addEventListener("change", (e) => {
if (e.matches) {
// 모션 감소 활성화됨
cancelAllAnimations();
}
});핵심 원칙:
- 모든 애니메이션을 없애는 것이 아니라, 과도한 모션 을 줄이는 것
- 페이드인/페이드아웃은 유지해도 됨, 회전, 확대/축소, 슬라이드는 줄이거나 제거
- 5초 이상 지속되는 애니메이션은 정지 버튼 제공
- 자동 재생 캐러셀은
prefers-reduced-motion: reduce에서 정지
다크 모드와 접근성
다크 모드를 지원한다고 접근성이 자동으로 좋아지는 것은 아닙니다. 다크 모드에서도 대비 비율을 유지 해야 합니다.
:root {
--text: #1a1a1a; /* 라이트: 거의 검정 */
--bg: #ffffff; /* 라이트: 흰색 */
/* 대비 비율: 약 17.4:1 ✅ */
}
@media (prefers-color-scheme: dark) {
:root {
--text: #e5e5e5; /* 다크: 밝은 회색 */
--bg: #171717; /* 다크: 거의 검정 */
/* 대비 비율: 약 15.4:1 ✅ */
}
}
/* ❌ 다크 모드에서 흔한 실수 */
@media (prefers-color-scheme: dark) {
:root {
--text: #888888; /* 너무 어두운 텍스트 */
--bg: #333333; /* 너무 밝은 배경 */
/* 대비 비율: 약 2.4:1 ❌ */
}
}텍스트 크기와 확대
WCAG 1.4.4는 텍스트를 200%까지 확대해도 콘텐츠가 유실되거나 기능이 깨지지 않아야 한다 고 규정합니다.
px대신rem을 사용하면 사용자가 브라우저 기본 글꼴 크기를 변경할 때 함께 조정됨- 본문 텍스트는 최소 16px (1rem) 을 권장
max-width를ch단위로 설정하면 줄당 문자 수를 제한해 가독성 향상
/* ❌ 고정 px, 사용자 설정 무시 */
body { font-size: 14px; }
/* ✅ rem, 사용자 브라우저 설정에 반응 */
body { font-size: 1rem; } /* 기본 16px */
h1 { font-size: 2rem; } /* 32px */
/* 줄 길이 제한으로 가독성 향상 */
article { max-width: 70ch; }시각 접근성 체크리스트
| 항목 | 기준 |
|---|---|
| 텍스트 대비 | 일반 4.5:1 이상, 큰 텍스트 (24px+) 3:1 이상 (AA) |
| UI 컴포넌트 대비 | 3:1 이상 |
| 색상만으로 정보 전달 | ❌ 아이콘/텍스트/패턴 병행 |
| 링크 구분 | 색상 + 밑줄 |
| prefers-reduced-motion | 과도한 모션 제거 또는 대체 |
| 다크 모드 대비 | 라이트 모드와 동일한 기준 유지 |
| 텍스트 크기 | rem 사용, 200% 확대 대응 |
| 줄 길이 | 70~80ch 이내 권장 |
다음 글: 폼과 에러 처리
시각적 접근성을 확보했다면, 이제 사용자가 실제로 상호작용 하는 폼을 살펴볼 차례입니다. 다음 글에서는 label 연결, 에러 메시지 전달, aria-live를 다룹니다.