# 텍스트 모드의 거짓말: 현대 TUI가 접근성에 악몽인 이유

> Clean Markdown view of GeekNews topic #29134. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29134](https://news.hada.io/topic?id=29134)
- GeekNews Markdown: [https://news.hada.io/topic/29134.md](https://news.hada.io/topic/29134.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-04T09:01:42+09:00
- Updated: 2026-05-04T09:01:42+09:00
- Original source: [xogium.me](https://xogium.me/the-text-mode-lie-why-modern-tuis-are-a-nightmare-for-accessibility)
- Points: 3
- Comments: 1

## Topic Body

- 터미널 앱이 텍스트 기반이라 본질적으로 접근 가능하다는 가정은 현대 **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 스트림이 훨씬 나음

## Comments



### Comment 56783

- Author: neo
- Created: 2026-05-04T09:15:50+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/ifbdw1/text_mode_lie_why_modern_tuis_are)   
- 이 글은 다른 블로그 글들과 마찬가지로 **AI 보조 작성 냄새**가 강함  
  LLM이 이런 식의 제목을 좋아함: “The Architectural Flaw”, “The Lag Loop”, “Why The ‘Old Guard’ Works”, “The Lost Art of Scrolling Regions”, “The ‘Stale Bot’ excuse: A Case Study in Neglect”  
  - 제목부터 AI 양산 글처럼 읽힘. 주제 자체는 새로워서 스팸 신고는 좀 과했을 수 있지만, 1) 어디서나 반복되는 같은 문체를 더는 못 견디겠고 2) 내용의 정확성까지 의심하게 됨  
    훌륭한 블로그 글이 될 수 있었는데, 작성자가 개요를 ChatGPT에 던져 넣고 끝낸 듯하면 독자와 저자 모두에게 손해임  
  - LLM 글쓰기에서 제일 싫은 특징 중 하나가 “The <전혀 정립된 개념이 아닌 것>”처럼 써서 마치 정식 개념인 듯 보이게 만드는 것임  
    아주 특수한 일회성 문제를 “고전적인” 문제라고 부르는 것도 마찬가지임  
  
- 정말 우울함. 요약하면 Irssi처럼 **접근 가능한 TUI**도 있는데, 현대 TUI 프레임워크들은 그런 선례를 무시하고 격자 차이 계산과 커서 이동에 의존함  
  화면 읽기 도구는 커서가 움직일 때 그 위치의 내용을 읽기 때문에, 결과가 뒤죽박죽이 되거나 엄청난 낭독 스팸이 발생함  
  
