OpenClaw 게이트웨이 아키텍처: WebSocket 연결 및 구성 가이드
여러 메시징 플랫폼을 하나의 인터페이스로 통합하려고 할 때, 각 서비스의 API와 연결 상태를 관리하는 건 정말 까다로운 일이에요. 특히 여러 기기에서 동시에 안정적으로 작동하게 만드는 건 더 어렵죠.
이런 복잡한 문제를 해결하기 위해 설계된 Gateway 아키텍처에 대해 자세히 알아볼게요. 시스템이 어떻게 구성되고 통신하는지 이해하면 더 효율적인 개발이 가능할 거예요.
- 하나의 실행 시간이 긴(long-lived) Gateway가 모든 메시징 서비스(Baileys를 통한 WhatsApp, grammY를 통한 Telegram, Slack, Discord, Signal, iMessage, WebChat)를 소유해요.
- 제어 평면(Control-plane) 클라이언트(macOS 앱, CLI, 웹 UI, 자동화 도구)는 설정된 호스트(기본값
127.0.0.1:18789)의 WebSocket을 통해 Gateway에 연결돼요. - Nodes(macOS/iOS/Android/headless)도 WebSocket으로 연결되지만, 명시적인 기능과 명령을 가진
role: node를 선언해요. - 호스트당 하나의 Gateway만 존재하며, WhatsApp 세션을 여는 유일한 장소예요.
- canvas host는 Gateway HTTP 서버의 다음 경로에서 제공돼요.
/__openclaw__/canvas/(에이전트가 수정 가능한 HTML/CSS/JS)/__openclaw__/a2ui/(A2UI 호스트) Gateway와 동일한 포트(기본값18789)를 사용해요.
구성 요소 및 흐름
섹션 제목: “구성 요소 및 흐름”Gateway (daemon)
섹션 제목: “Gateway (daemon)”- 프로바이더 연결을 유지해요.
- 타입이 지정된 WS API(요청, 응답, 서버 푸시 이벤트)를 노출해요.
- 유입되는 프레임을 JSON Schema에 따라 검증해요.
agent,chat,presence,health,heartbeat,cron과 같은 이벤트를 발생시켜요.
Clients (mac app / CLI / web admin)
섹션 제목: “Clients (mac app / CLI / web admin)”- 클라이언트당 하나의 WS 연결을 가져요.
- 요청(
health,status,send,agent,system-presence)을 보내요. - 이벤트(
tick,agent,presence,shutdown)를 구독해요.
Nodes (macOS / iOS / Android / headless)
섹션 제목: “Nodes (macOS / iOS / Android / headless)”role: node를 가지고 동일한 WS 서버에 연결돼요.connect시 기기 아이덴티티를 제공하며, 페어링은 기기 기반(node역할)으로 이루어지고 승인 정보는 기기 페어링 저장소에 보관돼요.canvas.*,camera.*,screen.record,location.get과 같은 명령을 노출해요.
프로토콜 상세 내용:
WebChat
섹션 제목: “WebChat”- 채팅 기록 확인 및 전송을 위해 Gateway WS API를 사용하는 정적 UI예요.
- 원격 설정에서는 다른 클라이언트와 마찬가지로 동일한 SSH/Tailscale 터널을 통해 연결돼요.
연결 라이프사이클 (단일 클라이언트)
섹션 제목: “연결 라이프사이클 (단일 클라이언트)”sequenceDiagram participant Client participant Gateway
Client->>Gateway: req:connect Gateway-->>Client: res (ok) Note right of Gateway: or res error + close Note left of Client: payload=hello-ok<br>snapshot: presence + health
Gateway-->>Client: event:presence Gateway-->>Client: event:tick
Client->>Gateway: req:agent Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"} Gateway-->>Client: event:agent<br>(streaming) Gateway-->>Client: res:agent<br>final {runId, status, summary}통신 프로토콜 (요약)
섹션 제목: “통신 프로토콜 (요약)”- 전송 계층: WebSocket, JSON 페이로드를 가진 텍스트 프레임.
- 첫 번째 프레임은 반드시
connect여야 해요. - 핸드셰이크 이후:
- 요청:
{type:"req", id, method, params}→{type:"res", id, ok, payload|error} - 이벤트:
{type:"event", event, payload, seq?, stateVersion?}
- 요청:
OPENCLAW_GATEWAY_TOKEN(또는--token)이 설정된 경우,connect.params.auth.token이 일치해야 하며 그렇지 않으면 소켓이 닫혀요.- 사이드 이펙트가 있는 메서드(
send,agent)의 안전한 재시도를 위해 Idempotency key가 필요해요. 서버는 단기 중복 제거 캐시를 유지해요. - Node는
connect시role: "node"와 함께 기능/명령/권한을 포함해야 해요.
페어링 및 로컬 신뢰
섹션 제목: “페어링 및 로컬 신뢰”- 모든 WS 클라이언트(운영자 및 노드)는
connect시 기기 아이덴티티를 포함해요. - 새로운 기기 ID는 페어링 승인이 필요하며, Gateway는 이후 연결을 위해 기기 토큰을 발급해요.
- 로컬 연결(loopback 또는 Gateway 호스트 자체의 tailnet 주소)은 매끄러운 사용자 경험을 위해 자동 승인될 수 있어요.
- 모든 연결은
connect.challenge논스(nonce)에 서명해야 해요. - 서명 페이로드
v3는platform과deviceFamily를 결합해요. Gateway는 재연결 시 페어링된 메타데이터를 고정하며, 메타데이터가 변경되면 페어링 수정을 요구해요. - 비로컬 연결은 여전히 명시적인 승인이 필요해요.
- Gateway 인증(
gateway.auth.*)은 로컬이나 원격에 상관없이 모든 연결에 적용돼요.
상세 내용: Gateway protocol, Pairing, Security.
프로토콜 타이핑 및 코드 생성
섹션 제목: “프로토콜 타이핑 및 코드 생성”- TypeBox 스키마가 프로토콜을 정의해요.
- 해당 스키마에서 JSON Schema가 생성돼요.
- JSON Schema에서 Swift 모델이 생성돼요.
원격 접속
섹션 제목: “원격 접속”-
권장 방법: Tailscale 또는 VPN.
-
대안: SSH 터널
Terminal window ssh -N -L 18789:127.0.0.1:18789 user@host -
터널을 통해서도 동일한 핸드셰이크와 인증 토큰이 적용돼요.
-
원격 설정의 WS를 위해 TLS와 선택적 핀닝(pinning)을 활성화할 수 있어요.
운영 스냅샷
섹션 제목: “운영 스냅샷”- 시작:
openclaw gateway(포그라운드 실행, stdout으로 로그 출력). - 상태 확인: WS를 통한
health(또한hello-ok에 포함됨). - 관리: 자동 재시작을 위해 launchd/systemd 사용.
불변 조건
섹션 제목: “불변 조건”- 정확히 하나의 Gateway가 호스트당 단일 Baileys 세션을 제어해요.
- 핸드셰이크는 필수예요. JSON이 아니거나 첫 프레임이
connect가 아니면 즉시 연결이 종료돼요. - 이벤트는 다시 재생되지 않아요. 클라이언트는 공백이 생기면 데이터를 새로고침해야 해요.
관련 문서
섹션 제목: “관련 문서”- Agent Loop — 상세한 에이전트 실행 주기
- Gateway Protocol — WebSocket 프로토콜 규약
- Queue — 명령 큐 및 동시성
- Security — 신뢰 모델 및 보안 강화
궁금한 점이 있거나 설정 중에 도움이 필요하면 언제든 물어보세요!
OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.