UI를 완성하고 Lighthouse를 실행했더니 갑자기 6개의 색상 쌍이 WCAG AA를 통과하지 못할 때
요약
UI 개발 마지막 단계에서 발생하는 웹 접근성 문제를 방지하기 위해, 디자인 토큰 생성 단계에서 WCAG 대비비를 자동으로 검사하는 salt-theme-gen 도구를 소개합니다. CSS 작성 전 토큰 조합의 가독성을 미리 검증하여 개발 효율성을 높일 수 있습니다.
핵심 포인트
- 디자인 토큰 생성 시 18개의 WCAG 2.1 대비비 검사 수행
- 텍스트 가독성, 브랜드 색상, 의미론적 색상 등 다양한 항목 검증
- OKLCH 색상 체계를 활용한 자동 수정 기능 지원
- CI 환경에서 접근성 위반 여부를 사전에 차단 가능
접근성 감사 (Accessibility audits)는 보통 마지막 단계에서 이루어집니다. 배포된 사이트에서 도구를 실행하면 수십 개의 저대비 텍스트/배경 조합이 발견되고, 이제 당신은 몇 달 전에 이미 결정된 값들을 수정하기 위해 컴포넌트 스타일을 역추적해야 합니다.
salt-theme-gen은 컴포넌트가 구축되기 전, 토큰 생성 시점에 18개의 WCAG 2.1 대비비 (contrast ratio) 검사를 실행합니다. 토큰 조합이 실패하면, CSS를 한 줄도 작성하기 전에 미리 알 수 있습니다.
검사 항목
const theme = generateTheme({ preset: 'ocean' });
const { accessibility } = theme.light;
모든 검사는 { ratio: number; level: 'AAA' | 'AA' | 'fail' } 객체로 반환됩니다:
accessibility.primaryOnBackground
// { ratio: 4.51, level: 'AA' }
...
18개의 검사 + OKLCH 자동 수정 + CI 친화적인 보고서:
텍스트 가독성 (Text legibility) (2개):
textOnBackground— 페이지 배경 위의 본문 텍스트textOnSurface— 카드/입력창 표면 위의 본문 텍스트
배경 위의 브랜드 색상 (Brand colors on background) (4개):
primaryOnBackground— 배경 위의 텍스트/아이콘으로서의 기본 강조색 (primary accent)secondaryOnBackground— 배경 위의 텍스트/아이콘으로서의 보조 강조색 (secondary accent)tertiaryOnBackground— 배경 위의 텍스트/아이콘으로서의 3차 강조색 (tertiary accent)quaternaryOnBackground— 배경 위의 텍스트/아이콘으로서의 4차 강조색 (quaternary accent)
색상 위의 텍스트 — 버튼/배지 라벨 (On-color text — button/badge labels) (4개):
onPrimaryOnPrimary— 기본 버튼 (primary button) 내부의 텍스트onSecondaryOnSecondary— 보조 버튼 (secondary button) 내부의 텍스트onTertiaryOnTertiary— 3차 버튼 (tertiary button) 내부의 텍스트onQuaternaryOnQuaternary— 4차 버튼 (quaternary button) 내부의 텍스트
배경 위의 의미론적 색상 (Semantic colors on background) (4개):
dangerOnBackground,successOnBackground,warningOnBackground,infoOnBackground
의미론적 전경색 위의 텍스트 (On-semantic foregrounds) (4개):
onDangerOnDanger,onSuccessOnSuccess,onWarningOnWarning,onInfoOnInfo
모든 내장 프리셋(presets)은 모든 검사 항목에 대해 WCAG AA를 통과합니다. 많은 항목이 AAA를 통과합니다.
CI에서 빠르게 실패하기 (Fail fast in CI)
접근성 보고서는 단순한 JavaScript입니다. Node.js가 실행되는 곳이라면 어디에서든 이를 검증(assert)할 수 있습니다:
import { generateTheme } from 'salt-theme-gen';
const theme = generateTheme({ preset: 'ocean' });
...
package.json에 추가:
{
"scripts": {
"check:a11y": "node scripts/check-accessibility.mjs"
...```
또는 빌드 전 단계(pre-build step)로 추가할 수 있습니다. 접근성(accessibility) 검사에 실패하면 빌드도 실패하게 됩니다.
## 커스텀 색상을 사용할 때 발생하는 일
프리셋(preset) 대신 헥스(hex) 색상을 전달하더라도, `salt-theme-gen`은 여전히 검사를 수행합니다:
const theme = generateTheme({ primary: '#f59e0b' }); // amber
const { accessibility } = theme.light;
...
생성된 색상이 AA 대비(contrast)를 통과하지 못할 경우, `salt-theme-gen`은 색조(hue)와 채도(chroma)를 유지하면서 OKLCH 밝기(lightness)를 조정하여 자동으로 수정합니다. 수동으로 조정할 필요 없이, 입력값과 가장 유사하면서도 기준을 통과하는 색상을 얻을 수 있습니다.
## 다크 모드도 확인하기
다크 모드(dark mode)에는 별도의 접근성 검증이 필요합니다. 라이트 모드(light mode)에서 통과하는 색상이 다크 모드에서는 실패할 수 있기 때문입니다:
const lightFailures = Object.entries(theme.light.accessibility)
.filter(([, c]) => c.level === 'fail');
...
모든 내장 프리셋은 두 모드 모두에서 통과합니다.
## 수동 대비 검사
토큰 시스템 외부의 색상 — 일러스트레이션, 차트 색상, 서드파티(third-party) 컴포넌트 등 — 의 경우:
import { contrastRatio } from 'salt-theme-gen';
const ratio = contrastRatio(
...
표준 18가지 검사 항목에 포함되지 않은 색상 조합을 확인하고 싶을 때 이 기능을 사용하세요.
## 결론
디자인 토큰(design tokens)의 색상 대비는 컴포넌트가 빌드되기 전에 처리할 수 있습니다. 모든 테마에 대해 18가지 WCAG 검사를 실행한다는 것은 다음을 의미합니다:
- 주니어 개발자도 프리셋을 변경한 후 통과 여부를 즉시 알 수 있습니다.
- CI(지속적 통합)가 배포 전에 대비(contrast) 회귀(regression)를 잡아냅니다.
- 다크 모드가 단순히 괜찮을 것이라고 가정하지 않고 별도로 검증합니다.
전체 문서: [learn.esalt.net/salt-theme-gen](https://learn.esalt.net/salt-theme-gen/)
_**salt-theme-gen — 모든 프레임워크를 위한 디자인 토큰**_ 시리즈의 일부 · 24개 중 3번째 기사*
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기