- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며 — 왜 다시 터미널인가
- Slumber — 터미널의 Postman
- 카테고리별 베스트 TUI
- fzf — 목록이 있는 곳에 fzf가 있다
- 멀티플렉서 — tmux와 zellij
- 조합 워크플로 — 어느 백엔드 개발자의 오전
- 직접 만들어보기 — ratatui와 bubbletea 맛보기
- 곁들이면 좋은 주변 도구들
- 도입 가이드 — 점진적으로, 한 번에 하나씩
- 한계와 비판적 시각
- 마치며
- 참고 자료
들어가며 — 왜 다시 터미널인가
최근 Hacker News와 GeekNews에서 Slumber라는 터미널 기반 HTTP 클라이언트가 소개되며 좋은 반응을 얻었습니다. Postman의 자리를 터미널 안에서 대체하겠다는 도구인데, 댓글란의 분위기가 흥미로웠습니다. "또 TUI야?"가 아니라 "드디어 이 영역에도 쓸 만한 TUI가 나왔다"는 환영 일색이었거든요. lazygit, k9s, btop 같은 도구들이 수만 개의 GitHub 스타를 쌓아온 흐름의 연장선입니다.
TUI(Text-based User Interface)가 다시 뜨는 데에는 구조적인 이유가 있습니다.
첫째, 원격 개발이 기본값이 됐습니다. 개발 환경이 클라우드 VM, 컨테이너, SSH 너머로 옮겨가면서 "어디서나 같은 도구"의 가치가 커졌습니다. GUI는 포워딩이 고통스럽지만 TUI는 SSH만 되면 끝입니다.
둘째, 키보드 워크플로의 재평가입니다. 마우스 왕복 없이 손이 홈로우에 머무는 작업 흐름은 한 번 몸에 붙으면 되돌아가기 어렵습니다. vim 키바인딩이 사실상의 표준 인터페이스가 되면서 도구 간 학습 전이도 쉬워졌습니다.
셋째, 2026년의 새 변수인데, AI 코딩 에이전트와 터미널의 궁합입니다. Claude Code 같은 에이전트가 터미널에서 동작하는 시대에, 개발자의 다른 도구들도 같은 터미널 멀티플렉서 안에 있으면 컨텍스트 전환이 사라집니다. 에이전트가 왼쪽 페인에서 코드를 고치는 동안 오른쪽 페인의 lazygit으로 diff를 검토하는 풍경은 이제 흔합니다. GUI 앱은 이 루프에 끼어들 자리가 없습니다.
이 글에서는 Slumber를 시작으로 카테고리별 베스트 TUI, 조합 워크플로, 그리고 ratatui/bubbletea로 직접 만들어보는 맛보기까지 다룹니다.
Slumber — 터미널의 Postman
Slumber는 Rust로 작성된 HTTP 클라이언트로, 세 가지 형태를 동시에 제공하는 것이 특징입니다. 같은 설정 파일 하나로 TUI(대화형 탐색), CLI(스크립트/CI용), 라이브러리(Rust 코드에서 호출)로 쓸 수 있습니다.
핵심 개념은 recipe입니다. 요청을 YAML 파일에 선언적으로 정의해두고 재사용합니다. Postman 컬렉션의 텍스트 파일 버전이라고 생각하면 됩니다. 당연히 git으로 버전 관리되고 코드 리뷰가 가능합니다.
# slumber.yml — 프로젝트 루트에 두면 자동 인식
profiles:
local:
data:
host: http://localhost:8000
production:
data:
host: https://api.example.com
requests:
login: !request
method: POST
url: "{{host}}/auth/login"
body: !json { "username": "demo", "password": "hunter2" }
list_users: !request
method: GET
url: "{{host}}/users"
authentication: !bearer "{{chains.auth_token}}"
query:
- page=1
- limit=20
chains:
auth_token:
source: !request
recipe: login
selector: $.token
위 설정의 chains가 Slumber의 강점입니다. "login 요청의 응답에서 JSONPath로 토큰을 뽑아 다음 요청의 Bearer 헤더에 넣는다"는 의존 관계를 선언만으로 처리합니다. 사용은 이렇게 합니다.
# TUI 모드 — 대화형으로 탐색, 프로필 전환, 응답 확인
slumber
# CLI 모드 — 같은 recipe를 스크립트/CI에서 실행
slumber request --profile production list_users
# 응답만 뽑아 파이프라인에 연결
slumber request login | jq .token
"팀원과 공유 가능한 선언적 요청 정의 + 터미널에서 즉시 실행"이라는 조합은 Postman 라이선스 문제와 일렉트론 앱 피로감에 지친 팀에게 충분히 매력적인 대안입니다.
카테고리별 베스트 TUI
git — lazygit
TUI 르네상스의 간판 스타입니다. 스테이징, 커밋, 브랜치, 리베이스, 스태시를 전부 단축키로 처리합니다.
# 설치
brew install lazygit # macOS
sudo apt install lazygit # Ubuntu 25.10+
# 자주 쓰는 흐름: 파일별/헝크별 스테이징
# 파일 패널에서 space = 파일 토글, enter = 헝크 단위로 진입
# 커밋은 c, 푸시는 P, 인터랙티브 리베이스는 브랜치에서 r
특히 헝크 단위 스테이징과 인터랙티브 리베이스가 압권입니다. git rebase -i의 에디터 편집을 화살표와 단축키로 대체하는 경험은 CLI git으로 돌아갈 수 없게 만듭니다. AI 에이전트가 만든 커밋들을 검토하고 squash로 정리하는 용도로도 그만입니다.
쿠버네티스 — k9s
클러스터 운영자의 필수품입니다. kubectl 명령을 외울 필요 없이 리소스 사이를 빠르게 항해합니다.
k9s # 기동
# :pods → 파드 목록 (콜론으로 리소스 전환)
# /error → 목록 필터링
# l → 로그, s → 셸 진입, d → describe
# ctrl-d → 삭제, :ctx → 컨텍스트 전환
장애 대응 중 "파드 목록 → 로그 → 이벤트 → 노드 상태"를 오가는 속도는 kubectl 타이핑이나 웹 대시보드와 비교가 되지 않습니다.
도커 — lazydocker
lazygit 작자의 도커 버전입니다. 컨테이너/이미지/볼륨 상태와 로그, 통계를 한 화면에서 봅니다. docker compose 환경에서 "어떤 서비스가 왜 죽었나"를 확인하는 최단 경로입니다.
데이터베이스 — rainfrog, harlequin
rainfrog는 PostgreSQL 중심의 가벼운 쿼리 탐색기, harlequin은 DuckDB/SQLite/Postgres 등을 지원하는 "터미널 SQL IDE"에 가깝습니다. 둘 다 vim 키바인딩으로 쿼리 편집과 결과 탐색이 됩니다.
harlequin mydata.duckdb # DuckDB 파일 열기
rainfrog --url postgres://user@localhost/mydb
파일 매니저 — yazi
Rust로 작성된 차세대 파일 매니저입니다. 비동기 IO 덕에 거대 디렉터리에서도 멈추지 않고, 이미지 프리뷰(커널 그래픽 프로토콜 지원 터미널), 일괄 이름 변경, zoxide 연동까지 갖췄습니다.
모니터링 — btop
htop의 정신적 후계자입니다. CPU/메모리/디스크/네트워크/프로세스를 마우스도 지원하는 미려한 화면으로 보여줍니다. GPU 모니터링 플러그인도 지원합니다.
한눈에 보는 추천 목록
| 카테고리 | 도구 | 한 줄 설명 |
|---|---|---|
| git | lazygit | 헝크 스테이징과 리베이스의 결정판 |
| 쿠버네티스 | k9s | 클러스터 항해의 표준 |
| 도커 | lazydocker | compose 환경 디버깅 최단 경로 |
| HTTP | slumber | recipe 기반, TUI/CLI/라이브러리 3형태 |
| DB | harlequin | 터미널 SQL IDE |
| 파일 | yazi | 비동기 + 프리뷰 + 일괄 작업 |
| 모니터링 | btop | 아름답고 빠른 시스템 대시보드 |
| 퍼지 파인더 | fzf | 모든 목록의 만능 인터페이스 |
| 멀티플렉서 | tmux, zellij | 모든 TUI를 담는 그릇 |
fzf — 목록이 있는 곳에 fzf가 있다
fzf는 단독 도구라기보다 "아무 목록이나 받아 대화형 선택기로 바꾸는" 빌딩 블록입니다. 레시피 몇 개만 익혀도 체감이 다릅니다.
# 1. 브랜치 퍼지 체크아웃
git branch --all | grep -v HEAD | fzf | sed 's/.* //' | xargs git checkout
# 2. 프로세스 골라 죽이기
ps -ef | fzf -m | awk '{print $2}' | xargs kill -9
# 3. 히스토리 검색은 기본 키바인딩으로 (ctrl-r)
# 설치 시 셸 통합을 켜면 ctrl-r/ctrl-t/alt-c가 활성화됨
eval "$(fzf --bash)" # bash 기준, zsh는 fzf --zsh
# 4. ripgrep과 결합한 코드 검색 + 미리보기
rg --line-number --no-heading . | fzf --delimiter : \
--preview 'bat --color=always --highlight-line {2} {1}'
# 5. SSH 대상 퍼지 선택
grep -E '^Host ' ~/.ssh/config | awk '{print $2}' | fzf | xargs -o ssh
포인트는 "fzf를 배운다"기보다 "파이프라인 끝에 fzf를 붙이는 습관"을 들이는 것입니다.
멀티플렉서 — tmux와 zellij
TUI 도구들을 담는 그릇이 멀티플렉서입니다. SSH 세션이 끊겨도 작업이 살아남고(detach/attach), 화면을 분할해 여러 TUI를 동시에 띄웁니다.
tmux는 표준이지만 설정의 진입장벽이 있고, zellij는 기본값이 친절한 현대적 대안입니다. 화면 하단에 단축키 힌트가 항상 떠 있어 학습 곡선이 완만합니다.
# tmux 핵심만
tmux new -s work # 세션 생성
# prefix(ctrl-b) + % : 세로 분할, " : 가로 분할, d : detach
tmux attach -t work # 재접속
# zellij — 레이아웃 파일로 개발 환경을 코드화
zellij --layout dev.kdl
# dev.kdl — 한 번에 뜨는 개발 환경 레이아웃 예시
layout {
pane split_direction="vertical" {
pane command="nvim"
pane split_direction="horizontal" {
pane command="lazygit"
pane command="btop"
}
}
}
조합 워크플로 — 어느 백엔드 개발자의 오전
도구는 조합될 때 가치가 커집니다. 가상의 그러나 전형적인 시나리오로 묶어보겠습니다.
┌────────────────────────── tmux: work 세션 ──────────────────────────┐
│ ┌───────────────┬──────────────────┬───────────────────────────┐ │
│ │ pane 1 │ pane 2 │ pane 3 │ │
│ │ nvim │ AI 코딩 에이전트 │ k9s (스테이징 클러스터) │ │
│ │ (코드 리뷰) │ (버그 수정 위임) │ + lazygit (커밋 검토) │ │
│ └───────────────┴──────────────────┴───────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
- 출근 후 tmux attach 한 번으로 어제의 화면 그대로 복귀합니다.
- 야간 알림으로 들어온 API 5xx를 조사합니다. k9s에서 해당 파드 로그를 열고, 에러 패턴을 확인합니다.
- 재현을 위해 Slumber TUI를 띄워 production 프로필로 문제의 엔드포인트를 호출하고, recipe를 local 프로필로 전환해 수정 후보를 검증합니다.
- 수정 작업 자체는 AI 에이전트에게 위임하고, 그동안 lazygit에서 에이전트가 쌓는 커밋의 diff를 헝크 단위로 검토합니다.
- 의심스러운 쿼리 성능은 harlequin으로 스테이징 DB에 접속해 실행 계획을 확인합니다.
- 머지 전 fzf로 브랜치를 골라 체크아웃하고, CI가 도는 동안 btop으로 로컬 부하를 확인합니다.
이 모든 과정에서 손은 키보드를 떠나지 않고, 화면은 터미널 하나를 떠나지 않습니다. SSH로 접속한 원격 개발 머신이라도 경험이 완전히 동일하다는 것이 핵심입니다.
직접 만들어보기 — ratatui와 bubbletea 맛보기
TUI 르네상스의 또 다른 동력은 프레임워크의 성숙입니다. Rust의 ratatui와 Go의 bubbletea가 양대 산맥입니다.
ratatui (Rust) — 즉시 모드 렌더링
ratatui는 매 프레임 UI를 다시 그리는 immediate mode 방식입니다. 미니 카운터 예제입니다.
use crossterm::event::{self, Event, KeyCode};
use ratatui::{
widgets::{Block, Borders, Paragraph},
DefaultTerminal,
};
fn main() -> std::io::Result<()> {
let mut terminal = ratatui::init();
let result = run(&mut terminal);
ratatui::restore();
result
}
fn run(terminal: &mut DefaultTerminal) -> std::io::Result<()> {
let mut count = 0i64;
loop {
terminal.draw(|frame| {
let body = Paragraph::new(format!("count: {count} (j/k 증감, q 종료)"))
.block(Block::default().title("mini-counter").borders(Borders::ALL));
frame.render_widget(body, frame.area());
})?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('j') => count -= 1,
KeyCode::Char('k') => count += 1,
KeyCode::Char('q') => return Ok(()),
_ => {}
}
}
}
}
bubbletea (Go) — Elm 아키텍처
bubbletea는 Model(상태) → Update(메시지 처리) → View(렌더링)의 Elm 아키텍처를 따릅니다.
package main
import (
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
)
type model struct{ count int }
func (m model) Init() tea.Cmd { return nil }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if key, ok := msg.(tea.KeyMsg); ok {
switch key.String() {
case "k":
m.count++
case "j":
m.count--
case "q":
return m, tea.Quit
}
}
return m, nil
}
func (m model) View() string {
return fmt.Sprintf("count: %d (j/k 증감, q 종료)\n", m.count)
}
func main() {
if _, err := tea.NewProgram(model{}).Run(); err != nil {
os.Exit(1)
}
}
두 프레임워크 모두 30분이면 동작하는 프로토타입이 나옵니다. 사내 배포 현황판, 온콜 체크리스트, 로그 필터 같은 "팀 전용 마이크로 도구"를 TUI로 만들어 배포 바이너리 하나로 나눠주는 패턴이 점점 흔해지고 있습니다. AI 에이전트에게 "이 CLI를 bubbletea TUI로 감싸줘"라고 시키기도 좋은, 잘 정형화된 작업이기도 합니다.
곁들이면 좋은 주변 도구들
본문에서 다룬 핵심 도구 외에, 함께 설치하면 시너지가 나는 주변 도구들도 정리해둡니다.
| 도구 | 영역 | 한 줄 설명 |
|---|---|---|
| atuin | 셸 히스토리 | 히스토리를 SQLite에 저장, 머신 간 동기화와 강력한 검색 |
| zoxide | 디렉터리 이동 | cd의 학습형 대체재, 자주 가는 경로로 점프 |
| bat | 파일 보기 | 문법 강조가 있는 cat, fzf 프리뷰의 단짝 |
| dive | 도커 이미지 | 이미지 레이어별 용량과 변경 분석 |
| lnav | 로그 | 포맷 자동 인식 로그 내비게이터, SQL 질의 지원 |
| dust | 디스크 | du의 시각화 버전, 큰 디렉터리를 한눈에 |
| glow | 마크다운 | 터미널에서 README를 예쁘게 렌더링 |
| posting | HTTP | Textual 기반의 또 다른 TUI HTTP 클라이언트 |
# 설치 예시 (Homebrew)
brew install atuin zoxide bat dive lnav dust glow
# atuin: ctrl-r을 동기화되는 검색 UI로 교체
atuin import auto
eval "$(atuin init zsh)"
# zoxide: cd 대신 z — 한 번 가본 경로는 일부만 입력해도 점프
eval "$(zoxide init zsh)"
z blog # 예: ~/projects/my-blog 로 점프
이 도구들의 공통점은 도입 리스크가 낮다는 것입니다. 기존 명령(cat, cd, du, ctrl-r)의 자리에 들어와 즉시 효과를 내고, 마음에 들지 않으면 원래 명령으로 돌아가면 그만입니다.
자주 받는 질문
우리 팀은 IDE 중심인데 의미가 있나요?
TUI는 IDE를 대체하지 않습니다. JetBrains나 VSCode를 쓰면서도 내장 터미널 패널 안에서 lazygit과 fzf는 그대로 가치를 냅니다. 실제로 가장 흔한 조합이기도 합니다.
Windows에서도 되나요?
WSL2 안에서는 전부 동작합니다. 네이티브 Windows도 Windows Terminal 조합으로 lazygit, fzf, btop 등 상당수가 포팅되어 있지만, 팀 표준으로 삼기 전에 검증이 필요합니다.
SSH 멀티홉 환경에서 느리지 않나요?
TUI는 화면 전체가 아니라 변경분만 다시 그리므로 레이턴시에 의외로 강합니다. 패킷 유실이 잦은 환경이라면 mosh를 곁들이는 것도 방법입니다.
AI 에이전트가 다 해주는데 도구를 배울 필요가 있나요?
에이전트의 출력을 검증하는 것은 여전히 사람의 몫입니다. diff 검토(lazygit), 클러스터 상태 확인(k9s), 요청 재현(slumber)은 그 검증 루프를 빠르게 만드는 핵심 도구입니다.
도구가 너무 많아 설정 지옥이 무섭습니다.
본문의 도구들은 의도적으로 제로 설정을 지향합니다. lazygit, k9s, btop은 설치 직후 기본값만으로 충분히 쓸 만합니다. 설정 파일은 불편함을 실제로 느낀 뒤에 만져도 늦지 않습니다.
도입 가이드 — 점진적으로, 한 번에 하나씩
전부 한꺼번에 바꾸려다 실패하는 경우를 많이 봤습니다. 추천하는 순서는 다음과 같습니다.
- 1주차: fzf. 셸 통합(ctrl-r 히스토리 검색)만 켜도 즉시 효과를 봅니다. 위험도 0.
- 2주차: lazygit. 기존 git 지식이 그대로 이전되므로 학습 비용이 낮고, 효과는 가장 큽니다.
- 3주차: tmux 또는 zellij. 처음엔 분할과 detach/attach만 씁니다. 설정 튜닝의 유혹은 나중으로 미루세요.
- 4주차 이후: 도메인 도구. 쿠버네티스를 만지면 k9s, API 개발이 많으면 slumber, DB 작업이 많으면 harlequin을 추가합니다.
- 항상: 탈출구를 유지. TUI가 안 풀리는 순간엔 주저 없이 원래 CLI/GUI로 돌아가세요. 도구는 종교가 아닙니다.
팀 도입이라면 dotfiles 저장소에 설정을 공유하고, 점심시간 데모 한 번이 문서 열 장보다 효과적입니다.
한계와 비판적 시각
균형을 위해 TUI의 약점도 분명히 짚어야 합니다.
- 러닝커브는 실재합니다. 단축키 기반 인터페이스는 첫 1~2주의 생산성 하락을 동반합니다. 마감이 코앞인 시기의 도입은 피하세요.
- 접근성 문제는 심각합니다. 스크린 리더는 GUI의 접근성 트리를 읽지만, TUI의 셀 기반 화면은 의미 구조를 전달하기 어렵습니다. 시각 장애가 있는 동료가 있는 팀이라면 TUI 전용 워크플로 강제는 배제적 결정이 될 수 있습니다.
- 발견 가능성이 낮습니다. GUI는 메뉴를 훑으며 기능을 발견할 수 있지만, TUI는 도움말(보통 ? 키)을 적극적으로 열어봐야 합니다.
- 터미널 호환성 이슈. 트루컬러, 이미지 프리뷰, 마우스 지원은 터미널 에뮬레이터마다 편차가 있습니다. 특히 Windows 환경이 섞인 팀은 사전 검증이 필요합니다.
- 모든 작업이 텍스트는 아닙니다. 디자인 검토, 복잡한 그래프 탐색, 대시보드 공유 같은 작업은 여전히 GUI/웹이 우월합니다.
"터미널로 돌아가자"는 구호가 아니라, "텍스트와 키보드가 본질인 작업에는 그에 맞는 도구를 쓰자"가 정확한 결론입니다.
마치며
TUI 르네상스는 복고 취미가 아닙니다. 원격 개발의 보편화, 키보드 중심 워크플로의 재평가, 그리고 터미널에서 동작하는 AI 에이전트라는 세 흐름이 만나, 터미널이 다시 개발 작업의 무게중심이 된 결과입니다. Slumber 같은 새 도구가 계속 등장하고 ratatui/bubbletea 생태계가 커지는 것은 이 흐름이 일시적 유행이 아니라는 방증입니다.
오늘 하나만 시작한다면 fzf의 ctrl-r을 켜는 것을 권합니다. 그리고 다음 주에 lazygit을 열어보세요. 한 달 뒤, 여러분의 tmux 세션 안에는 생각보다 많은 것들이 들어와 있을 겁니다.
참고 자료
- Slumber (GitHub): https://github.com/LucasPickering/slumber
- Slumber 공식 문서: https://slumber.lucaspickering.me/
- GeekNews — Slumber 소개: https://news.hada.io/topic?id=30337
- Hacker News: https://news.ycombinator.com/
- lazygit (GitHub): https://github.com/jesseduffield/lazygit
- k9s 공식 사이트: https://k9scli.io/
- lazydocker (GitHub): https://github.com/jesseduffield/lazydocker
- yazi (GitHub): https://github.com/sxyazi/yazi
- btop (GitHub): https://github.com/aristocratos/btop
- fzf (GitHub): https://github.com/junegunn/fzf
- harlequin 공식 사이트: https://harlequin.sh/
- rainfrog (GitHub): https://github.com/achristmascarl/rainfrog
- zellij 공식 사이트: https://zellij.dev/
- ratatui 공식 사이트: https://ratatui.rs/
- bubbletea (GitHub): https://github.com/charmbracelet/bubbletea