Skip to content

ROS2:Basic:CloudflareArchitecture

ROS2 통신의 Cloudflare Workers / Durable Objects 대체 가능성 분석

ROS2에서 일반 HTTP 요청으로 토픽/서비스를 위한 서버 역할을 Cloudflare Workers 또는 Durable Objects에서 대체할 수 있는지에 대한 분석.

ROS2 통신 모델 vs Cloudflare 런타임 비교

ROS2 통신 특성

패턴

특성

주기

예시

Topic (Pub/Sub)

단방향 스트림, 고빈도

10~1000Hz

/joint_states, /camera/image

Service (Req/Res)

동기 요청/응답

비정기

/robot/enable, /get_state

Action (Long-running)

비동기, 피드백 스트림

수초~수분

MoveToPoint, FollowTrajectory

Cloudflare 런타임 특성

런타임

상태

연결

CPU 제한

적합한 용도

Workers

Stateless

HTTP only

30s (free) / 15min (paid)

단발성 API 요청

Durable Objects

Stateful

HTTP + WebSocket

제한 없음 (idle시 hibernation)

실시간 세션, 상태 관리

패턴별 대체 가능 여부

1. ROS2 Service → Workers (대체 가능)

ROS2 Service는 본질적으로 Request/Response이므로 HTTP API와 동일한 패턴.

[Web UI] → POST /api/agents/:id/commands → [Worker] → [Edge Agent] → [ROS2 Service Call]
                                                        ← 결과 반환 ←

Workers로 충분. 단, Workers가 직접 ROS2를 호출하는 것이 아니라, Edge Agent가 중계.

2. ROS2 Topic (고빈도) → Durable Objects (조건부 가능)

[ROS2 Topic 100Hz] → [Edge Agent에서 다운샘플링 1~10Hz]
                      → WebSocket → [Durable Object] → WebSocket → [Web UI]

가능한 이유:

  • Durable Objects는 WebSocket을 지원하고 상태를 유지함
  • WebSocket Hibernation API로 유휴 시 비용 절감 가능

제약사항:

  • Edge Agent에서 반드시 다운샘플링 필요 (100Hz를 그대로 보내면 비용 폭발)
  • Durable Objects 간 통신은 비효율적 — 1 Agent = 1 Durable Object로 매핑
  • 바이너리 데이터(카메라 이미지)는 부적합 — 대역폭/비용 문제

3. ROS2 Action (장시간 작업) → Durable Objects (적합)

[Web UI] → "Move to Point A" → [DO] → [Edge Agent] → [ROS2 Action]
[Web UI] ← 피드백 스트림 ←      [DO] ← progress 30% ← [Edge Agent]
[Web UI] ← 피드백 스트림 ←      [DO] ← progress 70% ← [Edge Agent]
[Web UI] ← 완료 ←              [DO] ← done ←          [Edge Agent]

Durable Objects가 가장 빛나는 패턴. 상태 유지 + WebSocket 양방향 통신.

권장 아키텍처

                    Cloudflare Edge
                    ┌─────────────────────────────────┐
                    │                                 │
[Web UI] ──HTTP──→  │  Worker (Hono)                  │  ← 명령, CRUD, 인증
                    │    │                            │
                    │    ├── Agent DO ────WebSocket──→ │ ──→ [Edge Agent]
                    │    │   (per agent)              │
                    │    │   - 연결 상태 관리          │
                    │    │   - 텔레메트리 릴레이       │
                    │    │   - 명령 큐잉/추적          │
                    │    │                            │
[Web UI] ←─WSS───  │    └── 브라우저에 WebSocket 제공 │
                    │                                 │
                    └─────────────────────────────────┘

핵심 설계: Durable Object 코드 예시

// Durable Object: Agent 1개당 1개 인스턴스
export class AgentSession extends DurableObject {
  // Edge Agent WebSocket (1개)
  private agentSocket: WebSocket | null = null;
  // 브라우저 WebSocket (N개 - 대시보드 보는 사용자들)
  private viewers: Set<WebSocket> = new Set();

  async fetch(request: Request) {
    const url = new URL(request.url);

    if (url.pathname === '/connect-agent') {
      // Edge Agent가 연결
      const [client, server] = Object.values(new WebSocketPair());
      this.agentSocket = server;
      server.accept();
      server.addEventListener('message', (e) => {
        // 텔레메트리를 모든 viewer에 브로드캐스트
        for (const viewer of this.viewers) {
          viewer.send(e.data);
        }
        // 필요시 storage에 저장
      });
      return new Response(null, { status: 101, webSocket: client });
    }

    if (url.pathname === '/connect-viewer') {
      // 브라우저 대시보드가 연결
      const [client, server] = Object.values(new WebSocketPair());
      this.viewers.add(server);
      server.accept();
      server.addEventListener('message', (e) => {
        // 브라우저→Agent 명령 전달
        this.agentSocket?.send(e.data);
      });
      server.addEventListener('close', () => this.viewers.delete(server));
      return new Response(null, { status: 101, webSocket: client });
    }

    // REST: 명령 전송, 상태 조회 등
    if (url.pathname === '/command') {
      const cmd = await request.json();
      this.agentSocket?.send(JSON.stringify(cmd));
      // 명령 추적을 위해 storage에 저장
      await this.ctx.storage.put(`cmd:${cmd.id}`, cmd);
      return Response.json({ status: 'sent' });
    }
  }
}

대체 불가능한 영역 (Edge Agent 필수)

기능

이유

ROS2 DDS 직접 통신

DDS는 UDP 멀티캐스트 — HTTP/WebSocket 불가

실시간 제어 루프

<10ms 레이턴시 필요 — 클라우드 왕복 불가

E-Stop 안전 기능

네트워크 단절 시에도 동작해야 함

카메라 프레임 처리

대역폭/레이턴시 — Edge에서 처리 후 결과만 전송

다운샘플링/필터링

고빈도 토픽을 클라우드 전송 가능한 수준으로 축소

결론

역할

Workers

Durable Objects

Edge Agent

Agent CRUD, 인증

O

-

-

명령 전달 (Service 대체)

O

O (큐잉)

중계

텔레메트리 릴레이 (Topic 대체)

X

O (WebSocket)

다운샘플링 필수

Action 추적 (피드백)

X

O

중계

ROS2 DDS 직접 통신

X

X

필수

안전 기능 (E-Stop)

X

X

필수

Workers + Durable Objects는 "클라우드 측 서버"로서 충분히 대체 가능하지만, Edge Agent는 ROS2 브릿지 + 안전 기능 + 데이터 전처리를 위해 반드시 필요하다. Durable Objects가 Agent별 실시간 세션 허브 역할을 하는 것이 가장 자연스러운 설계.

See also