
접근성 검사에서 206개가 걸렸는데 원인은 넷이었습니다
글을 스무 편 가까이 쓰는 동안 접근성 검사를 한 번도 안 돌려봤습니다.
돌려봤습니다.
검사는 열 줄이면 됩니다
axe라는 검사기를 브라우저에 주입해서 페이지를 훑게 하는 방식입니다.
import { chromium } from 'playwright';
import fs from 'node:fs';
const axe = fs.readFileSync(
'node_modules/axe-core/axe.min.js',
'utf8',
);
const p = await browser.newPage({
colorScheme: 'light',
});
await p.goto('http://127.0.0.1:4500/blog/');
await p.addScriptTag({ content: axe });
const r = await p.evaluate(
async () => await window.axe.run(document),
);
console.log(r.violations);
빌드된 사이트를 로컬에 띄워놓고 돌렸습니다. 홈, 글 목록, 글 페이지, About, 개인정보처리방침, 태그 페이지, 404 일곱 곳을 라이트와 다크 두 모드로, 그러니까 열네 번 검사했습니다.
걸린 건 한 종류였습니다

위반 규칙 1종
[serious] color-contrast
Elements must meet minimum
color contrast ratio thresholds
색 대비 하나였습니다. 대체 텍스트, 헤딩 순서, 링크 이름, 문서 언어 설정 같은 건 다 통과했습니다.
이건 운이 아니었습니다. 대체 텍스트는 글머리에 칸을 따로 만들어두고 매번 채웠고, 본문 바로가기 링크도 처음부터 있었습니다. 이미 신경 쓴 것만 통과했고, 신경 안 쓴 게 정확히 하나 걸린 겁니다.
그 하나가 요소 206개에서 나왔습니다. 색 조합으로 묶으면 다섯 가지였고요.
| 어디 | 대비 | 요소 |
|---|---|---|
| 태그 칩 | 4.02 | 129 |
| 카드 안 날짜 | 4.45 | 38 |
| 본문 날짜·메타 | 4.27 | 29 |
| 코드 블록 주석 | 3.04 | 8 |
| 강조 문구·404 코드 | 2.49 / 3.01 | 2 |
기준은 4.5:1입니다. 본문 크기 글자에 적용되는 값입니다.
원인 1. opacity가 대비를 깎고 있었습니다
날짜와 읽기 시간에 쓰는 스타일이 이랬습니다.
.meta {
color: var(--ink-soft);
opacity: 0.85;
}
--ink-soft는 #5c5d74인데, 검사기가 잡아낸 색은 #747487이었습니다. 투명도가 배경색과 섞이면서 실제로는 더 밝은 색이 된 겁니다.
숫자로 보면 이렇습니다.
#5c5d74 (opacity 없이) → 6.00 : 1 통과
#747487 (opacity 0.85) → 4.27 : 1 미달
여기서 좀 허무했습니다. “살짝 흐리게 보이게” 하려고 쓴 한 줄이 정확히 대비를 깎는 동작이었습니다. 흐리다는 건 배경에 가까워진다는 뜻이고, 그게 대비가 낮다는 말과 같은 말이니까요.
카드 안에서는 더 아슬아슬했습니다. 4.45. 기준에서 0.05 모자랍니다. 눈으로는 절대 못 잡습니다.
opacity 줄을 지웠습니다. 흐리게 보이고 싶으면 변수 자체를 조정하는 게 맞습니다.
원인 2. 같은 색인데 배경이 두 개였습니다
태그 칩이 129개로 제일 많이 걸렸습니다. 글자색은 --accent-dark입니다.
--accent-dark #8f6527
종이 배경 #faf7f1 위 → 4.84 : 1 통과
칩 배경 #eee2c8 위 → 4.02 : 1 미달
같은 색인데 어디 놓이느냐에 따라 갈립니다. 저는 이 색을 정할 때 종이 배경만 보고 정했습니다. 칩에는 따로 배경색을 깔아놨다는 걸 잊고 있었습니다.
색은 혼자 못 정합니다. 항상 배경과 한 쌍입니다. 변수 이름에 dark라고 붙여놨다고 어디서나 어두운 게 아닙니다.
#7d5921로 내렸습니다. 칩 위에서 4.92, 종이 위에서 5.91입니다. 기준선에 딱 맞추면 나중에 배경을 조금만 건드려도 다시 떨어지니 여유를 뒀습니다.
원인 3. 제 CSS 밖에 있던 색
코드 블록 주석이 #6a737d, 배경이 #24292e. 3.04입니다.
이건 제가 쓴 색이 아닙니다. 문법 강조 테마(github-dark)가 정한 색이고, 빌드할 때 이렇게 박혀 나옵니다.
<span style="color:#6A737D">
// store/user/actions.ts
</span>
style 속성에 직접 들어갑니다. 클래스가 없어서 평범한 CSS로는 못 잡습니다.
테마를 통째로 바꾸는 선택지도 있었는데, 그러면 나머지 색이 전부 바뀝니다. 주석 하나 때문에 코드 블록 전체 인상을 바꾸고 싶지는 않았습니다. 그래서 색값을 직접 겨냥했습니다.
.astro-code span[style*="#6A737D" i] {
color: #8b949e !important;
}
깔끔하지 않습니다. 테마를 바꾸면 이 줄도 같이 손봐야 하고, !important도 반갑지 않습니다. 그래서 왜 이렇게 했는지 주석으로 길게 남겨뒀습니다. 반년 뒤의 제가 “이건 뭐지” 하고 지울 테니까요.
원인 4. 강조색을 본문 글자로 썼습니다
제일 나쁜 값이 여기서 나왔습니다. 2.49.
--accent는 금색 계열이라 종이 위에서 3.01밖에 안 나옵니다. 큰 제목이나 테두리, 아이콘에는 써도 되는 색인데 본문 크기 글자에는 못 쓰는 색입니다. 저는 그걸 목록 위 작은 강조 문구와 404 페이지 코드 자리에 쓰고 있었습니다.
거기에 앞에서 말한 opacity까지 겹쳐서 2.49가 된 겁니다.
--accent-dark로 바꿨습니다.
다크 모드는 거의 깨끗했습니다
다섯 가지 중 넷이 라이트 모드 전용이었습니다. 다크에서도 걸린 건 코드 주석 하나뿐이었고요.
확실한 이유는 모르겠지만, 짐작은 갑니다. 다크 모드는 배경이 확실히 어둡고 글자가 확실히 밝습니다. 중간 톤을 쓸 일이 없습니다. 반면 라이트 모드에서는 “너무 검지 않은 부드러운 회색”을 쓰고 싶어집니다. 그 부드러움이 정확히 위험한 자리였습니다.
검사가 못 잡은 것
고치고 다시 돌리니 0건이 나왔습니다. 그런데 0건이 “문제없음”은 아닙니다.
키보드로 Tab을 눌러가며 페이지를 돌아다녀 봤습니다. 여섯 번째에서 이상한 데 멈췄습니다.
1. 본문 바로가기 2. RyuMa Space
3. Home 4. Blog
5. About 6. <img> ← 여기
본문 이미지에 포커스가 갑니다. 링크도 버튼도 아니라 눌러도 아무 일이 안 일어납니다. 크롬이 스크롤되는 영역을 키보드로도 스크롤하게 해주는 기능 때문인 것 같은데, 재보니 이 이미지는 실제로 스크롤되지도 않습니다.
아직 안 고쳤습니다. tabindex="-1"로 막아버릴 수는 있는데, 브라우저가 왜 그렇게 하는지 확실히 모르는 상태에서 막는 게 맞는지 판단이 안 섰습니다. 다른 브라우저에서도 그런지 확인을 못 했고요.
그리고 더 근본적인 게 있습니다. 검사기는 대체 텍스트가 “있는지”는 보지만 “맞는지”는 모릅니다. 제가 alt에 “이미지”라고만 적어놨어도 통과합니다. 기계가 판단할 수 있는 건 거기까지입니다.
정리
한 번 돌려보는 비용이 생각보다 낮습니다. 설치하고 검사하고 결과 보는 데 십 분이 안 걸렸습니다. 스무 편을 쓰는 동안 안 돌려본 게 게을렀다기보다, 그냥 생각을 안 했던 쪽에 가깝습니다.
숫자로 보면 눈으로 못 보던 게 보입니다. 4.45는 눈으로 절대 못 잡습니다. 기준선 근처에서 아슬아슬하게 버티는 색이 있다는 것 자체를 몰랐습니다.
opacity는 색 대비를 깎습니다. 흐리게 보이게 하고 싶으면 색 자체를 조정하는 게 낫습니다. 같은 결과처럼 보이지만 한쪽만 검사에 걸립니다.
색은 배경과 한 쌍으로 정해야 합니다. 같은 변수가 배경에 따라 통과하기도 하고 떨어지기도 합니다.
0건이 끝이 아닙니다. 자동 검사는 규칙 위반을 잡지, 써보면 성가신 것까지 잡아주지는 않습니다. Tab 키로 한 바퀴 돌아보는 데는 일 분이면 됩니다.
참고한 문서
- W3C — WCAG 2.2 이해하기: 명도 대비(최소) — 4.5:1 기준, 반올림하지 않음
- Deque — axe 규칙 color-contrast — 투명도까지 계산에 넣는 검사 규칙
- MDN — CSS opacity (접근성) — 원인 1. opacity가 대비를 깎는 이유
- Astro 문서 — 구문 강조 — 원인 3. github-dark 테마 색이 인라인 style로 들어감
- axe-core 저장소 — 자동 검사로 잡히는 범위의 한계
댓글
로그인도 이메일도 필요 없습니다. 이름만 적고 편하게 남겨주세요.
지금은 댓글을 불러올 수 없습니다. 잠시 뒤에 다시 시도해 주세요. 급한 내용이면 ryuma@kakao.com로 보내주셔도 됩니다.