귀로 듣는 챗봇의 탄생 | 접근성 업무일지 #3

손연지
2025년 8월 13일

안녕하세요! 저는 토스코어에서 CX Product Team 소속으로 프론트엔드 개발을 하고 있는 손연지라고 합니다. 지금까지는 상담 대시보드, 내부 상담 어드민, STT 어드민 같은 CX 인터널 제품들을 주로 개발해왔고, 최근에는 대고객 제품인 고객센터 챗봇 서비스를 맡아 개발하고 있어요.

토스 고객센터 챗봇에서 상위 서비스를 선택하면, 그에 맞는 하위 선택 화면으로 전환되면서 여러 개의 버튼이 나타나요. 예를 들어 송금에 대해 문의하면, “송금 한도가 궁금해요”, “송금 한도를 변경하고 싶어요” 같은 버튼들이 새롭게 나타나죠. 어느 날 접근성 관련 피드백을 하나 받았어요. 새로운 메시지가 떠도, 스크린리더 사용자 입장에서는 화면이 바뀌었다는 걸 전혀 인지할 수 없었다는 거예요.

실제로 화면이 바뀌었는데도 초점은 그대로 이전 위치에 머물러 있으니, 스크린리더 사용자 입장에서는 새로운 흐름이 시작됐다는 걸 전혀 알 수 없었던 거예요. 이 문제를 해결하기 위해, 눈으로 보면 당연하게 느껴지는 화면의 흐름을, 보지 않아도 자연스럽게 따라갈 수 있는 설계를 고민하게 되었어요.


개선 1 — 시각적 UI의 흐름을 초점 이동에 반영하기

우선 스크린리더를 쓰지 않는 사용자가 챗봇을 사용할 때의 흐름을 떠올렸어요. 보통은 상위 항목을 누르면 새로운 메시지가 뜨고, 그 아래에 하위 선택 버튼들이 등장하죠. 자연스럽게 시선을 따라가며 다음 행동으로 넘어가게 돼요.

스크린리더 사용자에게는 이 시선의 흐름을 초점 이동이 대신 해줘야 해요. 그래서 화면이 바뀌었을 때는 초점도 함께 이동해줘야, 흐름이 끊기지 않을 수 있어요.

예를 들어, 안내 메시지가 위에 있고, 버튼이 아래에 있다면 초점은 메시지 → 버튼 → 다음 메시지 순으로 이동해야해요. 그래야 사용자가 “지금 어디쯤이고, 무엇을 해야 하는지”를 놓치지 않게 돼요.


개선 2 — 초점 이동 타이밍을 정교하게 조정하기

초점만 잘 옮겨주면 해결된다고 생각했는데, 초점이 언제, 어떻게 이동하느냐가 훨씬 더 중요했어요.

개선 과정에서 초점을 자동으로 옮기기 위해 target.focus()를 사용했더니, 브라우저가 해당 요소로 즉시 점프(scroll)해버리면서 기존에 잘 작동하던 챗봇의 부드러운 자동 스크롤scrollIntoView({ behavior: 'smooth' }) 이 무시되는 문제가 생겼어요. focus()가 강제로 즉시 스크롤을 발생시키면서, 스크롤이 ‘훅’ 튀는 느낌이 되어버린 거죠. 그래서 아래와 같이 흐름을 정교하게 나눠서 구현했어요:

  1. 먼저 메시지 박스를 scrollIntoView({ behavior: 'smooth' })로 부드럽게 스크롤시키고,
  2. 스크롤이 어느 정도 끝났을 타이밍(약 1초 후)

    target.focus({ preventScroll: true })를 호출해서 초점을 이동시켰어요.

  3. preventScroll: true 옵션 덕분에 초점 이동이 스크롤 위치를 다시 덮지 않게 만들 수 있었고요.

target.scrollIntoView({ behavior: 'smooth' });

setTimeout(() => {
  target.focus({ preventScroll: true });
}, 1000);

이렇게 흐름을 나눠서 처리하니, 시각적으로도 자연스럽고 초점도 정확한 위치에 도달했어요. 스크린리더 역시 그 타이밍에 맞춰 끊김 없이 안내를 이어갈 수 있었고요.

