아리아 라이브 리전

ARIA Live Region

화면이 스스로 바뀌었을 때(장바구니 개수, 저장 완료 등) 스크린 리더가 그 변화를 알아서 읽어주게 만드는 속성.

다른 이름: Live regionaria-live
···
html
<div class="stage">
  <div class="pane app">
    <div class="tag">화면</div>
    <div class="cartRow">
      <div class="cartIcon"><span id="count">0</span></div>
      <button class="addBtn" id="addBtn"></button>
    </div>
  </div>
  <div class="pane sr">
    <div class="tag">SR transcript</div>
    <div class="log" id="log"></div>
  </div>
</div>
css
.stage{width:94%;height:88%;display:flex;gap:4%}
.pane{position:relative;flex:1;border-radius:14px;border:1px solid var(--line);background:var(--surface);overflow:hidden}
.tag{position:absolute;top:8px;left:10px;font:700 10.5px/1 ui-monospace,monospace;color:var(--muted)}
.app{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10%}
.cartRow{width:64%;display:flex;align-items:center;justify-content:center;gap:14%}
.cartIcon{position:relative;width:36px;height:36px;flex:none;border-radius:9px;border:2px solid var(--fg);display:grid;place-items:center;font:800 13px/1 ui-monospace,monospace;color:var(--fg)}
.addBtn{width:40px;height:32px;flex:none;border-radius:9px;background:var(--accent);border:none;transition:transform .15s ease}
.log{position:absolute;inset:26px 10px 10px;display:flex;flex-direction:column-reverse;gap:6px;font:10.5px/1.3 ui-monospace,monospace;color:var(--accent-3);overflow:hidden}
.log div{opacity:0;transform:translateY(4px);transition:opacity .3s ease,transform .3s ease}
.log div.show{opacity:1;transform:translateY(0)}
js
const btn = document.getElementById('addBtn');
const countEl = document.getElementById('count');
const log = document.getElementById('log');
let n = 0;
function addLine(text) {
  const line = document.createElement('div');
  line.textContent = text;
  log.prepend(line);
  requestAnimationFrame(function () { line.classList.add('show'); });
  while (log.children.length > 4) log.removeChild(log.lastChild);
}
function tick() {
  n++;
  countEl.textContent = String(n);
  btn.style.transform = 'scale(0.9)';
  setTimeout(function () { btn.style.transform = 'scale(1)'; }, 150);
  addLine(n + (n === 1 ? ' item in cart' : ' items in cart'));
}
tick();
setInterval(tick, 2000);

포커스가 없는 위치에서 콘텐츠가 바뀌면(장바구니 개수, "저장됨" 토스트, 검색 결과 수) 화면을 보는 사용자는 눈으로 알아채지만 스크린 리더 사용자는 아무 신호도 받지 못합니다. `aria-live="polite"`를 준 영역은 내용이 바뀔 때마다 스크린 리더가 지금 읽던 것을 마치고 그 변화를 알려주고, `aria-live="assertive"`는 즉시 끼어들어 읽습니다.

`polite`가 기본값이고 거의 항상 옳은 선택입니다. `assertive`는 세션 만료처럼 정말 급한 경고에만 씁니다 — 남용하면 계속 말이 끊겨 오히려 불편합니다. 에러 메시지처럼 요소가 통째로 새로 나타나는 경우는 `role="alert"`(암묵적으로 assertive)를 쓰기도 합니다.

데모 왼쪽은 실제 화면, 오른쪽은 스크린 리더가 실제로 읽는 내용을 문자로 옮긴 트랜스크립트입니다. 담기 버튼이 자동으로 눌릴 때마다 화면과 별개로 오른쪽에 새 줄이 추가됩니다.

언제 쓰나

토스트 알림, 실시간 카운터, 자동완성 결과 수, 폼 검증 요약처럼 포커스 없이 바뀌는 모든 곳에 씁니다. 애니메이션 되는 숫자나 로딩 스피너에 매번 붙이면 스크린 리더가 계속 떠들게 되니 주의하세요.