aria-label과 aria-labelledby가 함께 있으면 무엇이 읽힐까

스크린 리더가 읽는 이름은 정해진 순서로 계산됩니다. aria-labelledby, aria-label, label, placeholder의 우선순위와 흔한 실수를 W3C 문서로 확인합니다.

개발접근성

화면에는 ’검색’이라고 적힌 버튼이 있는데 스크린 리더는 “사이트 내 찾기, 버튼”이라고 읽습니다. 마크업에 aria-label="사이트 내 찾기"가 있기 때문입니다. 보이는 글자와 들리는 이름이 다른 것은 브라우저 오류가 아니라 접근 가능한 이름(accessible name)을 계산한 결과입니다.

이름은 정해진 순서로 결정된다

W3C의 Accessible Name and Description Computation(AccName) 1.2는 4.3.2절에서 이름 계산 단계를 정의합니다. 세부 분기는 요소와 역할에 따라 달라지지만, 흔히 만나는 순서는 다음과 같습니다.

  1. aria-labelledby가 가리키는 요소의 텍스트
  2. 비어 있지 않은 aria-label
  3. <label>이나 alt 같은 HTML 고유의 이름
  4. 버튼·링크처럼 내용에서 이름을 얻는 역할의 자식 텍스트
  5. title 같은 툴팁 속성

앞 단계에서 이름이 나오면 뒤 단계의 후보는 이름에 자동으로 더해지지 않습니다. 따라서 <label for>로 연결한 입력창에 aria-label을 붙이면 보이는 <label>의 글자가 접근 가능한 이름에서 빠질 수 있습니다. HTML-AAM의 텍스트 입력 규칙에서는 placeholder가 title보다도 뒤에 옵니다. placeholder를 라벨 대용으로 삼으면 안 되는 이유 중 하나입니다.

aria-labelledby는 참조한 순서대로 합친다

aria-labelledby에는 여러 ID를 공백으로 나열할 수 있고, 각 참조에서 계산한 텍스트가 그 순서대로 합쳐집니다. AccName 예제를 줄이면 다음과 같습니다.

<a id="file1" href="/files/a.pdf">a.pdf</a>
<span role="button" tabindex="0" id="del1"
      aria-label="삭제" aria-labelledby="del1 file1"></span>

버튼은 먼저 자기 자신을 참조합니다. 참조를 따라 이름을 계산하는 동안에는 같은 aria-labelledby를 다시 따라가지 않고 aria-label의 ’삭제’를 얻습니다. 이어 파일명이 붙어 이름은 “삭제 a.pdf”가 됩니다.

두 가지 동작도 알아 둘 만합니다. hidden이나 display: none으로 숨긴 요소라도 aria-labelledby가 직접 가리키면 이름에 쓰일 수 있습니다. 참조는 연쇄적으로 계속 따라가지 않습니다. A가 B를 가리키고 B가 C를 가리켜도 A의 이름을 계산할 때 B의 aria-labelledby를 다시 따라가지는 않습니다.

무엇을 먼저 쓸까

WAI-ARIA 1.2는 라벨 텍스트가 DOM에 있으면 aria-labelledby를 쓰고 aria-label은 쓰지 않아야 한다고 권고합니다(SHOULD / SHOULD NOT). 폼 컨트롤에는 ARIA보다 <label for> 같은 HTML 고유 기법을 먼저 검토하는 편이 낫습니다. ARIA Authoring Practices Guide(APG)도 보이는 텍스트와 고유 HTML을 우선하라고 설명합니다. <label>은 클릭하면 연결된 컨트롤을 활성화하지만 aria-labelledby가 참조한 일반 요소는 그런 동작을 만들지 않는다는 차이도 있습니다.

aria-label은 보이는 라벨을 두기 어려운 아이콘 버튼에 적합합니다.

<button type="button" aria-label="닫기">
  <svg aria-hidden="true">…</svg>
</button>

보이는 글자와 이름이 다르면 생기는 문제

WCAG 2.2 성공 기준 2.5.3 ‘이름 속 레이블’(레벨 A)은 텍스트 라벨이 있는 사용자 인터페이스 구성 요소의 접근 가능한 이름에 보이는 텍스트가 포함되어야 한다고 요구합니다. 음성 입력 사용자는 화면에서 본 단어를 말해 컨트롤을 조작하기 때문입니다. 첫 예의 ‘검색’ 버튼에서 이름이 ’사이트 내 찾기’뿐이라면 기준을 충족하지 못합니다. 불필요한 aria-label을 지워 보이는 글자를 이름으로 쓰는 것이 간단한 해결책입니다. 해설 문서는 보이는 라벨을 이름 앞부분에 두는 것을 모범 사례로 설명합니다.

aria-label을 아무 요소에나 붙일 수도 없습니다. HTML-AAM은 역할 없는 <div>와 <span>을 generic 역할에 대응시키고, WAI-ARIA 1.2는 generic을 이름을 가질 수 없는 역할로 분류합니다. 이런 요소의 aria-label은 명세상 허용되지 않습니다.

다국어 사이트에서는 번역도 챙겨야 합니다. WAI-ARIA 1.2는 aria-label을 번역 대상 속성으로 지정하며, HTML 표준도 다른 명세가 번역 대상으로 정의한 속성을 인정하면서 aria-label을 예로 듭니다. 다만 추출 도구마다 지원 범위가 다르므로, 로컬라이제이션 파이프라인이 ARIA 속성값을 수집하는지 확인하거나 문자열을 번역 리소스에 명시적으로 넣어야 합니다.

Chrome DevTools의 Accessibility 탭에서는 Computed Properties에서 계산된 이름을 확인할 수 있습니다. 다만 APG는 명세에서 금지하거나 정의하지 않은 패턴이 일부 브라우저에서 동작해도 결과가 일관되지 않을 수 있으므로 보조 기술로 직접 시험하라고 권합니다.

이 글은 2026년 10월 7일에 확인한 문서를 기준으로 합니다. AccName 1.2와 HTML-AAM은 Working Draft이므로 단계 이름과 세부 규칙이 바뀔 수 있습니다. aria-labelledby가 aria-label보다 우선한다는 원칙은 W3C 권고안인 WAI-ARIA 1.2에도 적혀 있습니다.

참고 문서: AccName 1.2, WAI-ARIA 1.2, HTML-AAM, WCAG 2.5.3 해설, APG: Providing Accessible Names, HTML Standard: translate, Chrome DevTools 접근성 참고 문서

블로그로