터미널 UI: BubbleTea (Go) vs Ratatui (Rust)
Source: Dev.to
(번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.)
Source: …
BubbleTea (Go)
BubbleTea란?
BubbleTea는 The Elm Architecture를 기반으로 한 Go용 TUI 프레임워크입니다. 앱을 모델(상태)과 다음 세 가지 요소로 정의합니다:
| 요소 | 목적 |
|---|---|
| Init | 초기 커맨드(또는 nil)를 반환합니다. |
| Update | 들어오는 메시지를 처리하고, 새로운 모델과 선택적인 커맨드를 반환합니다. |
| View | UI를 문자열로 렌더링합니다. |
프레임워크는 이벤트 루프를 실행하고, 키 입력 및 I/O를 메시지로 변환하며, 모델이 변경될 때마다 UI를 다시 그립니다. 요컨대, 단일 진리 원천과 예측 가능한 업데이트를 갖춘, Go에서 터미널 앱을 만들기 위한 재미있고 상태 기반의 방법입니다.
BubbleTea를 선택해야 하는 이유
- 수만 개의 GitHub 스타를 보유한 프로덕션 레디(v1.x) 버전.
- 인라인, 전체 화면, 혹은 혼합 형태 모두 지원.
- 보통 Bubbles(입력, 뷰포트, 스피너 등 컴포넌트)와 Lip Gloss(스타일링)와 함께 사용됩니다.
- 일반적인 Go 프로젝트 레이아웃(
cmd/, 패키지 등)에 자연스럽게 녹아듭니다.
최소 BubbleTea 프로그램
package main
import (
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
)
type model struct {
choices []string
cursor int
selected map[int]struct{}
}
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 "ctrl+c", "q":
return m, tea.Quit
case "up", "k":
if m.cursor > 0 {
m.cursor--
}
case "down", "j":
if m.cursor "
}
checked := " "
if _, ok := m.selected[i]; ok {
checked = "x"
}
s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
}
return s + "\nPress q to quit.\n"
}
func main() {
if _, err := tea.NewProgram(model{
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
selected: make(map[int]struct{}),
}).Run(); err != nil {
fmt.Printf("error: %v", err)
os.Exit(1)
}
}
BubbleTea로 만든 주요 앱
- Crush – Charm의 TUI 기반 AI 코딩 에이전트.
- Glow – 마크다운 뷰어.
- Huh – 인터랙티브 프롬프트.
- 그 외에도 Go 트렌딩 프로젝트 생태계에서 많이 사용되는 도구들.
대규모 Go 애플리케이션에서는 의존성 주입, 견고한 단위 테스트, 기타 Go 관용 패턴을 추가할 수 있으며, 동일한 개념을 BubbleTea 모델과 커맨드에 적용할 수 있습니다.
Ratatui (Rust)
Ratatui란?
Ratatui는 즉시‑모드 렌더링을 사용하는 Rust 기반 TUI 라이브러리입니다. 매 프레임마다 전체 UI(위젯과 레이아웃)를 기술하면 Ratatui가 이를 그려줍니다.
- 가볍고 의견이 강제되지 않으며 – Elm‑스타일 모델이나 특정 앱 구조를 강요하지 않습니다.
- 직접 상태를 관리하고, 자체 이벤트 루프를 실행합니다(보통 crossterm, termion, termwiz 중 하나와 함께 사용). 그리고
terminal.draw(|f| { … })를 호출해 렌더링합니다.
Elm‑스타일 vs. 즉시‑모드
| 접근 방식 | 루프를 누가 소유하나요? | UI는 어떻게 기술하나요? |
|---|---|---|
| Elm‑스타일 (BubbleTea) | 프레임워크 | Update → View (변경된 부분만 다시 그려짐) |
| 즉시‑모드 (Ratatui) | 당신(앱) | 매 프레임 현재 상태에서 전체 UI를 다시 구축 |
왜 Ratatui를 선택해야 할까요?
- 2,100개 이상의 크레이트에서 사용되고, Netflix(
bpftop), OpenAI, AWS(amazon-q-developer-cli), Vercel 등 기업에서도 신뢰하고 있습니다. - 현재 안정 버전은 0.30.x이며, 문서가 풍부하고 선택적인 백엔드를 제공합니다.
- 입력 처리와 렌더링을 완전하게 제어해야 하거나, 이미 Rust 생태계에서 작업하고 있다면 이상적입니다.
최소 Ratatui 프로그램
use crossterm::event::{self, Event, KeyCode};
use ratatui::{prelude::*, widgets::Paragraph};
use std::time::Duration;
fn main() -> Result<()> {
// Initialise the terminal
let mut terminal = ratatui::init();
loop {
// Draw the UI each frame
terminal.draw(|frame| {
let area = frame.area();
frame.render_widget(
Paragraph::new("Hello, Ratatui! Press q to quit.")
.alignment(Alignment::Center),
area,
);
})?;
// Handle input (poll every 250 ms)
if event::poll(Duration::from_millis(250))? {
if let Event::Key(key) = event::read()? {
if key.code == KeyCode::Char('q') {
break;
}
}
}
}
// Restore the terminal state before exiting
ratatui::restore();
Ok(())
}
언제 어떤 것을 선택할까?
| 항목 | BubbleTea (Go) | Ratatui (Rust) |
|---|---|---|
| Architecture | Elm 아키텍처 (model + Init/Update/View) | 즉시 모드 (루프를 직접 관리) |
| Ecosystem | Bubbles, Lip Gloss, 10k+ 앱 (예: Crush) | 2,100+ 크레이트, Netflix, OpenAI, AWS, Vercel 사용 |
| Best for | 빠른 반복, Go 팀, CLI | 전체 제어, 성능에 민감한 TUI, Rust 코드베이스 |
| Typical use‑case | Go에서 다듬어진 TUI를 가장 빠르게 만들고 싶을 때 | 최대 제어가 필요하거나 이미 Rust를 사용 중일 때 |
핵심: 두 프레임워크 모두 훌륭합니다. 선호하는 언어와 프레임워크에서 원하는 구조의 정도가 선택을 좌우해야 합니다.
추가 읽을거리 및 자료
- 2026년 1월 GitHub에서 트렌드 상위 19개 Go 프로젝트
- 2026년 1월 GitHub에서 트렌드 상위 23개 Rust 프로젝트
- Go에서 의존성 주입: 패턴 및 모범 사례
위 스크린샷의 Crush UI는 BubbleTea 프레임워크를 사용해 구현되었습니다.
실무
- Go SDKs for Ollama – 예시와 비교
- PostgreSQL용 Go ORM 비교: GORM vs Ent vs Bun vs sqlc
- Go 프로젝트 구조: 실무 및 패턴
- Go 단위 테스트: 구조 및 모범 사례
- Bubble Tea – Go TUI를 위한 Elm 아키텍처
- Ratatui – 소개
- Ratatui – 렌더링 (즉시 모드)
- Charm Crush – TUI 코딩 에이전트
- crates.io에 있는 Ratatui