⏱️ 예상 읽기 시간: 12분

개요

브라우저에서 터미널을 제공하는 오픈소스는 원격 교육, 데모, 운영 자동화, 임시 접근 공유 등 다양한 활용처가 있습니다. 본 글에서는 대표 프로젝트인 GoTTY, ttyd, Wetty를 여러 관점에서 비교하고, macOS에서 바로 실행 가능한 스모크 테스트 스크립트와 zsh alias를 제공합니다.

프로젝트 한눈에 보기

항목 GoTTY ttyd Wetty
주요 언어 Go C(서버) + libwebsockets Node.js (Express)
최신성/메인터넌스 비교적 레거시(마지막 릴리스 2017) 활발 활발
인증 Basic Auth(-c) Basic/Auth 파일/토큰 옵션 제공 Basic/Auth(옵션·미들웨어)
TLS 자체 옵션(-t) 자체 옵션(–ssl, cert/key) 프록시/자체 설정 가능
다중 접속 멀티플렉서(tmux) 조합 권장 내장 멀티클라이언트 안정 내장 멀티클라이언트
리버스 프록시 가능 용이(Nginx/Caddy) 용이(Express 기반)
배포 난이도 중(레거시 빌드) 낮음(Homebrew) 낮음(npm/Docker)
사용 사례 읽기 전용 쉐어/데모 범용 원격 쉘 브라우저 SSH/로컬 쉘

참고: GoTTY는 레거시 프로젝트로 최신 macOS/ARM 환경에서 빌드 이슈가 있을 수 있습니다. 실무 적용 시 ttyd 또는 Wetty를 우선 검토하는 것을 권장합니다. 원 저장소의 옵션과 보안 경고는 문서에서 확인하세요: yudai/gotty.

아키텍처 및 동작 원리

  • GoTTY: Go 서버가 로컬 TTY 출력을 WebSocket으로 중계하고, 프론트엔드는 xterm.js/hterm를 사용합니다. 옵션 -w로 쓰기를 허용할 수 있으나 기본은 읽기 위주입니다. yudai/gotty
  • ttyd: C 기반 경량 서버가 libwebsockets로 TTY 세션을 브라우저에 중계합니다. 성숙한 옵션 집합과 낮은 오버헤드가 강점입니다. tsl0922/ttyd
  • Wetty: Node.js(Express)와 xterm.js를 조합해 SSH 또는 로컬 쉘을 브라우저에 제공합니다. JS 생태계 익숙한 팀에 적합합니다. butlerx/wetty

보안 관점 비교

  • 전송 보안: 세 프로젝트 모두 기본 HTTP는 평문입니다. 프로덕션에서는 TLS 종단(Nginx/Caddy/Cloudflare) 또는 자체 TLS 옵션(ttyd/GoTTY)을 필수로 고려하세요.
  • 인증:
    • GoTTY: -c user:pass로 Basic Auth. -r 랜덤 URL 옵션도 제공하지만 보안 강도는 낮습니다.
    • ttyd: --credential user:pass 또는 별도 파일/토큰 옵션 제공. 리버스 프록시의 OIDC/SAML과 연계하기 용이.
    • Wetty: 미들웨어/리버스 프록시 조합으로 Basic/OIDC 등 확장 쉬움.
  • 권한 제어: 읽기 전용 데모는 GoTTY 기본값이 안전 측면에서 유리. 상호작용이 필요하면 tmux/명령 래핑, 컨테이너 격리(Docker)로 피해 범위를 줄이세요.
  • 감사/로깅: ttyd/Wetty는 프록시/미들웨어로 접근 로그 적재가 수월합니다. 민감 환경은 Bastion 호스트/세션 레코딩 솔루션을 고려하세요.

성능/운영 관점 비교

  • 리소스 사용량: ttyd가 경량인 편이며, Wetty는 Node 런타임 오버헤드가 있으나 확장성과 DX가 좋습니다.
  • 확장성: 세 프로젝트 모두 리버스 프록시에 올려 다중 인스턴스/세션 관리가 가능합니다. 세션 멀티플렉싱은 tmux/containers 조합이 일반적입니다.
  • 운영 편의성: Homebrew/npm/Docker로 배포가 쉬운 ttyd/Wetty가 유리. GoTTY는 레거시로 빌드 이슈를 감안해야 합니다.

