개요
TUI(Terminal User Interface) 프레임워크는 터미널 환경에서 인터랙티브 UI를 구축하는 도구입니다. SSH 환경, 리소스 제한 환경, 개발자 도구에서 특히 유용하며, 최근 Go의 Charm 스택을 필두로 르네상스를 맞고 있습니다.
주요 프레임워크
Go — Charm 스택 (Bubble Tea + Lip Gloss + Huh)
| 항목 | 내용 |
|---|---|
| 개발 | Charm |
| 핵심 | Go TUI 생태계의 사실상 표준 |
| 아키텍처 | Elm Architecture (Model-Update-View) |
| GitHub | https://github.com/charmbracelet/bubbletea |
구성:
| 라이브러리 | 역할 |
|---|---|
| Bubble Tea | TUI 프레임워크 (이벤트 루프, 상태 관리) |
| Lip Gloss | 스타일링 (색상, 정렬, 테두리, 패딩) |
| Bubbles | 재사용 컴포넌트 (테이블, 텍스트 입력, 목록 등) |
| Huh | 인터랙티브 폼/프롬프트 |
| Wish | SSH 앱 서버 (SSH로 TUI 서빙) |
| Log | 컬러 로깅 |
| Glow | 터미널 마크다운 렌더러 |
package main
import (
tea "github.com/charmbracelet/bubbletea"
"fmt"
)
type model struct { count int }
func (m model) Init() tea.Cmd { return nil }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q": return m, tea.Quit
case "up": m.count++
case "down": m.count--
}
}
return m, nil
}
func (m model) View() string {
return fmt.Sprintf("Count: %d\n\n↑/↓ to change, q to quit", m.count)
}
func main() {
tea.NewProgram(model{}).Run()
}대표 앱: k9s, lazygit, lazydocker, glow, soft-serve, gh (GitHub CLI)
Python — Textual
| 항목 | 내용 |
|---|---|
| 개발 | Textualize (Will McGugan, Rich 개발자) |
| 핵심 | Python TUI의 사실상 표준, CSS 스타일링 |
| GitHub | https://github.com/Textualize/textual |
특징:
- CSS 기반 레이아웃: 웹 개발 경험 그대로 TUI에 적용
- 위젯 시스템: Button, DataTable, Tree, Input, ListView 등
- async 네이티브: asyncio 기반
- Textual Web: TUI를 브라우저에서도 실행 가능
- DevTools: 실시간 CSS 수정, 스냅샷 테스트
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Button, Static
class CounterApp(App):
CSS = """
Screen { align: center middle; }
#count { text-style: bold; }
"""
count = 0
def compose(self) -> ComposeResult:
yield Header()
yield Static(f"Count: {self.count}", id="count")
yield Button("+1", id="increment")
yield Footer()
def on_button_pressed(self, event: Button.Pressed):
self.count += 1
self.query_one("#count").update(f"Count: {self.count}")
CounterApp().run()관련:
- Rich: 터미널 리치 텍스트 (테이블, 프로그레스바, 마크다운)
- Typer/Click: CLI 인자 파서 (TUI가 아닌 CLI)
대표 앱: Dolphie (MySQL 모니터), Trogon, Posting (HTTP 클라이언트)
Rust — Ratatui
| 항목 | 내용 |
|---|---|
| 개발 | 커뮤니티 (tui-rs 포크) |
| 핵심 | Rust TUI의 사실상 표준, 즉시 모드 렌더링 |
| GitHub | https://github.com/ratatui/ratatui |
특징:
- 즉시 모드(Immediate mode): 매 프레임 전체 UI 재렌더링
- 위젯: Table, List, Chart, Gauge, Sparkline, Canvas 등
- 백엔드: Crossterm(크로스플랫폼), Termion(Unix)
- 고성능: Rust 특성상 최저 메모리/CPU
use ratatui::{prelude::*, widgets::*};
fn ui(frame: &mut Frame) {
let block = Block::default()
.title("Counter")
.borders(Borders::ALL);
let paragraph = Paragraph::new("Count: 42")
.block(block)
.alignment(Alignment::Center);
frame.render_widget(paragraph, frame.area());
}대표 앱: gitui, bottom (btm), bandwhich, wiki-tui
JavaScript/TypeScript — Ink
| 항목 | 내용 |
|---|---|
| 개발 | Vadim Demedes |
| 핵심 | React로 TUI 구축 |
| GitHub | https://github.com/vadimdemedes/ink |
특징:
- React 컴포넌트 모델 그대로 터미널에 적용
- JSX로 TUI 작성
- Flexbox 레이아웃
- React hooks 사용 가능
import React, {useState} from 'react';
import {render, Text, Box, useInput} from 'ink';
const Counter = () => {
const [count, setCount] = useState(0);
useInput((input) => {
if (input === 'k') setCount(c => c + 1);
if (input === 'j') setCount(c => c - 1);
});
return <Box><Text>Count: {count}</Text></Box>;
};
render(<Counter />);대표 앱: Pastel (Prettier CLI), create-ink-app
기타
| 프레임워크 | 언어 | 특징 |
|---|---|---|
| ncurses | C | 원조 TUI 라이브러리, 저수준 |
| Brick | Haskell | 선언적 TUI, Elm 아키텍처 |
| tview | Go | 위젯 기반, Bubble Tea보다 전통적 |
| Cursive | Rust | ncurses 스타일 Rust TUI |
| FTXUI | C++ | 함수형 터미널 UI |
| prompt_toolkit | Python | 고급 프롬프트/입력 (IPython 기반) |
| blessed | Node.js | ncurses 대안 (레거시) |
비교
| 프레임워크 | 언어 | 아키텍처 | 스타일링 | 학습 곡선 | 생태계 | 성능 |
|---|---|---|---|---|---|---|
| Bubble Tea | Go | Elm (MVU) | Lip Gloss | 중간 | 최대 | 높음 |
| Textual | Python | 이벤트 기반 | CSS | 낮음 | 큼 | 중간 |
| Ratatui | Rust | 즉시 모드 | 코드 | 높음 | 성장 중 | 최고 |
| Ink | JS/TS | React | Flexbox | 낮음 (React 경험 시) | 중간 | 중간 |
| tview | Go | 위젯 | 코드 | 낮음 | 중간 | 높음 |
| ncurses | C | 저수준 | 코드 | 높음 | 레거시 | 최고 |
대표 TUI 앱
| 앱 | 프레임워크 | 용도 |
|---|---|---|
| k9s | Bubble Tea | Kubernetes 관리 |
| lazygit | Bubble Tea | Git TUI |
| lazydocker | Bubble Tea | Docker 관리 |
| gitui | Ratatui | Git TUI (Rust) |
| bottom (btm) | Ratatui | 시스템 모니터 |
| Dolphie | Textual | MySQL 모니터 |
| Midnight Commander | ncurses | 파일 매니저 |
| htop | ncurses | 프로세스 모니터 |
AI + TUI
- Claude Code, Codex CLI, Gemini CLI 등 AI 코딩 에이전트가 TUI 기반
- LLM으로 TUI 코드 생성이 쉬워짐 (Hatchet 사례: 2일 만에 TUI 완성)
- Claude Code가 tmux로 TUI 테스트 자동화 수행
선택 가이드
| 상황 | 추천 |
|---|---|
| Go 프로젝트 | Bubble Tea |
| Python 프로젝트 | Textual |
| Rust 프로젝트 | Ratatui |
| React 경험자 | Ink |
| CSS로 스타일링 | Textual |
| 최고 성능 | Ratatui |
| 가장 큰 생태계 | Bubble Tea |
| SSH 앱 서빙 | Bubble Tea + Wish |
관련 항목
- 프로그래밍 언어 비교
- AI CLI — AI 코딩 에이전트 (TUI 기반)
- AI Coding Agent
- SaaS CLI 도구