터미널 로드맵 — TTY·PTY에서 현대 TUI까지
터미널을 단순한 명령창이 아니라 하나의 입출력·렌더링 스택으로 이해하기 위한 학습 지도. TTY/PTY, termios, ANSI/VT, terminfo, curses를 거쳐 현대 TUI 프레임워크와 실제 애플리케이션 구조까지 바닥부터 올라간다.
터미널에서 동작하는 도구를 오래 쓰다 보면 서로 다른 질문이 결국 같은 바닥으로 모인다. tmux는 왜 터미널을 중첩할 수 있는가, SSH에서도 왜 Neovim 화면이 그대로 보이는가, TUI 앱은 픽셀을 그리지 않는데 어떻게 화면 전체를 갱신하는가, fzf와 btop은 무엇을 직접 구현했고 OpenTUI나 Ratatui는 무엇을 대신해주는가.
이 로드맵은 특정 도구의 사용법보다 그 도구들이 공통으로 기대는 터미널의 원리를 다룬다. 도구 자체의 설정과 사용법은 기존 shell, tmux, neovim 로드맵에 두고, 여기서는 그 아래의 공통 기반을 바닥부터 올라간다.
한눈에 보기
| 단계 | 핵심 질문 | 주요 주제 |
|---|---|---|
| 1. 터미널의 정체 | 터미널은 프로그램인가 장치인가? | 터미널 에뮬레이터(Terminal Emulator), TTY |
| 2. 프로세스와 연결 | 셸과 앱은 터미널에 어떻게 붙는가? | PTY(Pseudoterminal), 표준 입출력, 제어 터미널 |
| 3. 입력 모드 | 왜 TUI는 키를 즉시 받을 수 있나? | termios, canonical/raw mode, echo, signal |
| 4. 화면 제어 | 표준 출력으로 어떻게 커서를 움직이나? | ANSI/VT escape sequence, 커서, 색상, 대체 화면(Alternate Screen) |
| 5. 터미널 차이 추상화 | 터미널마다 기능이 다른데 앱은 어떻게 대응했나? | termcap, terminfo |
| 6. 고전 TUI | escape sequence를 직접 안 쓰고 UI를 어떻게 만들었나? | curses, ncurses, 화면(Screen)·창(Window) 추상화 |
| 7. TUI 엔진 | 화면 전체를 매번 다시 그리는가? | 이벤트 루프(Event Loop), 상태(State), 레이아웃(Layout), 렌더러(Renderer) |
| 8. 현대 TUI | 최근 프레임워크는 무엇을 더 추상화하나? | Bubble Tea, Ratatui, Textual, OpenTUI |
| Branch A. 실제 앱 | 실제 앱은 어느 추상화 계층을 선택했나? | fzf, btop, lazygit, Yazi, Harlequin, OpenCode |
| Branch B. TUI 플랫폼 | TUI가 다시 상위 UI 플랫폼이 될 수 있나? | Neovim 내장 TUI, UI protocol, vim.ui, nui, Snacks, LazyVim |
| Integration. 전체 연결 | tmux와 SSH는 이 스택 어디에 끼나? | 터미널 에뮬레이터 ↔ PTY ↔ 셸/tmux/SSH ↔ 애플리케이션 |
1. 터미널은 무엇인가
출발점은 GUI 앱으로서의 Ghostty·Kitty·iTerm2가 아니라, Unix가 말하는 터미널이라는 추상화가 무엇인지 이해하는 것이다. 물리 터미널에서 터미널 에뮬레이터로 바뀌었어도 프로그램 입장에서는 여전히 터미널 장치와 대화하는 것처럼 보인다.
여기서 TTY의 역사와 현재 의미를 잡는다.
2. TTY와 PTY — 프로세스는 터미널에 어떻게 붙는가
현대 터미널 에뮬레이터는 보통 PTY(Pseudoterminal, 물리 터미널처럼 동작하는 가상 터미널 장치)를 만들고 그 반대편에 셸을 실행한다.
1
2
3
4
5
6
7
터미널 에뮬레이터
↕
PTY
↕
셸
↕
애플리케이션
이 구조를 이해하면 ssh, tmux, 컨테이너의 -t, 터미널 크기 변경 같은 현상이 한 계통으로 연결되기 시작한다.
3. 표준 입출력과 termios — 키 입력은 어떻게 앱까지 오는가
평범한 셸 입력에서는 Enter 전까지 한 줄을 모으지만, Neovim이나 fzf는 키 하나를 누르는 즉시 반응한다. 차이는 터미널 드라이버의 입력 모드다.
- canonical mode
- raw mode
- echo
- control character
Ctrl-C와 signal
여기서는 termios를 직접 바꿔보며 입력 경로를 확인한다.
글: termios와 raw mode — Ctrl-C는 언제 문자가 아니라 signal이 되는가
4. ANSI/VT Escape Sequence — 텍스트로 화면을 그리는 법
TUI(Terminal User Interface, 터미널 화면에서 상호작용하는 사용자 인터페이스) 앱이 보통 픽셀을 직접 그리는 것은 아니다. 표준 출력에 일반 문자와 함께 escape sequence를 출력하고 터미널 에뮬레이터가 이를 커서 이동·색상·화면 지우기 명령으로 해석한다.
직접 printf로 커서를 움직이고 화면을 지우는 실험을 해본다.
글: ANSI/VT Escape Sequence — 표준 출력으로 커서를 움직이고 화면을 그리는 법
5. termcap과 terminfo — 서로 다른 터미널을 다루는 법
과거 터미널마다 지원 기능과 제어 문자열이 달랐다. 이를 데이터로 기술하고 애플리케이션이 조회할 수 있게 한 계층이 termcap과 terminfo다.
여기서 TERM, capability database, tput이 연결된다.
글: termcap과 terminfo — 터미널마다 다른 제어 코드를 어떻게 숨겼나
6. curses/ncurses — 화면과 창 추상화의 등장
escape sequence를 직접 조합하는 대신 화면을 하나의 상태로 다루고 필요한 부분을 갱신하는 라이브러리가 등장했다.
1
2
3
4
5
6
7
애플리케이션
↓
curses / ncurses
↓
terminfo
↓
터미널
vi 같은 초기 애플리케이션과 이후 curses 계열 프로그램을 비교하며 추상화 수준이 어떻게 올라갔는지 본다.
글: curses와 ncurses — 터미널 제어가 Screen·Window 추상화로 올라온 순간
7. TUI 엔진 — 이벤트 루프에서 렌더링까지
현대 TUI 프레임워크를 이해하려면 내부의 공통 구조를 먼저 본다.
1
2
3
4
5
6
7
8
9
10
11
입력 이벤트(Input Event)
↓
이벤트 루프(Event Loop)
↓
상태 갱신(State Update)
↓
레이아웃(Layout)
↓
렌더링(Render)
↓
터미널
핵심은 전체 화면을 무작정 출력하는 것이 아니라 현재 UI 상태와 터미널 셀의 차이를 계산해 필요한 부분을 갱신하는 방식이다.
글: TUI 엔진의 공통 구조 — 이벤트 루프, 상태, 레이아웃, 렌더러
8. 현대 TUI 프레임워크
고전 curses에서 더 올라가 상태·컴포넌트·레이아웃까지 프레임워크가 담당하기 시작한다.
| 생태계 | 대표 도구 | 주로 추상화하는 것 |
|---|---|---|
| Go | Bubble Tea | Elm식 Model/Update/View |
| Rust | Ratatui + Crossterm | Widget/Layout + 터미널 백엔드 |
| Python | Textual | Widget, event, CSS형 layout/style |
| TypeScript | OpenTUI | 컴포넌트, 레이아웃, native renderer, React/Solid bindings |
글: 현대 TUI 프레임워크 비교 — 무엇을 얼마나 추상화하는가
배경 글: TUI의 역사와 현대 프레임워크 — ncurses에서 OpenTUI까지
여기까지가 터미널 자체를 이해하는 핵심 스택이다. 아래부터는 이 스택을 실제 앱과 조합에 적용해 보는 선택적 Zoom-in이다.
Branch A — 실제 애플리케이션을 추상화 계층에 꽂아보기
프레임워크 이름을 외우는 대신 실제 사용하는 도구가 어느 계층을 선택했는지 본다.
fzf,btop, Neovim처럼 자체 TUI 처리 계층을 가진 프로그램- 중간 수준 TUI 계층을 사용하는 lazygit/Yazi
- Textual 기반 Harlequin
- OpenTUI 기반 OpenCode
같은 “TUI”라도 어떤 앱은 터미널에 가까이 내려가고, 어떤 앱은 고수준 프레임워크 위에서 만들어진다.
글: 실제 TUI 앱은 어느 추상화 계층에 서 있나 — fzf부터 OpenCode까지
Branch B — Neovim: TUI가 다시 플랫폼이 되는 사례
Neovim은 단순한 터미널 애플리케이션에서 끝나지 않는다.
1
2
3
4
5
6
7
8
9
10
11
터미널
↑
Neovim 내장 TUI
↑
Neovim UI / Window / Buffer API
↑
vim.ui / nui.nvim / Snacks
↑
플러그인
↑
LazyVim
자체 TUI가 다시 플러그인용 UI 플랫폼의 바닥이 되고, 그 위에 UI 라이브러리와 배포판 생태계가 올라간다. 추상화가 한 번만 일어나는 것이 아니라 반복해서 층을 만든다는 좋은 사례다.
글: Neovim은 왜 TUI 앱이면서 UI 플랫폼인가
Integration — tmux·SSH까지 전체 스택 연결하기
마지막에는 개별 개념을 한 그림으로 연결한다.
1
2
3
4
5
6
7
8
9
10
11
Ghostty
↕
로컬 PTY
↕
tmux client
↕
tmux server
↕
PTY
↕
Neovim / fzf / 셸
SSH가 들어오면 어느 쪽에서 PTY가 생기는지, TERM은 어디서 전달되는지, 터미널 크기 변경과 signal은 어떻게 흘러가는지를 추적한다.
다른 로드맵과의 경계
이 로드맵은 공통 기반 원리만 다룬다.
- zsh/bash 문법·파이프·스크립팅·환경변수 관리 →
shell - tmux 설정·키맵·세션·플러그인 →
tmux - Neovim 편집·LSP·플러그인·LazyVim 사용법 →
neovim - 터미널 자체, PTY, 입력 모드, escape sequence, TUI 렌더링 원리 →
terminal
즉 도구를 쓰는 법은 도구 폴더, 도구들이 공통으로 기대는 터미널 원리는 이 로드맵에 둔다.