텍스트 모드의 거짓말: 현대 TUI가 접근성에 악몽인 이유
1 week ago
5
- 터미널 앱이 텍스트 기반이라 본질적으로 접근 가능하다는 가정은 현대 TUI에서 깨지며, Ink, Bubble Tea, tcell 같은 프레임워크가 화면 읽기 프로그램 사용자에게 더 적대적인 환경을 만들 수 있음
- CLI는 stdin/stdout의 선형 스트림으로 출력이 시간순으로 쌓이지만, TUI는 터미널을 문자 셀 기반 2D 격자로 다뤄 화면 읽기 프로그램이 흐름을 따라가기 어려워짐
- gemini-cli는 Ink가 React 컴포넌트 트리를 터미널 격자에 맞춰 다시 그리면서 스피너·타이머·대화 기록 사이로 커서를 이동시켜 Speakup과 NVDA에 반복 낭독, 크래시, 입력 지연을 유발할 수 있음
- nano, vim, menuconfig, Irssi 같은 오래된 도구는 커서 숨김, 단일 열 포커스, VT100 스크롤 영역 활용으로 좌표 갱신 소음을 줄이고 입력 줄과의 간섭을 최소화함
- 접근 가능한 터미널 도구를 만들려면 터미널을 캔버스처럼 다루는 선언형 UI 프레임워크와 공격적인 다시 그리기를 피하고, 단순하고 선형적인 CLI 스트림에 가까운 동작을 보장해야 함
“텍스트라서 접근 가능하다”는 오해
- 터미널에서 실행되는 애플리케이션이 본질적으로 접근 가능하다는 가정은 실제 사용 환경과 맞지 않음
- 그래픽, 복잡한 DOM, WebGL 캔버스가 없기 때문에 화면 읽기 프로그램이 원시 ASCII 텍스트를 쉽게 해석할 수 있다는 기대는 현대 TUI에서 깨짐
- Ink(JS/React), Bubble Tea(Go), tcell 같은 터미널 UI 프레임워크는 개발자 경험(DX)을 개선하려 하지만, 시각장애인 사용자에게는 더 적대적인 환경을 만들 수 있음
- 잘못 구현된 그래픽 인터페이스보다 현대 TUI가 접근성 측면에서 더 나쁜 경우가 많음
CLI와 TUI의 구조적 차이
-
CLI: 선형 스트림
- CLI는 stdin/stdout 기반으로 동작하며, 명령을 입력하면 결과가 아래에 추가되고 커서가 내려감
- 출력이 선형적이고 시간순으로 쌓이기 때문에 Speakup 같은 커널 수준 화면 읽기 프로그램에 적합함
-
TUI: 2D 격자
- TUI는 터미널 창을 텍스트 스트림이 아니라 문자 셀 하나하나가 픽셀처럼 쓰이는 2D 격자로 다룸
- 시간적 흐름을 포기하고 공간적 레이아웃을 우선하면서 화면 읽기 프로그램이 따라가기 어려운 구조가 됨
gemini-cli에서 드러나는 문제
- gemini-cli는 Node.js와 Ink 프레임워크로 작성된 도구이며, 겉으로는 단순한 채팅 인터페이스처럼 보임
- 내부에서는 Ink가 React 컴포넌트 트리를 터미널 격자에 맞춰 조정하려고 함
- Speakup(Linux)이나 NVDA(Windows)로 사용할 때, 애플리케이션이 단순히 실패하는 수준을 넘어 화면 읽기 프로그램에 계속 읽을 내용을 쏟아냄
-
반응형 캔버스처럼 동작하는 화면
- 프레임워크가 화면을 반응형 캔버스로 취급하기 때문에 모든 업데이트가 다시 그리기를 유발함
- AI가 “생각 중”일 때 타이머나 스피너를 갱신하려고 하드웨어 커서를 타이머 위치로 옮기고, 새 시간을 쓰고, 다시 원래 위치로 돌림
- 시각 사용자에게는 즉시 지나가는 동작이지만, 화면 읽기 프로그램 사용자에게는 “Responding... Time elapsed 1s... Responding... Time elapsed 2s...”처럼 반복해서 들림
- 커서가 상태 표시, 스피너, 대화 기록 사이를 순간적으로 이동하면서 Speakup은 그 순간 커서 아래에 있는 내용을 읽으려 함
- 결과적으로 타이머 갱신과 대화 조각이 섞여 들려 실제로 입력 중인 내용에 집중하기 어려워짐
-
NVDA와 붙여넣기에서 발생하는 불안정
- Windows에서 NVDA를 사용해 터미널을 열고, Linux 장비에 SSH로 접속한 뒤 screen 세션에 붙어서 텍스트를 붙여넣으면 NVDA가 즉시 크래시하거나 시스템이 크게 불안정해질 수 있음
- 문자를 입력하거나 텍스트를 붙여넣을 때마다 애플리케이션 상태가 바뀌고, 프레임워크는 인터페이스를 다시 렌더링해야 한다고 판단함
- 대화 기록이 상태에 포함되어 있으면 수천 줄의 텍스트 레이아웃을 즉시 다시 그리거나 다시 계산하려고 함
- 대화 메시지가 많을수록 이 문제가 더 자주 발생함
- 동적 콘텐츠 알림을 피하기 위한 Insert+5 조합으로도 이 문제를 피할 수 없음
-
입력 지연 루프
- Ink 같은 프레임워크가 Node.js처럼 단일 스레드 환경에서 실행되면 기록이 커질수록 성능 저하가 커짐
- 큰 텍스트 블록을 붙여넣으면 수천 줄에 대한 차이를 계산해야 함
- 시스템이 화면을 다시 그리는 방법을 계산하느라 바빠져 입력 처리가 늦어짐
- 키 하나를 눌러도 문자가 다시 표시되기까지 최대 10초까지 기다릴 수 있음
오래된 도구들이 작동하는 이유
- nano, vim, menuconfig 같은 도구가 접근성에 항상 완벽해서 쓰이는 것은 아님
- 핵심은 이 도구들이 커서를 완전히 숨기거나, 커서 위치 추적에서 생기는 소음을 줄일 수 있다는 데 있음
-
nano와 vim: 커서 숨기기
- nano를 --constantshow처럼 커서 위치를 표시하는 옵션으로 실행하거나, vim을 특정 설정 없이 쓰면 사용성이 깨질 수 있음
- 커서가 보이고 추적이 활성화되면 Speakup은 문자 에코보다 커서 위치 갱신을 우선함
- 사용자가 “a”를 입력했을 때 “a” 대신 “Column 2”를 듣고, “b”를 입력하면 “Column 3”을 듣게 됨
- 이 오래된 도구들은 시각적 커서나 상태 표시줄 갱신을 억제하도록 설정할 수 있기 때문에 화면 읽기 프로그램이 좌표 갱신이 아니라 문자 입력 스트림에 의존하게 만들 수 있음
- 현대 프레임워크는 보통 “no-cursor”나 “headless” 모드를 제공하지 않고, 시각적 커서가 필수라고 가정함
-
menuconfig: 단일 열 포커스
- Linux 커널의 menuconfig는 엄격한 단일 열 포커스를 유지하기 때문에 작동함
- 테두리와 제목이 있어도 활성 영역은 세로 목록이며, 커서는 그 목록에 고정됨
- 커서가 시계 갱신을 위해 오른쪽 아래로 이동했다가 제목 갱신을 위해 왼쪽 위로 이동하는 식으로 움직이지 않음
- 공간적 복잡도가 낮게 유지되어 화면 읽기 프로그램이 길을 잃지 않음
-
Irssi: 스크롤 영역 활용
- Irssi는 운 좋게 접근 가능한 것이 아니라, 20년 넘게 커스텀 렌더링 엔진을 통해 VT100 스크롤 영역을 활용해 온 채팅 도구임
- 새 메시지가 도착하면 터미널 드라이버에 “1행부터 23행까지를 스크롤 영역으로 정의하라”고 지시함
- 이어 “위로 스크롤하라”는 명령을 보내고, 터미널이 내용을 위로 이동시킨 뒤 해당 영역의 아래쪽에 새 텍스트를 그림
- 이 방식은 입력 줄과의 간섭을 최소화함
- 화면의 모든 문자를 수동으로 다시 쓰기보다 터미널의 하드웨어 기능에 의존함
- 현대 프레임워크는 이런 하드웨어 기능을 무시하고 화면 상태 차이를 계산해 문자를 다시 쓰는 방식을 택하는데, 이는 계산 비용이 더 크고 접근성에 적대적임
gemini-cli 이슈 처리의 문제
- Google과 gemini-cli 유지보수자는 접근성을 신경 쓰는 것처럼 보이지만, 저장소에서는 중요한 접근성 회귀가 방치되어 있음
- Issue #3435와 Issue #11305 같은 접근성 회귀에는 토론, 로드맵, 수정이 없음
- Issue #1553은 이런 접근성 실패를 추적하기 위한 이슈였지만 해결되지 않았고, 봇이 자동으로 닫음
- 봇은 오래 활동이 없고 백로그를 관리하기 위해 닫는다는 일반적인 문구로 이슈를 종료함
- 유지보수자가 몇 달 동안 손대지 않았다는 이유로 접근성 보고를 닫는 것은 정리가 아니라 증거를 숨기는 것과 같음
- 버그를 충분히 오래 무시하면 존재하지 않게 된다는 신호를 주며, 실제 소프트웨어는 시각장애인 사용자에게 여전히 사용할 수 없는 상태로 남음
- 프로젝트의 “Closed Issues” 지표는 좋아질 수 있지만 접근성 문제는 해결되지 않음
접근 가능한 터미널 도구를 만들기 위한 결론
- 터미널용 애플리케이션에서 접근성을 중요하게 생각한다면 터미널을 캔버스처럼 다루는 선언형 UI 프레임워크 사용을 멈춰야 함
- “현대적” TUI 스택은 개발자가 React처럼 코드를 작성하기 쉽게 하는 쪽으로 최적화됐고, 기계가 텍스트를 효율적으로 렌더링하는 능력을 희생함
- 애플리케이션이 사용자가 커서를 숨길 수 있도록 보장하지 못하거나, 스피너와 타이머를 표시하기 위해 공격적인 다시 그리기에 의존한다면 접근 불가능한 도구가 됨
- 시각장애인 사용자에게는 지연되고, 계속 읽을 내용을 쏟아내고, 커서를 화면 전체에 흩뿌리는 “스마트” TUI보다 단순하고 선형적인 CLI 스트림이 훨씬 나음
-
Homepage
-
Tech blog
- 텍스트 모드의 거짓말: 현대 TUI가 접근성에 악몽인 이유