터미널 UI: BubbleTea (Go) vs Ratatui (Rust)

Elm 스타일 (Go) vs 즉시 모드 (Rust) TUI 프레임워크 빠른 비교

Page content

두 가지 강력한 선택지는 오늘날 터미널 사용자 인터페이스(TUI)를 구축하는 데 있어 BubbleTea (Go) 및 Ratatui (Rust). 하나는 Elm 스타일의 의견 있는 프레임워크를 제공하고, 다른 하나는 유연한 즉시 모드 라이브러리입니다.

이 게시물은 각각이 무엇인지 요약하고, 두 가지 모두에 대한 최소 예제를 보여주며, 어떤 경우에 어떤 것을 선택해야 하는지 제안합니다. 예, 유용한 링크도 제공합니다.

Crush UI - BubbleTea 프레임워크를 사용하여 구현됨

Crush UI (위 스크린샷)는 BubbleTea 프레임워크를 사용하여 구현되었습니다.

BubbleTea란 무엇인가요?

BubbleTeaThe Elm Architecture 기반의 Go TUI 프레임워크입니다. 모델(상태)과 세 가지 요소인 Init(초기 명령), Update(메시지를 처리하고 새 모델과 선택적 명령을 반환), View(UI를 문자열로 렌더링)로 앱을 설명합니다. 프레임워크는 이벤트 루프를 실행하고, 키 입력 및 I/O를 메시지로 변환하며, 모델이 변경되면 다시 렌더링합니다. 따라서: BubbleTea란 무엇인가요? 간단히 말해, Go로 터미널 앱을 만들 때 단일 진실 원천과 예측 가능한 업데이트를 통해 재미있는, 상태 있는 방식입니다.

BubbleTea는 프로덕션 준비가 되었으며(v1.x), 수만 개의 GitHub 스타와 수천 개의 알려진 임포터가 있으며, 인라인, 전체 화면, 또는 혼합 화면에서도 작동합니다. 일반적으로 Bubbles와 함께 사용하여 구성 요소(입력, 뷰포트, 스피너)를 만들고 Lip Gloss를 사용하여 스타일링합니다. Go TUI를 구축 중이라면, 앱이 성장함에 따라 cmd/와 패키지가 명확하게 유지되도록 일반적인 Go 프로젝트 구조를 따르는 것이 좋습니다.

최소한의 BubbleTea 프로그램은 다음과 같습니다: 모델, Init, Update(키 메시지 처리), View가 문자열을 반환합니다. 런타임은 나머지 작업을 수행합니다.

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 < len(m.choices)-1 { m.cursor++ }
        case "enter", " ":
            if _, ok := m.selected[m.cursor]; ok {
                delete(m.selected, m.cursor)
            } else {
                m.selected[m.cursor] = struct{}{}
            }
        }
    }
    return m, nil
}

func (m model) View() string {
    s := "What should we buy?\n\n"
    for i, choice := range m.choices {
        cursor := " "
        if m.cursor == i { 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 및 GitHub에서 가장 인기 있는 Go 프로젝트 생태계의 많은 도구들이 포함됩니다. 더 복잡한 Go 앱을 만들고자 한다면 의존성 주입 및 견고한 단위 테스트를 추가할 수 있습니다; 동일한 아이디어는 BubbleTea 모델과 명령에도 적용됩니다.

Ratatui란 무엇인가요?

Ratatui즉시 모드(immediate-mode) 렌더링을 사용하는 Rust TUI 라이브러리입니다: 각 프레임마다 전체 UI(위젯 및 레이아웃)를 설명하고, Ratatui가 그릴 수 있습니다. Ratatui란 무엇인가요? 가볍고 중립적인 도구킷입니다. Elm 스타일의 모델이나 특정 앱 구조를 강요하지 않습니다. 자신의 상태를 유지하고, 자신의 이벤트 루프를 실행(일반적으로 crossterm, termion, 또는 termwiz를 사용), 그리고 terminal.draw(|f| { ... })를 호출하여 렌더링합니다. 따라서 Elm 스타일과 즉시 모드 사이의 차이는 정확히 이점입니다: Elm 스타일에서는 프레임워크가 루프를 소유하고, Update/View를 통해 반응하며, 즉시 모드에서는 루프를 소유하고, 각 프레임에서 현재 상태로 전체 UI를 다시 그립니다.

Ratatui는 2,100개 이상의 크레이트에서 사용되고 있으며, Netflix (예: bpftop), OpenAI, AWS (예: amazon-q-developer-cli), Vercel 등과 같은 회사에서 신뢰받고 있습니다. 현재 버전 0.30.x이며, 강력한 문서와 선택적 백엔드가 제공됩니다. 입력과 렌더링에 대한 완전한 제어가 필요하거나, 이미 Rust 생태계에 있다면 Ratatui가 좋은 선택입니다.

최소한의 Ratatui 앱: 터미널을 초기화하고, 그린 후 이벤트를 읽는 루프를 실행하고, 종료 시 터미널을 복원합니다.

use crossterm::event::{self, Event, KeyCode};
use ratatui::{prelude::*, widgets::Paragraph};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut terminal = ratatui::init();
    loop {
        terminal.draw(|frame| {
            let area = frame.area();
            frame.render_widget(
                Paragraph::new("Hello, Ratatui! Press q to quit.").alignment(Alignment::Center),
                area,
            );
        })?;
        if event::poll(Duration::from_millis(250))? {
            if let Event::Key(key) = event::read()? {
                if key.code == KeyCode::Char('q') {
                    break;
                }
            }
        }
    }
    ratatui::restore();
    Ok(())
}

따라서: 언제 BubbleTea와 Ratatui 중 하나를 선택해야 하나요? BubbleTea를 선택하세요. Go로 정교한 TUI를 가장 빠르게 만들고 싶고, 단일 모델과 명확한 Update/View가 있으며, 팀이나 생태계가 Go(예: 이미 Go ORMs 또는 Go에서 Ollama 사용을 사용 중인 경우. Ratatui를 선택하세요. 입력과 렌더링에 대한 최대한의 제어가 필요하거나, Rust에 있으며, 성능 민감하거나 자원 제한이 있는 TUI를 구축하고자 할 때; 즉시 모드 설계와 선택적 백엔드는 이러한 유연성을 제공합니다.

요약

항목 BubbleTea (Go) Ratatui (Rust)
스타일 Elm 아키텍처 (모델, Init/Update/View) 즉시 모드 (루프를 소유, 프레임마다 렌더링)
생태계 Bubbles, Lip Gloss, 10,000개 이상의 앱, Crush 2,100개 이상의 크레이트, Netflix/OpenAI/AWS/Vercel
가장 적합한 경우 빠른 반복, Go 팀, CLI 제어, 성능, Rust 코드베이스

둘 다 훌륭한 선택입니다. 선호하는 언어와 프레임워크에서 얼마나 많은 구조를 원하는지가 결정을 이끌어야 합니다.

유용한 링크

외부 자원