결과적으로 사용자는 부드러운 스크롤과 또렷한 초점 이동 흐름을 함께 경험할 수 있었어요.


개선 3 — 버튼 존재 알려주는 안내 추가하기

*음성안내가 있으니 꼭 소리를 켜고 재생해주세요.

텍스트 메시지 아래에 버튼이 있는 경우, 초점이 버튼까지 도달하지 않으면 버튼이 있는지조차 모른 채 지나치게 돼요. 그래서 메시지가 끝난 뒤, 스크린리더 전용으로 “아래 메뉴 버튼을 선택해 주세요”라는 안내를 추가했어요.

<ScreenReaderOnly>아래 메뉴 버튼을 선택해 주세요.</ScreenReaderOnly>

이 메시지는 시각적으로는 보이지 않지만, 스크린리더 사용자는 들을 수 있어요. “아, 이제 선택할 수 있는 버튼이 있구나” 하고 흐름을 놓치지 않을 수 있죠.

시각적 디자인은 그대로 유지하면서도, 음성 흐름상 필요한 안내를 덧붙여주는 방식으로 흐름을 보완할 수 있었어요.


개선 4 — 메시지 상황에 대한 청각 피드백 주기

*음성안내가 있으니 꼭 소리를 켜고 재생해주세요.

상담원이 메시지를 입력 중이거나, 메시지를 보냈을 때, 일반 사용자는 화면의 변화나 타이핑 애니메이션 등을 통해 이를 쉽게 인식할 수 있어요. 하지만 스크린리더 사용자에겐 이 모든 맥락이 공백이에요. 그래서 이런 시각적 정보를 음성으로 안내하려고 했죠.

상담원이 입력 중일 때는 aria-live="polite" 속성을 활용해 “상담원이 메시지를 입력 중입니다”라는 음성을 안내했어요. 메시지를 보낼 때 / 받을 때 시점에 각각 효과음을 재생해 상황에 대한 피드백을 주려고 했어요.

스크린리더 음성이 겹쳐도 효과음은 별도로 울리기 때문에, 메시지를 못 들었더라도 “무언가가 방금 발생했구나”를 인지할 수 있어요. 메시지 효과음은 사실 우리 모두에게 익숙한 경험이에요. 눈으로 확인한 정보에 소리로 피드백이 더해지면, 그 경험은 더 선명하게 느껴져요. 이 개선은 시각장애인을 위한 대응이자, 모든 사용자에게 익숙하고 친절한 사용성을 제공하는 방식이기도 했어요.


개선 이후

프론트엔드 개발자로서 이번 작업은 단순한 기능 구현이 아니라, 사용자의 인지 흐름을 설계한 경험이었어요. 직접 스크린리더를 켜고 눈을 감고 탐색해보며 “내가 과연 이 흐름을 이해할 수 있을까?” 를 계속 되묻는 시간이었죠.

접근성은 특정 상황에 놓인 사용자만을 위한 기능이 아니었어요. 오히려 모든 사용자에게 더 명확하고, 더 친절한 흐름을 설계하는 일이라는 걸 깊이 느낄 수 있었어요.

특히 메시지 수신/발신 효과음 같은 기능은 누구에게나 익숙한 대화의 리듬을 더 또렷하게 만들어주는 요소가 될 수 있죠. 소리 피드백이 더해지면 사용자 입장에서 흐름은 더 선명해지니까요.

이번이 처음 해본 접근성 개선 작업이었지만, 앞으로 개발하는 모든 화면에서 반드시 함께 고려해야 할 하나의 기준이 생긴 것 같아요.

앞으로는 이 흐름을 팀 내 공통 패턴으로 확장해보고 싶어요. 초점 이동이나 타이밍 제어 같은 것들은 재사용 가능한 유틸로 만들면 다른 화면에도 쉽게 적용할 수 있을 거예요.

접근성은 소수만을 위한 고려가 아니라, 모든 사용자에게 더 나은 흐름을 제공하는 방법이라는 걸 배웠습니다. “눈을 감고도 안심하고 사용할 수 있는 서비스”를 위해 앞으로도 계속 고민해볼게요.

댓글 0댓글 관련 문의: toss-tech@toss.im
㈜비바리퍼블리카 Copyright © Viva Republica, Inc. All Rights Reserved.