
원문: https://hidde.blog/component-conformance/
접근성을 고려해 UI 컴포넌트를 만들 수 있습니다. 개발하면서 컴포넌트와 함께 접근성 관련 사항을 문서화하거나, 명백한 장애물이 없는지 검토해도 됩니다. 모두 도움이 되고 권장할 만한 일입니다. 그렇다면 적합성을 주장하는 건 어떨까요? 이 글에서는 WCAG가 기술적으로 그것을 허용하지 않는 이유와, 그 판단이 옳다고 보는 이유를 이야기합니다.
이 글의 일부는 제가 진행해 온 "내장 접근성: 축복인가 저주인가?"라는 발표 시리즈에서 비롯되었습니다. 이 발표에서는 "접근 가능한 웹 플랫폼 기능"과 저작 도구도 다룹니다. JS Heroes 2025 유튜브 영상을 확인하실 수 있습니다.
평소와 같이, 이 글의 의견은 제 개인적인 견해이며 고용주나 제가 속한 워킹 그룹의 입장을 대표하지 않습니다.
컴포넌트가 준수할 수 없는 이유
WCAG 2에서 컴포넌트(디자인 시스템의 리액트/앵귤러/바닐라/HTML 컴포넌트 등)는 공식적으로 WCAG를 준수할 수 없습니다. WCAG의 적합성 요건 중 하나가 이렇게 명시하고 있기 때문입니다.
적합성은 완전한 웹 페이지에만 적용되며, 웹 페이지의 일부가 제외된 경우에는 달성할 수 없습니다.
격리된 컴포넌트를 HTML 페이지에 올려두거나 Codepen이나 스토리북(Storybook) 환경에 두는 방식도 있지만, 그렇다고 달라진다고 보지 않습니다(기술적으로 '완전한 웹 페이지'를 만들었다 해도 마찬가지입니다). 우리가 알고 싶은 건 사용자가 무언가에 접근할 수 있는지 여부이고, 사용자(최종 사용자)는 최종 제품, 즉 완전한 페이지와 프로세스에 접근합니다(예를 들어 물건을 구매하거나 리뷰를 제출하고 싶어 합니다).
이 요건은 WCAG 2.0이 발행된 2008년 이전에 작성되었습니다. 당시에는 프런트엔드 컴포넌트가 설치 가능한 패키지로도, 복사해서 붙여넣을 수 있는 코드 조각으로도 존재하지 않았습니다(나탈리 다우니(Natalie Downe)가 2009년 Clearleft에서 이 관행을 선구적으로 도입한 것으로 보입니다).
요건을 재검토할 여지가 있습니다. 지난 10년간 디자인 시스템은 많이 성숙했습니다. 멀티 브랜드, 멀티 프레임워크, 자동화 테스트 컴포넌트가 이제 표준이 되었습니다. 접근성 전문가로서 편향될 수 있지만, 저는 많은 팀이 접근성을 디자인 시스템 개발의 주요 동기 중 하나 혹은 핵심 동기로 꼽는 모습을 봐왔습니다. 수많은 팀이 더 접근 가능한 최종 제품을 만드는 데 대단히 효과적인 것도 목격했습니다. 모범 사례를 많은 사람에게 전달하고, 유용한 문서를 한 곳에 모아두는 역할을 하기 때문입니다.
컴포넌트가 얼마나 접근 가능한지 테스트하고, 웹사이트의 접근성에 무엇을 기여할 수 있고 없는지 문서화하는 일은 반드시 해야 합니다. WCAG 요건도 이 작업에 도움이 됩니다. 그러나 오늘날 우리가 하는 것처럼 페이지 또는 페이지 집합에 대한 WCAG 적합성을 주장하는 방식이 올바른 접근이라고 봅니다. 컴포넌트 자체의 적합성을 주장하려 해서는 안 됩니다(컴포넌트를 검토하고, 최적화하고, 문서화하고, 접근성 전문가가 평가하는 일은 얼마든지 해도 됩니다). 적합성을 주장해서는 안 되는 이유는 두 가지 위험 때문입니다. 과잉 약속과 실제 접근성을 제대로 포착하지 못하는 문제입니다.
과잉 약속의 위험
컴포넌트에 대한 적합성 주장을 허용하면 "컴포넌트 세일즈맨"이 지킬 수 없는 약속을 너무 쉽게 하게 됩니다.
"컴포넌트 세일즈맨"이라는 표현을 비하적으로 쓴 건 아닙니다. 저도 한때 그런 사람이었으니까요. 이 표현으로 제가 가리키는 건 구체적으로 다음과 같은 역할을 맡은 사람들입니다.
- 자신의 제품에 컴포넌트를 쓸 수 있는 사람들(또는 상업적으로 구매할 수 있는 사람들)에게 디자인 시스템을 홍보하는 역할
- 의사 결정권자와 예산 담당자에게 디자인 시스템과 그 장점을 홍보하는 역할
WCAG를 준수하는 컴포넌트라는 개념은 정말 매력적으로 들립니다. 개발자라면 당장 npm install 하고 싶을 것이고, 예산 담당자라면 막대한 자금을 쏟아붓고 싶을 겁니다. 접근성 담당자로서도 그런 것이 존재하기를 바라겠지만, 저는 꽤 확신합니다… "그것"은 없습니다. 그것은 실제로 실현 가능하거나 의미 있는 무언가가 아닙니다(아래 내용 참조).
컴포넌트가 접근 가능하다거나 어떤 접근성 표준을 준수한다고 말할 때 그 가치를 과도하게 약속할 실질적인 위험이 있습니다. 사람들이 해당 컴포넌트를 쓰거나 구매하면 더 이상 접근성에 대해 걱정할 필요가 없다고 믿게 만들 수 있습니다. 잘못된 기대를 심어주는 거죠. 접근성은 지속적인 프로세스입니다. 사용자 경험을 항상 개선하고 싶듯이, 접근성도 항상 개선해야 합니다.
실제 접근성을 포착하지 못하는 위험
컴포넌트가 적합하다고 주장하는 것은 보이는 것만큼 의미 있지 않습니다. 여러 이유로 사용자의 실제 접근성을 제대로 포착하지 못할 가능성이 높습니다. 아래에서 세 가지를 살펴보겠습니다. 맞춤화 가능성, 조합 가능성, 그리고 맥락입니다.
맞춤화 가능성
대부분의 현대 컴포넌트에는 옵션이 있습니다. 스토리북 같은 도구를 쓰면 웹 개발자가 컴포넌트 옵션을 나열하고, 데모하고, 테스트할 수 있습니다.
이러한 옵션 중 많은 것이 사용 시점에서 WCAG 적합성에 쉽게 영향을 미칩니다. 사용이 WCAG를 충족하는지는 최종 제품에서만 확인할 수 있다는 뜻이고, 적합성은 "데모" 컴포넌트 단계에서 결정할 수 없습니다.
예를 들어:
- 컴포넌트에서 색상을 바꿀 수 있다면, 최종 제품이 WCAG를 충족하는지 판단하려면 어떤 색상인지 알아야 합니다(1.4.3, 1.4.11)
- 컴포넌트에서 버튼 텍스트를 바꿀 수 있다면, 최종 제품이 접근 가능한지(예: "여기를 클릭하세요"는 안 되고 설명적인 텍스트여야 함) 또는 WCAG를 충족하는지 판단하려면 최종 제품의 텍스트가 무엇인지 알아야 합니다(예: 2.5.3)
- 이미지 컴포넌트에 대체 텍스트를 전달할 수 있다면, 전달된 텍스트가 이미지를 제대로 설명하는지 알아야 합니다… 최종 제품이 WCAG를 충족하는지 판단하려면 이미지와 텍스트 모두 확인해야 합니다(1.1.1)
- 간격을 맞춤화할 수 있다면, 최종 제품이 WCAG를 충족하는지 판단하려면 최종 제품의 수치가 무엇인지 알아야 합니다(2.5.8)
조합 가능성
접근 가능하거나 WCAG를 충족하는 무언가를 만들려고 컴포넌트를 올바른 방식으로 조합해야 할 때가 있습니다.
예를 들어, 많은 디자인 시스템에는 별도의 레이블 컴포넌트와 입력 컴포넌트가 있습니다. WCAG를 충족하는 입력 상황을 만들려면(1.3.1, 4.1.2), 최종 제품을 만드는 사람이 두 컴포넌트를 조합해야 할 수 있습니다. 그 시점에서 "적합성"은 컴포넌트 하나에 있는 것이 아니라, 여러 컴포넌트의 효과적인 조합에 있게 됩니다(많은 시스템이 이를 쉽게 해주는 헬퍼나 단일 컴포넌트를 제공하지만, 그건 제 핵심 주장이 아닙니다).
맥락
마지막으로, 맥락도 중요합니다. 테스트 스위트의 고립된 환경에서는 볼 수 있는 것이 제한적입니다. 실험실 조건에서 접근성을 살펴보는 것은 분명히 유용하지만, 실제 접근성에는 맥락이 필요합니다. 사람들이 실제로 쓸 환경 말이죠.
건너뛰도록 설정된 ID를 포함하지 않는 페이지에서 제 스킵 링크 컴포넌트를 쓰면, 의미 있는 접근성을 제공할 수 없습니다. 반복되는 콘텐츠 블록이 없는 경우도 마찬가지입니다. 2.4.1 반복 블록 건너뛰기 충족에 기여할 수는 있지만, 사용자가 실제 블록을 실제로 건너뛸 수 있게 해주는 페이지의 맥락 안에서만 그렇습니다.
날짜 선택기(date picker)가 중간을 잘라버리는 요소 안에 있다면, 제 캘린더 컴포넌트의 포커스 표시기는 의미 있는 접근성을 제공할 수 없습니다. 2.4.7 포커스 표시 충족에 기여할 수는 있지만, 그것을 깨뜨리지 않는 페이지의 맥락 안에서만 그렇습니다.
내장할 수 있는 접근성
접근성의 일부 측면은 맞춤화 가능성, 조합 가능성, 맥락에서 대체로 "살아남는" 것들이 있습니다.
가능하다면 다음 항목들은 컴포넌트에 반드시 내장하려고 노력해야 합니다.
- 키보드 접근성. 예를 들어 날짜 선택기에서 날짜 간 이동 방법, 목록에서 옵션 선택 방법, 요소 순서 등입니다.
참고: 페이지 수준의 키보드 개입으로 여전히 깨질 수 있습니다(양수tabindex사용이나 스크립트를 통한 개입 등). - 의존하지 않는 시맨틱(특히 역할(role)). 예를 들어 button 요소를 쓰는 버튼 컴포넌트입니다.
참고: 많은 시맨틱이 실제로 의존합니다. 예를 들어 팝오버(popover)에는 적합한 역할이 여러 가지입니다. - 상태와 관계. 예를 들어 확장 가능한 요소의
aria-expanded상태입니다. - 합리적인 읽기 순서.
- 줌 및 리플로우(reflow) 지원.
참고: 콘텐츠와 맥락에 따라 여전히 깨질 수 있습니다. - 사용자 선호 지원. 예를 들어 다크 모드/강제 색상 모드, 텍스트 간격 등입니다.
- 접근성 기능 지원. 예를 들어 비디오 플레이어 컴포넌트의 자막 및 화면 해설 지원입니다.
컴포넌트를 견고하게 만드는 방법은 이 외에도 많습니다. 그렇게 하는 데서 큰 가치를 느낍니다. 지난 몇 년간 디자인 시스템 수준에서 접근성에 진지하게 투자해 최종 제품의 문제가 더 적고 덜 심각해지는 사례를 많이 봤습니다.
디자인 시스템에서 컴포넌트를 다루는 또 다른 큰 이점은 방향을 제시할 기회가 많다는 점입니다. 컴포넌트를 잘 쓰는 방법, 테스트한 내용, 최종 제품에서 테스트해야 할 내용 등을 문서화하세요. 선의를 가진 개발자들이 올바르게 쓸 수 있도록 도와주세요(악의적인 개발자를 어떻게 할지는 다른 글에서 다룰 수 있습니다).
컴포넌트가 충족할 수 있는 스펙
Peter의 사려 깊은 댓글을 바탕으로 8월 13일에 추가되었습니다
컴포넌트가 WCAG 스펙을 충족할 수 없다고 말하지만, 다른 스펙은 충분히 충족할 수 있습니다. 버튼이 WCAG를 충족한다고 주장하는 것은 의미 없지만, 버튼이 버튼 전용 스펙을 충족한다고 말하는 것은 의미 있습니다.
어떤 컴포넌트에 대해서도 그 컴포넌트를 접근 가능하게(또는 훌륭하게) 만들기 위한 요구사항 목록을 작성할 수 있습니다. 컴포넌트는 그 요구사항 전체를 충족할 수 있습니다. 공상이 아닙니다.
NL 디자인 시스템 프로젝트(면책 사항: 저는 그곳에서 일한 적이 있습니다)는 정부 디자인 시스템 제작자 커뮤니티의 컴포넌트를 인큐베이팅합니다. 인큐베이션 과정에서 각 컴포넌트의 요구사항 목록을 작성합니다. 예를 들어 스킵 링크에 대한 요구사항 목록을 확인해보세요(네덜란드어이지만, 번역 서비스를 쓰면 됩니다).
US 웹 디자인 시스템에도 체크리스트가 있습니다. 버튼 체크리스트가 그 예입니다. 컴포넌트를 만들 때 테스트한 내용과 구현 시 각 컴포넌트에 대해 테스트해야 할 내용을 설명합니다.
마무리
공식적으로, 컴포넌트에 대한 접근성 적합성을 주장할 수 없습니다. 그러나 과잉 약속의 위험이 있기 때문에 그런 주장을 하고 싶지도 않습니다. 그럼에도 컴포넌트를 최적화하는 데는 큰 가치가 있습니다. 합리적으로 내장할 수 있는 것을 내장하려는 시도에도 큰 가치가 있습니다. 어떻게 만들고 테스트했는지 설명하는 문서를 제공하는 일도 마찬가지입니다. 누가 무엇과, 그리고 어떻게 상호작용하는지 절대 잊지 않는 한에서 말이죠. 목표는 사람들이 최종 제품을 쓸 수 있어야 한다는 것입니다.
업데이트 목록
- 2025년 8월 15일: 피드백을 반영해 여러 곳에 명확한 설명을 추가했습니다. 이 글은 컴포넌트를 만들고, 테스트하고, 평가하고, 최적화하는 것을 만류하려는 게 아닙니다. WCAG가 적합성 주장을 공식적으로 전체 페이지에 한정하는 이유, 그리고 그 범위가 왜 타당한지(사용자는 컴포넌트가 아닌 최종 제품을 경험하기 때문)를 설명하기 위한 글입니다.
- 2025년 8월 13일: 컴포넌트가 충족할 수 있는 다른 스펙 섹션 추가.
'Web Frontend Developer' 카테고리의 다른 글
| [번역] 타입스크립트 성능 문제 해결하기 — 사례 연구 (0) | 2026.06.05 |
|---|---|
| [번역] 리액트는 기본값으로 승리했습니다 – 그리고 프런트엔드 혁신을 죽이고 있습니다 (0) | 2026.05.08 |
| [번역] 자바스크립트 Date 계산은 얼마나 잘못될 수 있을까요? (0) | 2026.05.08 |
| [번역] CSS in 2026: 프런트엔드 개발을 바꾸는 새로운 기능들 (0) | 2026.03.27 |
| [번역] 이제 모던 CSS가 SPA를 끝낼 때입니다 (12) | 2026.03.27 |