대화 입력창에서 질문을 보내면 답이 한 글자씩 늘어난다. 시각적으로는 생성이 시작됐다는 사실과 아직 끝나지 않았다는 상태를 함께 읽을 수 있다. 그러나 스크린리더 사용자의 초점이 입력창에 남아 있다면 화면 다른 곳의 변화를 같은 방식으로 알 수 있는 것은 아니다. 그렇다고 새 글자가 생길 때마다 읽던 위치를 옮기면 다음 질문을 준비하던 행동이 끊긴다.
에릭 베일리는 11월 5일 스매싱 매거진에서 이런 전체 화면 LLM 대화를 다뤘다. 다른 화면 한쪽의 보조 챗봇과 달리, 대화 자체가 작업 공간인 제품이다. 이곳에서 답이 왔다고 알리는 일, 지난 내용을 다시 읽는 일, 다음 질문을 입력하는 일은 각각 자리를 마련해야 한다고 설명한다.
화면의 답과 소식을 알리는 영역을 나누기
베일리의 제안은 모든 메시지를 실시간 알림 영역으로 만드는 대신 문서 끝에 전용 라이브 영역을 두는 것이다. 화면의 응답 본문은 부분적으로 갱신하더라도, 이 알림 영역에는 완성된 메시지를 전달한다. 생성 중인 조각을 계속 읽어 맥락이 끊기거나 같은 내용을 여러 번 알리는 일을 피하려는 선택이다.
W3C의 상태 메시지 문서는 기다림·진행·완료를 초점 이동 없이 알아차리게 하는 목적을 설명한다. WAI-ARIA의 status 역할도 상태가 바뀌었다는 이유로 그 요소에 초점을 옮기지 않도록 권고한다. 이 역할에는 polite와 전체 내용을 대상으로 하는 atomic의 기본값이 있다. 다만 모든 긴 답변을 같은 길이로 읽어야 한다는 규칙까지 이 정의에서 자동으로 나오지는 않는다. 무엇을 어느 시점에 알릴지는 제품의 내용과 사용 맥락에 맞춰 정해야 한다.
표나 코드가 답에 들어오면 알림과 읽기 자료의 역할은 더 달라진다. 원문은 표의 행·열 맥락이나 코드 파일의 개요처럼 내용을 탐색할 단서를 먼저 줄 수 있다고 설명한다. 실제 메시지에는 표의 구조와 코드가 남아 있어야 한다. 알림을 짧게 한다는 이유로 본문까지 평평한 문자열로 바꾸면, 사용자가 셀이나 줄을 다시 살필 경로도 사라진다.
부분 표시와 완료 알림을 작은 예제로 확인하다
아래 코드는 입력폼과 sr-only 스타일을 포함한 ARCH.B의 독립 실행 예제다. 참고자료의 전체 HTML 페이지에서도 같은 코드를 실행할 수 있다. 입력창에서 Enter를 누를 때마다 시작·부분 표시·완료로 한 단계씩 바뀌며 네 번째 Enter는 다시 시작한다. 정해진 문장을 보여주는 설명용 예제로 실제 모델이나 외부 서비스를 호출하지 않고 입력한 내용도 서버로 전송하지 않는다.
2026년 11월 10일 로컬 Chrome에서 Enter를 세 번 눌러 DOM 값과 초점을 확인했다. 시작·부분 표시 단계에는 완료 전용 알림 영역이 비어 있었고, 완료 단계에만 완성 문장이 들어갔다. 세 단계 모두 활성 요소는 메시지 입력창이었다. 화면의 답과 알림 영역은 서로 다른 시점에 갱신되며, 코드는 새 응답을 표시하기 위해 입력 초점을 옮기지 않는다.
이번 예제는 완료 알림과 부분 표시를 분리하는 동작에 한정된다. 실제 서비스에서는 생성 중이나 오류 같은 진행 상태를 보조 기술에 알리는 방법도 별도로 설계해야 한다. 실제 스크린리더의 음성·점자 출력이나 사용자의 이해도는 검사하지 않았으므로 DOM·초점 확인을 접근성 준수 검증으로 확대할 수는 없다.
ARCH.B 독립 실행 예제: 입력폼·단계 전환·완료 알림HTML
<!doctype html>
<html lang="ko">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>입력 초점과 완료 알림 — ARCH.B 독립 예제</title>
<style>
:root { font-family: system-ui, sans-serif; line-height: 1.6; color-scheme: light dark; }
body { max-width: 42rem; margin: 3rem auto; padding: 0 1rem; }
input, button { font: inherit; padding: .6rem; }
input { box-sizing: border-box; display: block; width: 100%; margin: .4rem 0; }
:focus-visible { outline: 3px solid #087f8c; outline-offset: 3px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
</style>
<main>
<h1>입력하던 자리를 지키는 응답 알림</h1>
<p id="instructions">질문을 입력하고 Enter를 세 번 누르세요. 시작, 부분 표시, 완료가 한 단계씩 진행됩니다.
네 번째 Enter는 다시 시작합니다. 답은 고정된 문장이며 실제 AI를 호출하지 않습니다.
입력한 내용은 서버로 전송하지 않습니다.</p>
<form id="demo-form">
<label for="prompt">메시지 입력</label>
<input id="prompt" type="text" aria-describedby="instructions" autocomplete="off"
placeholder="예: 표의 구조를 설명해 주세요">
<button type="submit">다음 단계</button>
</form>
<p id="progress">준비: Enter로 시작하세요.</p>
<h2>응답</h2>
<p id="reply">아직 응답이 없습니다.</p>
<p>이 예제는 입력창의 Enter 조작, DOM 갱신과 초점을 비교합니다. 완료 전용 알림 영역은
시작·부분 표시에서 비워 두고 완료 문장만 전달합니다. 실제 서비스의 진행 상태 알림은 별도로 설계해야 합니다.
스크린리더 음성·점자 출력이나 사용자 이해도를 검증한 결과는 아닙니다.</p>
</main>
<div id="announcer" class="sr-only" role="status" aria-live="polite" aria-atomic="true"></div>
<script>
const form = document.querySelector('#demo-form');
const reply = document.querySelector('#reply');
const progress = document.querySelector('#progress');
const announcer = document.querySelector('#announcer');
const stages = [
['시작', '아직 응답이 없습니다.', ''],
['부분 표시', '홈의 방향과 맞물리는', ''],
['완료', '홈의 방향과 맞물리는 면을 먼저 살펴보세요.', '홈의 방향과 맞물리는 면을 먼저 살펴보세요.'],
];
let step = 0;
form.addEventListener('submit', event => {
event.preventDefault();
const [name, text, announcement] = stages[step];
progress.textContent = `${step + 1}/3 · ${name}`;
reply.textContent = text;
announcer.textContent = announcement;
step = (step + 1) % stages.length;
});
</script>
</html>
| 단계 | 화면의 응답 | 전용 알림 영역 | 활성 요소 |
|---|---|---|---|
| 시작 | 아직 응답이 없습니다. | 빈 문자열 | 메시지 입력창 |
| 부분 표시 | 홈의 방향과 맞물리는 | 빈 문자열 유지 | 메시지 입력창 |
| 완료 | 홈의 방향과 맞물리는 면을 먼저 살펴보세요. | 완성 문장으로 갱신 | 메시지 입력창 |
지난 답을 다시 찾을 때 필요한 표식
알림을 들은 뒤 내용을 다시 읽을 방법도 필요하다. 베일리는 메시지에 제목을 제공하고 작성 주체를 알아볼 수 있게 하자고 제안한다. 시각적으로 큰 제목을 매번 보여주지 않더라도 의미 있는 제목 구조는 메시지 사이를 찾는 단서가 된다. 대화 전체의 제목과 개별 메시지의 제목을 구분하면 같은 화면 안에서도 계층을 읽을 수 있다.
화면의 큰 구역은 대화 목록을 담는 탐색, 현재 대화의 본문, 메시지 입력 폼, 별도 결과물을 놓는 보조 영역처럼 나눈다. 모든 메시지를 랜드마크로 만들면 오히려 큰 구역을 고르기 어려워질 수 있다. 전체 작업 구역을 찾는 이동과 메시지 하나씩 돌아보는 이동에 서로 다른 단위를 주는 것이다.
키보드의 Tab 이동과 방향키 이동도 같은 문제에 닿는다. WAI-ARIA 작성 지침은 일반적으로 Tab으로 구성 요소 사이를 이동하고 복합 위젯 안에서는 방향키를 쓰는 관례를 설명한다. 베일리가 제안하는 메시지 탐색도 긴 대화에서 모든 작은 요소를 차례로 통과하는 부담을 줄이려는 방향이다. 다만 이를 위해 복합 위젯을 구현한다면 이름·초점 표시·키 동작을 함께 맞춰야 한다. 속성 하나를 추가하는 것으로 탐색이 완성되지는 않는다.
기다리는 동안에는 진행 상태가 필요하고, 답이 완성되면 그 소식을 알아야 한다. 나중에는 지난 메시지의 표와 코드로 돌아갈 길도 있어야 한다. 응답 본문과 별도 알림, 메시지 제목과 큰 작업 구역은 이 서로 다른 순간을 받도록 나뉜다.
ARCH.B 의견
이 제안에서 눈길이 가는 부분은 답이 도착한 뒤에도 입력하던 자리를 지켜준다는 점이다. 새 내용을 알리는 일을 초점을 옮기는 동작과 떼어 놓으면, 읽고 있거나 다음 질문을 준비하던 사람의 행동을 이어갈 여지가 생긴다.
표가 생겼을 때에도 표 전체를 곧바로 읽을지, 표가 도착했다는 사실을 먼저 알릴지 따져볼 수 있다. 사용자가 나중에 원하는 셀로 들어갈 길까지 함께 남기면 알림 이후의 읽기도 설계에 들어온다. DOM 값과 초점 검사에서 더 나아가 실제 보조 기술·사용자와 확인해야 하는 부분이 바로 이 흐름이다.

