
# 아키텍처

## 전체 흐름

기본값(로컬 tmux + 터널):

```
Browser (phone)
  |
  | HTTPS
  v
Cloudflare Quick Tunnel
  |
  | HTTP/WS
  v
Local Termbridge server
  |
  | PTY
  v
Tmux session
```

직접 샌드박스 모드(Daytona, 터널 없음):

```
Browser (phone)
  |
  | HTTPS
  v
Daytona preview link
  |
  | HTTP/WS
  v
Termbridge server (sandbox)
  |
  | PTY
  v
Tmux session (sandbox)
```

`--no-tunnel`이 설정되면 Termbridge은 Cloudflare을 건너뛰고 제공된 공개 URL를 사용합니다.

## 컴포넌트

### CLI 프로세스

- UI 에셋을 제공하는 HTTP 서버를 시작합니다.
- 터미널 I/O용 WebSocket 서버를 시작합니다.
- 하나 이상의 tmux 세션(또는 Daytona PTY)을 생성합니다.
- 일회용 교환 토큰을 발급합니다.
- 터널이 활성화된 경우 터널을 시작하고 모니터링합니다(현재 Cloudflare).
- 직접 샌드박스 모드에서는 샌드박스 안에서 Termbridge을 실행하고 공유 URL을 기다립니다.

### 터미널 백엔드

- **tmux 백엔드**: 실제 키 입력과 출력을 위해 `node-pty`을 사용해 tmux에 연결합니다.
- **Daytona 백엔드**: 샌드박스 안에서 Daytona PTY를 사용합니다.
- 전체 색상 지원을 위해 `TERM=xterm-256color` 및 `COLORTERM=truecolor`을 설정합니다.
- tmux의 경우 UI을 깔끔하게 유지하도록 tmux 상태 표시줄을 비활성화합니다.

### 터미널 레지스트리

- 사용 가능한 터미널 세션을 추적합니다.
- UI에 목록을 제공하고 선택한 터미널 ID를 확인합니다.

### 인증 및 세션

- 일회용 토큰은 URL으로 출력되고 QR 코드에 인코딩됩니다.
- `GET /__tb/s/:token`가 토큰을 교환하고 쿠키 세션을 설정합니다.
- WebSocket 연결에는 유효한 세션 쿠키와 CSRF 토큰이 필요합니다.
- CSRF 토큰은 `GET /__tb/api/csrf`을 통해 가져와 WebSocket 쿼리 매개변수로 전달됩니다.

### 프록시 모드

`--proxy <port>`이 전달되면:
- 모든 termbridge 경로는 `/__tb/` 접두사 아래에 있습니다.
- `/__tb/`가 아닌 요청은 대상 앱으로 프록시됩니다.
- UI는 뷰 전환기를 통해 터미널/미리보기 뷰를 표시합니다.
- 미리보기 뷰는 `/`를 가리키는 iframe을 불러옵니다.
- HMR용 WebSocket 연결은 대상에 전달됩니다.

### 보안

- **CSRF 보호**: 사이트 간 탈취를 방지하기 위해 WebSocket 업그레이드에 CSRF 토큰이 필요합니다.
- **입력 제한**: 64KB HTTP 본문, WebSocket 메시지 1MB, 메시지당 터미널 입력 64KB입니다.
- **요청 제한**: 토큰 교환과 WebSocket 연결에 IP별 제한을 적용합니다.

## API 엔드포인트

프록시된 앱과의 충돌을 피하기 위해 모든 경로는 `/__tb/` 접두사 아래에 있습니다:

- `GET /__tb/healthz` - 상태 확인
- `GET /__tb/s/:token` - 토큰 교환 → 쿠키 → 리디렉션
- `GET /__tb/api/terminals` - 터미널 목록
- `GET /__tb/api/csrf` - WebSocket용 CSRF 토큰 가져오기
- `GET /__tb/api/config` - 설정 가져오기(proxyPort, devProxyUrl)
- `POST /__tb/api/terminals` - 새 tmux 세션 생성
- `GET /__tb/app/*` - SPA 대체 경로
- `WS /__tb/ws/terminal/:terminalId?csrf=<token>` - 터미널 I/O 스트리밍

프록시 모드가 활성화된 경우:
- `GET /` - 프록시된 앱으로 리디렉션(비활성화된 경우 `/__tb/app`)
- `* /*` - 대상 앱으로 프록시됨

## WebSocket 프로토콜

클라이언트 -> 서버:

```json
{ "type": "input", "data": "ls -la" }
{ "type": "resize", "cols": 120, "rows": 32 }
{ "type": "control", "key": "ctrl_c" }
```

서버 -> 클라이언트:

```json
{ "type": "output", "data": "..." }
{ "type": "status", "state": "connected" }
```

## UI 스택

- Vite + TanStack Router
- xterm.js + Fit 애드온 + WebGL 렌더러
- 입력 바를 고정한 모바일 우선 레이아웃
- 지수형 백오프로 자동 재연결(최대 10회 재시도)
- 연결 상태 표시기