- 여기의 기술 설명이 완전히 정확한지는 의문임  
  특히 Ink는 오랫동안 **증분 렌더링**을 전혀 지원하지 않았고, Ink를 쓰는 앱 대부분도 아직 활성화하지 않음. 그 증분 렌더링도 [라인 기반](https://github.com/vadimdemedes/ink/pull/781)이라 실제 타이머 위치로 커서를 옮기지는 않음  
  Gemini CLI는 증분 렌더링을 켜려면 [대체 버퍼 사용이 필요](https://github.com/google-gemini/gemini-cli/blob/4e175527a2b241a68afd5f1509a8bebc21a44dfe/packages/cli/src/interactiveCli.tsx#L165-L167)하고, 이는 내장 **화면 읽기 도구 친화 모드**가 켜지면 [비활성화됨](https://github.com/google-gemini/gemini-cli/blob/4e175527a2b241a68afd5f1509a8bebc21a44dfe/packages/core/src/utils/terminal.ts#L76-L81). 관련 옵션 문서는 [여기](https://geminicli.com/docs/cli/settings/#:~:text=ui.accessibility.screenReader)에 있음  
  덧붙이면 Python의 rich/textual은 더 느리고 주로 단일 스레드인 언어 위에서도 Ink보다 훨씬 빠른 경우가 많음. 수천 줄 차이 계산이 반드시 그렇게 느린 것도 아니고, 10초씩 걸릴 정도는 아님  
  사용자 경험이 답답하고 망가졌다는 점은 의심하지 않지만, 제시된 정확한 원인은 LLM 환각이거나 불완전한 정보에 기반했을 가능성이 있어 보임. Ink의 증분 렌더링은 켜져 있더라도 설명처럼 동작하지 않음  
  실제로는 전체 화면 다시 그리기가 화면 읽기 도구를 혼란스럽게 만들고, 라인 기반 다시 그리기가 변경과 무관한 임의의 끊어진 텍스트 조각들을 다시 읽게 만드는 식으로 나쁠 가능성이 큼  
  
- TUI만 탓하는 건 공정하지 않음  
  진짜 문제는 거의 전체 스택의 **접근성 지원**이 형편없다는 데 있음  
  첫째, GPU 렌더링 터미널 에뮬레이터 대부분은 시스템 제공 접근성 API를 전혀 쓰지 않음. 텍스트가 GPU로 렌더링되면 접근성 도구가 “읽을” 수 없고 이미지처럼 보일 뿐임. Kitty, Alacritty, WezTerm이 여기에 해당함. 내 터미널 Ghostty는 macOS에서 접근성 API로 읽을 수 있고, iTerm2와 Terminal.app도 가능함  
  둘째, TUI가 접근성 정보를 터미널 에뮬레이터에 전달할 터미널 시퀀스나 표준 움직임이 전혀 없음. 터미널 셀, 실행 구간, 영역을 위한 ARIA식 주석에 해당하는 것이 필요하지만 그런 시도는 없음. TUI가 커서를 잘 다뤄도 많은 사용 사례에서 문제가 터질 것임  
  예로 Ghostty에서 **OSC133**과 접근성 API를 통합해 각 셸 프롬프트, 입력, 명령을 단순 텍스트 박스가 아니라 구조적으로 의미 있는 요소로 노출하는 작업을 해왔음. 이는 터미널 명세, TUI, 터미널 에뮬레이터가 함께 맞물려야 함을 보여줌  
  전체 스택이 썩어 있고, 진심으로 고치려는 사람도 거의 없음. 나도 시간이 제한되어 최선을 다할 뿐인데, 이건 생태계 정치까지 필요한 거대한 주제라 감당하기 어렵다  
  보너스로, 멋지면서도 끔찍한 현실은 AI가 여기서 접근성 개선을 돕고 있다는 점임. 많은 AI 도구가 접근성 API를 이용하거나 남용해 창 목록을 읽고 입력을 수행함. 그래서 더 많은 앱이 AI 사용 사례 때문에 접근성 통합을 훨씬 진지하게 다루기 시작했음  
  - 터미널이 정말 **작은 브라우저**가 되어 가는 중임  
  
- Claude Code와 gemini-cli가 **readline 기반**이 아니라서 매일 화가 남  
  몇몇 비슷한 키 입력은 넣었지만, 익숙한 readline 단축키의 긴 꼬리는 빠져 있음  
  Anthropic은 “웹 개발처럼 만들어야 한다”는 판단이 실수였다고 인정하고 readline으로 다시 시작해도 됨  
  이런 도구를 만드는 개발자에게 익숙한 개발 경험이, 도구를 쓰는 사용자에게 익숙한 사용자 경험보다 중요하다는 생각은 틀렸음  
  - 이 문제의 큰 부분은 Ink가 사실상 **렌더링 백엔드**에 만족하고 입력 위젯을 제공하지 않는다는 데 있다고 이해함  
    실제로 잘 유지되는 유명한 서드파티 해법도 거의 없음. 유연한 입력 상자가 필요하면 처음부터 직접 만들어야 함  
    [Textual의 훌륭한 Input 위젯](https://textual.textualize.io/widgets/input/)이나, JS 생태계의 다른 라이브러리인 [OpenTUI](https://opentui.com/docs/components/textarea/)와 대비됨  
  - readline은 GNU 라이선스 아닌가? 누군가 드디어 GPL이 아닌 버전을 만든 건가?  
    LLM을 좋아하지는 않아서 UI가 나쁜 건 개인적으로 장점이지만, readline을 쓰지 않는 데는 이유가 있을 수도 있음  
  
- kakoune, helix 같은 터미널 편집기는 “커서 숨기기” 요령을 쓰지 않는 한 **접근성 기준**을 통과하기 어려울 것 같음  
  그래도 VS Code만큼 접근 가능하지는 않을 가능성이 큼  
  VS Code 말고 접근 가능한 크로스플랫폼 IDE-lite나 IDE가 뭐가 있을까? VS Code의 점점 적대적인 태도는 마음에 들지 않음. JetBrains IDE일 수도 있겠음  
  - [emacspeak](https://emacspeak.sourceforge.net/)가 있고, Emacs에 매우 접근성 좋은 인터페이스를 제공함  
    단점은 Emacs 자체는 크로스플랫폼이지만, emacspeak는 TTS 때문에 Linux에 약한 의존성이 있을 수 있다는 점임. 아니면 아닐 수도 있음. Windows에서는 시도해 본 적이 없음  
  - 누구를 위한 접근성인지가 먼저임. 청각장애인을 위한 것이라면 현지 언어의 글과 현지 수어를 제공해야 함. 미국이라면 보통 ASL임  
    시각장애인을 위한 접근성이라면 emacspeak나 플랫폼의 시각장애인용 접근성 도구가 필요함  
    **접근성은 스펙트럼**이지 체크박스가 아님  
  
- Links에는 별도의 [브라유 터미널 모드](https://asciinema.org/a/Slst3gi5EIsmZcAj)가 있는데, 가짜 GUI 요소를 더 단순한 전체 화면 메뉴로 바꾸고 방향키 탐색도 줄 단위로 바꿈  
  또 다른 흥미로운 사례는 [edbrowse](https://edbrowse.org/)임. 시각장애인인 Karl Dahlke가 만든 텍스트 모드 브라우저인데, 더 인기 있는 텍스트 모드 웹 브라우저들과 달리 TUI를 쓰지 않고 ed 스타일의 명령줄 인터페이스를 사용함  
  
- **Ink 프레임워크**라면 CLI가 CPU 100%를 쓰고 영원히 멈춘 채 긴 채팅 기록을 계속 다시 그리는 이유일 가능성이 큼. 안타까움