macOS 설치 및 실행

ttyd 설치

brew install ttyd

실행(로컬 bash 쉘 제공, 포트 7681):

ttyd -p 7681 bash

Basic 인증 예:

ttyd -p 7681 --credential user:pass bash

TLS 자체 종단 예(인증서가 있을 때):

ttyd --ssl --ssl-cert /path/cert.pem --ssl-key /path/key.pem -p 8443 bash

Wetty 설치

npm install -g wetty

로컬 쉘 제공:

wetty --port 3000 --command bash

리버스 프록시(Nginx 등) 뒤에서 TLS/인증을 처리하는 구성이 일반적입니다. 세부 옵션은 저장소 문서를 참고하세요: butlerx/wetty.

GoTTY 설치(참고)

GoTTY는 레거시라 최신 macOS/ARM에서 빌드가 실패할 수 있습니다. 가능하면 컨테이너나 기존 바이너리를 활용하세요. 문서 옵션 예시는 아래와 같습니다.

# 실행 예시(포트 8080, 읽기 전용 top)
gotty -p 8080 top

# Basic Auth
gotty -p 8080 -c user:pass bash

# 제목 포맷(브라우저 타이틀)

gotty --title-format "{{ .command }}@{{ .hostname }}" bash

옵션과 보안 경고는 저장소를 확인하세요: yudai/gotty.

스모크 테스트 스크립트(macOS)

세 도구를 감지해 동시에 기동 후 HTTP 응답을 확인하는 간단한 스크립트입니다. 설치된 항목만 테스트합니다.

#!/usr/bin/env bash
set -euo pipefail

TTVD_PORT=7681
WETTY_PORT=3000
GOTTY_PORT=8080

cleanup() {
  [[ -n "${TTVD_PID:-}" ]] && kill "$TTVD_PID" 2>/dev/null || true
  [[ -n "${WETTY_PID:-}" ]] && kill "$WETTY_PID" 2>/dev/null || true
  [[ -n "${GOTTY_PID:-}" ]] && kill "$GOTTY_PID" 2>/dev/null || true
}
trap cleanup EXIT

if command -v ttyd >/dev/null 2>&1; then
  ttyd -p "$TTVD_PORT" bash &
  TTVD_PID=$!
fi

if command -v wetty >/dev/null 2>&1; then
  wetty --port "$WETTY_PORT" --command bash &
  WETTY_PID=$!
fi

if command -v gotty >/dev/null 2>&1; then
  gotty -p "$GOTTY_PORT" bash &
  GOTTY_PID=$!
fi

sleep 2

check_port() {
  local name=$1 port=$2
  if curl -fsS "http://127.0.0.1:${port}" >/dev/null 2>&1; then
    echo "${name} OK on :${port}"
  else
    echo "${name} NOT RESPONDING on :${port}" >&2
  fi
}

[[ -n "${TTVD_PID:-}" ]] && check_port ttyd "$TTVD_PORT"
[[ -n "${WETTY_PID:-}" ]] && check_port wetty "$WETTY_PORT"
[[ -n "${GOTTY_PID:-}" ]] && check_port gotty "$GOTTY_PORT"

예상 출력:

ttyd OK on :7681
wetty OK on :3000
gotty OK on :8080

zshrc alias 제안

# ~/.zshrc
alias ttyd-up="ttyd -p 7681 bash"
alias wetty-up="wetty --port 3000 --command bash"
alias gotty-up="gotty -p 8080 bash"
alias ttyd-auth="ttyd -p 7681 --credential user:pass bash"

적용:

source ~/.zshrc

리버스 프록시 구성 팁

  • TLS와 인증은 Nginx/Caddy/Cloudflare 등에서 종단하는 것이 가장 단순합니다.
  • 백엔드로는 http://127.0.0.1:7681(ttyd) / :3000(Wetty) / :8080(GoTTY)을 프록시합니다.
  • WebSocket 업그레이드 헤더(Upgrade, Connection)를 꼭 전달해야 합니다.

선택 가이드

  • 가볍고 빠른 단일 바이너리: ttyd 권장.
  • JS 생태계 친화/커스터마이즈: Wetty 권장.
  • 레거시/간단 데모: GoTTY 가능(최신 환경 빌드 이슈 감안).

참고 링크(인용)