ROS2:Basic:CloudflareArchitecture
ROS2 통신의 Cloudflare Workers / Durable Objects 대체 가능성 분석
ROS2에서 일반 HTTP 요청으로 토픽/서비스를 위한 서버 역할을 Cloudflare Workers 또는 Durable Objects에서 대체할 수 있는지에 대한 분석.
ROS2 통신 모델 vs Cloudflare 런타임 비교
ROS2 통신 특성
| 패턴 | 특성 | 주기 | 예시 |
| Topic (Pub/Sub) | 단방향 스트림, 고빈도 | 10~1000Hz | |
| Service (Req/Res) | 동기 요청/응답 | 비정기 | |
| Action (Long-running) | 비동기, 피드백 스트림 | 수초~수분 | |
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와 동일한 패턴.
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별 실시간 세션 허브 역할을 하는 것이 가장 자연스러운 설계.