ARIA 접근성 가이드

속성 · 라이브 리전 · 전역

aria-live

영역의 내용이 바뀌면 포커스가 없어도 화면낭독기가 자동으로 읽어 주도록 하고, 그 긴급도를 정합니다.

기초

한눈에 보기

구분
속성 (Property)
분류
라이브 리전
값 형식
토큰 (token): off / polite / assertive
기본값
off
적용 범위
모든 요소 (전역 속성)
HTML 대체
<output> (암묵적 status 역할, polite로 동작)

설명

aria-live는 요소를 라이브 리전으로 만듭니다. 라이브 리전의 내용이 바뀌면 사용자가 다른 곳에 포커스를 두고 있어도 화면낭독기가 변경된 내용을 읽어 줍니다. "장바구니에 담았습니다", "저장되었습니다", "검색 결과 12건"처럼 포커스를 옮기지 않고 알려야 하는 상태 메시지에 씁니다(WCAG 4.1.3 상태 메시지).

값은 긴급도입니다. polite는 지금 읽고 있는 문장이 끝나거나 사용자가 입력을 멈춘 뒤에 읽어 대부분의 상황에 알맞습니다. assertive는 즉시 읽고 이전 안내를 끊을 수도 있으므로, 세션 만료 직전 경고처럼 바로 알지 못하면 문제가 되는 내용에만 씁니다. off(기본값)는 사용자가 그 영역에 있을 때만 읽습니다. 같은 효과를 내는 역할로 status(polite), alert(assertive), log(polite), timer·marquee(off)가 있습니다.

가장 흔한 실수는 라이브 리전을 내용과 동시에 만드는 것입니다. 화면낭독기는 이미 접근성 트리에 있는 라이브 리전의 변경을 감지하므로, aria-live가 붙은 요소를 메시지와 함께 새로 삽입하면 읽히지 않는 경우가 많습니다. 페이지를 불러올 때 빈 영역을 미리 두고, 나중에 텍스트만 바꿉니다. display:none이나 hidden으로 숨겼다가 보이는 방식도 환경에 따라 읽히지 않으므로, 영역은 보이게 두고 내용만 비웁니다.

읽는 범위는 aria-atomic(전체 / 바뀐 부분), 어떤 변경을 알릴지는 aria-relevant로 조정합니다. 같은 문장을 다시 넣으면 변경으로 감지되지 않을 수 있어, 한 번 비운 뒤 잠시 후 다시 넣는 방법을 씁니다. 지나치게 자주 알리면 사용자가 다른 내용을 들을 수 없으므로, 타이핑할 때마다 갱신되는 결과 수 같은 정보는 입력이 멈춘 뒤(디바운스) 알립니다.

검수할 때는 화면낭독기를 켠 채 해당 기능을 실행하고 포커스를 옮기지 않은 상태에서 메시지가 읽히는지, 같은 메시지가 반복 실행에도 다시 읽히는지, assertive를 남용해 다른 안내를 끊지 않는지, 페이지 로딩 직후 불필요한 안내가 나오지 않는지 확인합니다.

값

값
값의미
off 기본값사용자가 그 영역에 포커스를 두고 있을 때만 변경을 알립니다.
polite현재 읽고 있는 내용이 끝나거나 사용자가 잠시 멈췄을 때 알립니다. 대부분의 상태 메시지에 씁니다.
assertive즉시 알리며, 대기 중인 다른 안내를 지울 수도 있습니다. 긴급한 내용에만 씁니다.

사용 예

미리 만들어 둔 빈 영역에 메시지 넣기

권장HTML
<button type="button" id="add">장바구니 담기</button>
<p id="cart-msg" aria-live="polite"></p>

<script>
  document.getElementById('add').addEventListener('click', () => {
    document.getElementById('cart-msg').textContent = '장바구니에 담았습니다. (총 3개)';
  });
</script>

메시지와 함께 라이브 리전을 새로 삽입

비권장HTML
<!-- 비권장: 영역이 생기는 순간 내용도 함께 들어가 읽히지 않을 수 있음 -->
<script>
  document.body.insertAdjacentHTML('beforeend',
    '<p aria-live="polite">저장되었습니다.</p>');
</script>

역할로 대신하기

HTML
<div role="status">검색 결과 12건</div>   <!-- polite + atomic -->
<div role="alert">세션이 1분 후 만료됩니다.</div>   <!-- assertive + atomic -->
<output for="qty price">합계 30,000원</output>    <!-- 암묵적 status -->

같은 메시지를 다시 알리기

JavaScript
function announce(region, text) {
  region.textContent = '';
  setTimeout(() => { region.textContent = text; }, 100); // 변경으로 감지되도록
}

직접 해 보기

버튼을 눌러 보세요. 포커스는 버튼에 그대로 있지만, 화면낭독기는 아래 영역의 새 문장을 읽습니다. 긴급도를 바꿔 aria-live 값의 차이를 비교해 볼 수 있습니다.

화면낭독기에서는

화면낭독기 안내 예시 (표현은 화면낭독기·브라우저·버전에 따라 조금씩 다릅니다)
상황들리는 안내 (예)
"장바구니 담기" 버튼을 누름 (polite)장바구니 담기, 버튼 … 장바구니에 담았습니다. (총 1개)
assertive 영역에 메시지가 들어옴세션이 1분 후 만료됩니다. (읽던 내용을 끊고 즉시)
off 영역의 내용이 바뀜(포커스가 영역 밖이면 읽지 않음)

사용 지침

이렇게 쓰세요

  • 페이지를 불러올 때 빈 라이브 리전을 미리 만들어 두고, 나중에 내용만 바꿉니다.
  • 대부분의 상태 메시지에는 polite(또는 role="status")를 씁니다.
  • 메시지는 짧고 그 자체로 이해되게 씁니다.
  • 실제 화면낭독기로 읽히는지 확인합니다. 브라우저·화면낭독기 조합에 따라 결과가 다릅니다.

이렇게 쓰지 마세요

  • assertive를 일반 안내에 남용하지 않습니다.
  • 페이지 본문 전체나 자주 바뀌는 큰 영역을 라이브 리전으로 만들지 않습니다.
  • 포커스를 옮기는 대화상자의 내용을 굳이 라이브 리전으로 다시 읽히게 하지 않습니다(중복 안내).
  • 라이브 리전을 display:none으로 숨겼다가 보이는 방식에 기대지 않습니다.

사용할 수 있는 역할

전역 속성이므로 모든 역할과 HTML 요소에 쓸 수 있습니다. 특히 다음 역할과 자주 함께 씁니다.

이 속성을 쓰는 패턴

참고 자료