본문으로 건너뛰기
5분 AI.
GITHUB TRENDING RUST MONTHLY #4 딥다이브 · 2026-10-23 분석

cua 딥다이브
— AI에게 컴퓨터를 빌려주고, 행동의 결과를 확인하는 법

SDK·실행 인프라

빠른 판단

무엇
에이전트용 데스크탑 환경·관찰·입력·앱 자동화·결과 평가를 연결하는 컴퓨터 사용 인프라 모음
이럴 때
AI가 분리된 컴퓨터의 앱을 조작하고 결과를 검증하도록 드라이버·샌드박스·평가 환경을 구성할 때
AI가 브라우저를 넘어 데스크톱 앱까지 다루려면 무엇이 필요할까요? cua는 컴퓨터를 준비하는 샌드박스, 화면과 앱을 조작하는 드라이버, 결과를 평가하는 도구를 함께 담은 모노레포입니다. Rust의 인터페이스 설계부터 Python 평가 루프, TypeScript와 SwiftUI 화면까지 연결해 읽습니다. ⭐30,747 · 포크 2,235 · 주 언어 Rust · 2026-10-23 GitHub 기준. 코드 설명은 커밋 cdda707 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

모델이 생각하고, cua가 컴퓨터와 조작 수단을 제공합니다

cua는 AI 에이전트가 쓸 컴퓨터를 만들고 연결하며, 그 안의 앱을 관찰·조작하고 평가하도록 돕는 도구 모음입니다. 이름의 CUA는 Computer Use Agent를 뜻합니다. 여기서 컴퓨터 사용은 “텍스트를 답한다”를 넘어 창을 찾고, 버튼을 누르고, 파일을 저장하는 행동입니다.

예를 들어 “계산기에서 6 × 7을 계산해 줘”라는 요청을 생각해 보세요. 언어 모델은 다음 행동을 정하지만 계산기 창의 실제 위치는 모릅니다. 드라이버는 창과 접근성 정보를 읽고 입력을 전달합니다. 마지막에는 화면이나 앱 상태에서 42를 확인해야 합니다. 요청이 접수되었다는 응답만으로 계산 성공을 선언할 수는 없습니다.

이 저장소에서 배울 핵심은 AI의 판단과 컴퓨터의 실행, 실행 결과의 검증을 서로 다른 책임으로 나누는 방법입니다.

비유로 시작하기

로봇 직원에게 사무실을 마련해 준다면

모델은 무엇을 할지 결정하는 직원, 샌드박스는 그 직원 전용 사무실입니다. Cua Driver는 눈과 손에 해당합니다. Cua Spaces는 사람이 사무실을 보고 함께 일하는 관리 화면입니다.

Cua Bench는 업무가 끝났는지 채점하는 시험관입니다. 사무실이 잘 열려도 손이 고장 날 수 있고, 손이 움직여도 업무는 틀릴 수 있습니다. 각 부분을 따로 관찰해야 문제를 고칠 수 있습니다.

구성요소주된 책임소스의 입구
Cua SDK / CLI샌드박스 생성·연결·수명 관리. 하나의 Rust 코어를 여러 언어와 명령으로 공개libs/cua/
Cua DriverOS별 창 탐색, 접근성 트리, 화면 캡처, 포인터·키보드 조작libs/cua-driver/rust/
cua-spacesd대상 컴퓨터 내부에서 프로세스·파일·화면·드라이버 기능을 원격으로 제공libs/cua-spacesd/
Spaces / LumeSpaces는 사용자 앱, Lume는 Apple Silicon에서 macOS·Linux VM을 관리하는 도구apps/, libs/lume/
Bench / S1Bench는 과제·평가·궤적 수집, S1은 작고 특화된 컴퓨터 사용 모델 연구libs/cua-bench/, libs/cua-s1/
용어 먼저
에이전트 · 샌드박스 · 드라이버
에이전트는 목표를 위해 도구를 반복 호출하는 프로그램입니다. 샌드박스는 작업을 분리해 실행하는 환경이며 VM이나 컨테이너가 될 수 있습니다. 드라이버는 상위 명령을 OS가 이해하는 관찰·입력 작업으로 바꿉니다. 세 단어는 서로 다른 역할을 가리킵니다.

처음 읽을 때 범위를 좁히는 법

이 글은 libs/cua의 수명 관리와 cua-driver-core의 대상 검증을 중심으로 읽습니다. Teleport, 메시 네트워크, 모델 학습은 연결 지점까지 다룹니다. 거대한 저장소를 처음부터 모두 이해하려 하기보다 “컴퓨터를 만들고 → 현재 상태를 읽고 → 한 번 행동하고 → 결과를 확인한다”는 한 흐름을 따라가면 됩니다.

학습의 첫 목표
모델 API 키 없이도 설계는 공부할 수 있습니다

파일 읽기, 인터페이스 비교, 토큰 형식 분석, 상태 전이 표 작성에는 모델 호출이나 VM 실행이 필요하지 않습니다. 실제 데스크톱 조작과 비용이 드는 모델 실험은 구조를 이해한 다음 단계로 두세요.

2왜 주목받는가

브라우저 자동화에서 컴퓨터 전체의 실행 환경으로

2-1. 화제의 배경과 확인 가능한 근거

2026-10-23 기준 GitHub Trending Rust Monthly 4위이며, 스타는 30,747개입니다. 다만 순위와 스타만으로 사용량이나 안정성을 증명할 수는 없습니다. 주목받는 이유는 다음 기능 조합에서 추론할 수 있습니다. 이는 코드와 공개 설명을 바탕으로 한 해석이며, 유입 경로를 측정한 결과는 아닙니다.

cua의 매력은 클릭 명령의 개수보다, 실행 환경을 준비하는 단계부터 결과를 증명하는 단계까지 연결한다는 데 있습니다.

2-2. 경쟁·인접 도구와 비교하기

다음은 기능의 중심을 비교한 표입니다. 성능 순위표가 아니며, 이 표에는 같은 과제로 측정한 속도·정확도 수치를 담지 않았습니다. 브라우저만 다루는 일이면 전용 도구가 더 간단할 수 있습니다.

도구중심 문제cua를 배울 때 드러나는 차이
PlaywrightChromium·WebKit·Firefox 기반 웹 앱 E2E 테스트. 실행기·검증·격리 제공cua는 네이티브 앱과 VM·컨테이너 수명도 다룹니다. 웹 앱의 결정적 테스트에는 Playwright가 직접적인 선택입니다.
Browser UseAI의 브라우저 작업과 브라우저 인프라. 로컬 공개 라이브러리와 클라우드 경로cua는 OS 창·접근성·입력과 전체 데스크톱을 연결합니다. 모델이 행동을 정한다는 점은 겹치지만 제어 범위가 다릅니다.
Lume 단독 사용Apple Virtualization.Framework 기반 로컬 VM 관리같은 저장소의 기반 도구입니다. cua SDK와 Spaces가 그 위에 연결·파일·조작·사용자 화면을 더합니다.
OS별 입력 API 직접 사용특정 OS에서 클릭·키 입력을 직접 구현cua의 공통 계층은 대상·좌표·세션·거절 응답을 정리합니다. 대신 추상화와 플랫폼별 제약을 함께 이해해야 합니다.

비교 근거: Playwright 공식 소개, Browser Use 공식 시작 안내, cua의 플랫폼 지원표. 각 프로젝트의 범위에 관한 비교이며 “더 빠르다”거나 “더 정확하다”는 주장을 하지 않습니다.

2-3. 최신 커밋이 알려 주는 좋은 개발 습관

커밋 cdda707의 제목은 Browser Use CLI 비교 경로를 버전 고정과 문제가 있으면 중단하는 사전 점검으로 준비했다는 뜻입니다. 여기서 비교 경로는 같은 과제를 서로 다른 도구로 수행하는 실험의 한 갈래입니다.

libs/cua-driver-bench/automated-eval/macos_bench/pins.json은 Browser Use를 0.13.11, Python을 3.12로 지정하고 wheel 파일과 스킬의 SHA-256을 기록합니다. 반면 같은 폴더의 libs/cua-driver-bench/automated-eval/macos_bench/browser_use_cli.py에서 preflight()는 다음처럼 동작합니다.

# browser_use_cli.py의 동작을 한국어로 풀어 쓴 축약 예시
def preflight():
    return [(ARM, "fail", "운영 사전 점검이 아직 구현되지 않음")]

즉, 준비된 코드가 있다는 사실과 실행 가능한 지원이 완료되었다는 사실은 다릅니다. 이 시점의 비교 경로는 점검을 통과할 수 없습니다. 초보자는 함수의 이름만 읽지 말고 반환값과 호출자의 중단 조건까지 확인하는 습관을 배울 수 있습니다.

실험실의 문

새 실험 장치를 들여놓았다고 안전 점검표를 자동으로 “통과”로 바꾸면 안 됩니다. 이 코드의 사전 점검은 아직 준비되지 않은 장치를 작동시키지 않도록 문을 잠가 둔 상태입니다. 이를 fail-closed, 즉 확인이 안 되면 진행하지 않는 설계라고 합니다.

2-4. 소개 문구와 현재 소스를 구분하기

읽은 내용커밋 cdda707의 확인 결과
최신 릴리스2026-10-23 GitHub 기준 cua-spaces-v0.13.1. README의 수동 다운로드 링크는 여전히 0.9.4를 가리킵니다.
VM 없는 Bench 실습루트 README는 모의 과제를 소개하지만 libs/cua-bench/pyproject.toml은 simulated Playwright provider를 0.3에서 삭제했다고 명시합니다. browser = []도 빈 호환용 옵션입니다.
호스팅 위치libs/cua/crates/cua-sandbox-core/src/lib.rs의 CLOUD_ENDED는 이전 Cua Cloud 경로의 종료를 알립니다. 현재 로컬·직접 연결·자기 클라우드 계정 경로와 구별해야 합니다.
전체가 MIT인가루트는 MIT지만 Spaces 계열에 FSL 코드가 있습니다. 특히 README는 미디어 전송 프로토콜을 MIT라고 적지만 해당 crate와 라이선스 안내는 FSL로 표시합니다.

3기술 스택 전체 지도

의존성 선언의 버전과 실제 설치 버전을 구별하며 읽기
버전 표기 읽는 법
버전 범위 · 정확한 고정 · 잠금 파일
^19.1.0은 호환 범위, Python의 >=3.12,<3.14는 허용 구간입니다. Cargo의 version = "1"도 정확히 1.0.0이라는 뜻은 아닙니다. =0.31.0처럼 정확히 고정한 경우와 구별하세요. 아래 표는 의존성 파일에 선언된 값을 그대로 적습니다. 실제 해석 결과는 각 잠금 파일이 맡습니다.

3-1. 백엔드와 시스템 계층

영역실제 선언역할 · 근거 파일
SDK Rust버전 0.7.0, edition 2024, rust-version 1.97libs/cua/Cargo.toml. 이미지·런타임·샌드박스·daemon·언어 바인딩의 중심
비동기 실행tokio = "1", 기능 full같은 workspace. 네트워크·대기·여러 작업의 동시 진행
RPC / 계약tonic = "0.14", prost = "0.14", tonic-web = "0.14"같은 workspace. Protobuf 메시지와 gRPC·gRPC-Web 통신
HTTP / CLIaxum = "0.8", tower = "0.5", clap = "4"같은 workspace. daemon 라우팅, 요청 처리, 명령 인자 해석
언어 경계uniffi = "=0.31.0", rmcp = "=3.4.1"같은 workspace. 외부 언어 바인딩과 MCP 연결. 두 버전은 정확한 고정
미디어 전송quinn = "0.11.11", rustls = "0.23.42"같은 workspace의 선언. QUIC 연결과 TLS 기반 보안 통신
Driver Rustworkspace 0.38.0, edition 2021, image = "0.25"libs/cua-driver/rust/Cargo.toml. SDK와 별개 workspace이며 버전도 독립
선택적 인식ort = "=2.0.0-rc.10"Driver workspace. 동적 ONNX Runtime 로딩 경로. 기본 제어와 모델 확장을 구별
LumeSwift tools 6.0, ArgumentParser from: "1.3.1", SwiftNIO from: "2.81.0"libs/lume/Package.swift. Apple 가상화 API와 VM·SSH·서버 기능 연결
Modal 보조 도구Go 1.25.0, toolchain go1.26.10, modal-client v0.11.0libs/cua/crates/cua-contrib/modal-helper/go.mod. 일부 클라우드 연동용이며 주 백엔드가 Go인 것은 아님

3-2. Python은 SDK 사용과 평가·연구를 연결합니다

패키지버전·Python 범위의존성에서 읽는 설계
cua0.7.0, >=3.10libs/cua/python/pyproject.toml의 기본 dependencies는 빈 배열. wheel에는 Rust 네이티브 라이브러리와 CLI 바이너리가 포함됩니다.
cua-bench0.3.1, >=3.12,<3.14aiohttp>=3.9.0, rich>=14.2.0, datasets>=3.0.0, cua-sandbox>=0.8.0,<0.10.0 이 선언이 네트워크·표시·데이터셋·실행 환경의 역할을 나눕니다.
cua-s10.0.0, >=3.11,<3.14numpy>=1.26, safetensors>=0.4,<1, torch>=2.2,<3. 모델 가중치는 패키지에 포함하거나 자동 다운로드하지 않는다고 명시합니다.
루트 개발 환경cua-workspace 0.1.0, >=3.12,<3.14루트 pyproject.toml에는 openai>=2.20.0,<3.0.0, anthropic>=0.67.0. 이 범위를 모든 하위 패키지의 최소 요구사항으로 일반화하면 안 됩니다.

Python SDK의 “기본 의존성이 없다”는 말은 순수 Python 구현이라는 뜻이 아닙니다. 배포되는 네이티브 라이브러리가 실제 기능을 수행할 수 있습니다. 패키지 관리자 의존성과 운영체제 바이너리 의존성은 다른 목록입니다.

3-3. 프론트엔드는 한 종류가 아닙니다

화면·셸실제 버전 선언구조에서 볼 점
Tauri 앱앱 0.13.1, React ^19.1.0, TypeScript ^5.8.3, Vite ^6.3.5, Tauri API ^2.5.0apps/cua-spaces/package.json. Rust 셸의 apps/cua-spaces/src-tauri/Cargo.toml도 Tauri 2를 선언
공유 웹 화면React ^19.3.0, TypeScript ^7.0.2, Vite ^8.3.2, Zustand ^5.0.15, Tailwind ^4.3.3apps/cua-spaces-web/package.json. 호스트 연결을 브리지 뒤에 숨기고 상태·라우팅·컴포넌트를 구성
Electron 셸앱 0.13.1, Electron 44.9.1, electron-builder 26.15.3, pnpm 11.20.0apps/cua-spaces-desktop/package.json. 웹 화면을 네이티브 기능과 연결하고 데스크톱 앱으로 포장
macOS 네이티브Swift tools 6.2, macOS 26, Sparkle 2.10.0 정확한 고정apps/cua-spaces-macos/Package.swift. SwiftUI 셸, Rust 앱 코어, 업데이트 기능
TypeScript SDK@trycua/cua 0.7.0, @ubjs/core 0.31.0-3, @ubjs/node 0.31.0-3libs/cua/typescript/package.json. 화면용 React 패키지와 달리 Rust API의 언어 바인딩

같은 이름의 Spaces라도 빌드 대상이 다릅니다. React 버전 하나를 찾아 “프론트엔드는 React 19.1”로 끝내면 다른 앱의 의존성을 놓칩니다. 폴더별 manifest가 버전 판단의 단위입니다.

3-4. 인프라·빌드·CI

초보자를 위한 읽기 순서

처음에는 Rust·React·Swift·Python을 모두 설치할 필요가 없습니다. 관심 있는 기능의 manifest 한 개, 인터페이스 한 개, 구현 한 개, 해당 CI 한 개를 묶어 읽으세요. 이 네 파일을 연결하는 것이 전체 의존성 이름을 외우는 것보다 유익합니다.

4아키텍처 심화 분석

한 번의 작업을 따라가며 네 가지 설계 패턴을 읽습니다

4-1. 시스템 전체 구조

사람 / 에이전트 / 자체 평가 하네스 | +-- CLI · MCP · Python · TypeScript · Rust | | | cua SDK (libs/cua) | | | +-----------+-----------+ | | | | embedded 모드 cua daemon 모드 | 같은 프로세스 호스트의 공유 서비스 | +-----------+-----------+ | | | cua-sandbox-core | | | +-----------+----------------+ | | | | LocalRuntime 직접 연결 / 공급자 | | | | cua-vmm | | +-- Lume: macOS · Linux VM | | +-- QEMU: VM | | +-- 컨테이너 엔진: gVisor / runc | | +---------------+------------+ | | | 대상 컴퓨터 / 샌드박스 | | | [있을 때 연결] cua-spacesd | 3211 (기본): gRPC / gRPC-Web / MCP | 3212 (기본): QUIC 미디어 | | | cua-driver-core | | | platform-macos / windows / linux | | | OS 창 · 접근성 · 캡처 · 입력 | +-- Spaces 앱: 화면 · 연결 · 공동 작업 +-- Cua Bench: 과제 준비 → 실행 → 평가 → 정리

위 구조는 대표적인 연결 경로를 단순화한 것입니다. Cua Driver는 샌드박스 없이 현재 컴퓨터의 앱에도 사용할 수 있습니다. 반대로 샌드박스는 cua-spacesd 없이도 실행할 수 있습니다. 예를 들어 웹 서버 컨테이너가 준비되었는지는 해당 서비스의 HTTP 응답만 확인하면 됩니다.

cua daemon과 cua-spacesd는 별개입니다. 전자는 클라이언트 쪽에서 샌드박스 상태와 연결을 여러 프로세스가 공유하게 합니다. 후자는 대상 컴퓨터 안에서 파일·프로세스·화면 기능을 제공합니다. 둘을 하나로 읽으면 “내 PC의 프로세스”와 “게스트 안의 프로세스”를 혼동하게 됩니다.

샌드박스가 실행 중이라는 사실, 제어 서버에 연결된다는 사실, 앱의 작업이 성공했다는 사실은 각각 따로 확인해야 합니다.

4-2. 패턴 ① 포트와 어댑터: 실행 환경을 바꾸는 인터페이스

libs/cua/crates/cua-sandbox-core/src/runtime.rs의 LocalRuntime은 상위 계층이 로컬 실행 환경에 요구하는 계약입니다. 포트는 “무슨 기능을 요구하는가”, 어댑터는 “어느 제품으로 구현하는가”에 해당합니다.

// LocalRuntime에서 핵심 메서드만 발췌
#[async_trait]
pub trait LocalRuntime: Send + Sync {
    fn backend(&self) -> String;
    async fn start(&self, spec: &LocalStartSpec)
        -> RuntimeResult<LocalInstance>;
    async fn stop(&self, name: &str) -> RuntimeResult<()>;
    async fn delete(&self, name: &str) -> RuntimeResult<()>;
}

Send + Sync는 이 객체를 여러 비동기 작업·스레드 사이에서 다룰 수 있도록 요구하는 Rust 제약입니다. 모든 메서드가 모든 환경에서 가능한 것은 아닙니다. 예를 들어 기본 fork()와 checkpoint() 구현은 RuntimeError::Unsupported를 돌려줍니다. 지원하지 않는 기능을 조용히 흉내 내지 않습니다.

libs/cua/crates/cua-vmm/src/auto.rs의 select()와 doctor()는 이미지 종류, 호스트 OS·아키텍처, 실행기 가용성을 판단합니다. macOS 게스트는 지원되는 Mac의 Lume, Linux·Windows VM은 우선 QEMU, 컨테이너는 Docker API 엔진과 gVisor·runc 경로를 사용합니다. QEMU를 사용할 수 없고 Lume가 준비되어 있거나 준비 가능한 경우 Linux ARM64 VM은 Lume로 실행할 수 있습니다. 자동 선택은 이미지와 호스트의 제약을 없애는 기능이 아닙니다.

멀티탭의 소켓

샌드박스 관리자는 “시작·중지·삭제”라는 소켓 모양만 압니다. Lume와 QEMU 어댑터가 각 장치의 전기 규격으로 바꿉니다. 새 실행기를 넣을 때 상위 코드 전체를 고치지 않아도 되는 이유가 여기에 있습니다. 다만 스냅샷처럼 소켓마다 지원이 다른 기능은 명시적으로 확인해야 합니다.

생성은 시작 명령 하나가 아니라 작은 트랜잭션입니다

libs/cua/crates/cua-sandbox-core/src/sandbox.rs의 Sandboxes::create()를 따라가면 다음 순서가 보입니다.

  1. apply_placement()와 validate_sidecars()로 조합을 검증합니다.
  2. build_image()로 이미지를 준비하고 create_local() 또는 create_contrib()로 분기합니다. 직접 연결 대상은 여기서 만들지 않습니다.
  3. wait_ready()로 사용자가 지정한 probe를 확인합니다. 이미지 다운로드는 게스트 부팅에 쓸 준비 시간 예산과 구분합니다.
  4. declares_spacesd()가 참이면 추가로 wait_spacesd()를 호출합니다. 이미지가 서비스를 선언하고, env 서비스가 있으며, 시작 명령을 대체하지 않은 경우입니다. Health가 응답하는지 확인하므로 데스크톱의 준비 상태는 별도로 살펴야 합니다.
  5. 준비 실패 시 새로 만든 대상을 정리합니다. 기존에 같은 이름으로 있던 대상은 보존하며, keep_on_failure 같은 정책도 반영합니다.

create_cancellable()와 DiscardGuard::drop()는 요청이 취소되거나 future가 버려질 때도 생성 중 자원을 정리하는 경로를 둡니다. Rust의 Drop 안에서는 비동기 정리를 직접 기다릴 수 없어 현재 Tokio 런타임을 얻을 수 있을 때 정리 작업을 예약합니다. “스코프를 벗어났다”와 “원격 자원 삭제가 완료되었다”를 구별해야 하는 이유입니다.

출처: 생성·준비·취소 로직, 실행기 선택.

4-3. 패턴 ② 파사드와 브리지: 같은 기능에 여러 입구 만들기

libs/cua/crates/cua-sdk/src/native/cua.rs에는 Cua 객체 뒤의 두 실행 방식이 enum으로 표현됩니다. 파사드는 복잡한 내부 구조 앞에 일관된 입구를 세우는 패턴입니다.

// 소스의 내부 Backend 정의
#[derive(Clone)]
pub(crate) enum Backend {
    Embedded(Runtime),
    Daemon(DaemonClient),
}

Cua::embedded()는 같은 프로세스에 런타임을 만들고, Cua::connect()는 daemon 연결 객체를 만들며, 실제 연결은 첫 호출 때 확인합니다. Cua::auto()는 로컬 daemon의 가용성을 판단하는 기본 진입점입니다. 어떤 연결 오류든 무조건 숨기는 함수는 아닙니다. 앱 번들에 포함된 빌드와 맞지 않는 daemon 등에는 별도 오류 경로가 있습니다.

libs/cua/crates/cua-sdk/src/lib.rs는 이 workspace에서 UniFFI export를 모으는 공개 경계입니다. 오류를 CuaError로 정리하고, 외부 언어 호출이 사용하는 Tokio 런타임도 SDK가 소유합니다. Python 이용자가 Rust 실행기를 직접 준비할 필요를 줄이는 설계입니다.

화면 쪽에도 같은 아이디어가 있습니다. apps/cua-spaces-web/src/bridge/transport.ts의 HostTransport는 post()와 listen()을 요구합니다. webkitTransport()는 Swift 호스트의 메시지 핸들러를, electronTransport()는 Electron preload의 호출 채널을 사용합니다. 화면은 같은 요청·이벤트 형식을 다룰 수 있습니다.

언어를 넘는 경계
FFI와 RPC는 다른 이동입니다
FFI는 Python·Swift 같은 언어에서 네이티브 Rust 함수를 호출하는 경계입니다. RPC는 별도 프로세스나 다른 컴퓨터에 요청을 보내는 경계입니다. cua는 두 경계를 함께 사용합니다. 바인딩 생성이 네트워크 실패까지 없애 주지는 않습니다.

출처: SDK 진입점, 웹 화면의 호스트 브리지.

4-4. 패턴 ③ 버전 붙은 핸들: “그때 본 버튼”을 가리키기

화면을 읽은 뒤 창이 바뀌면 이전 좌표나 요소 번호가 다른 버튼을 가리킬 수 있습니다. libs/cua-driver/rust/crates/cua-driver-core/src/element_token.rs는 스냅샷 번호와 요소 인덱스를 결합한 토큰을 만듭니다.

// element_token.rs의 형식
pub fn token_for(snapshot_id: u32, element_index: usize) -> String {
    format!("{}:{element_index}", format_snapshot_id(snapshot_id))
}
// snapshot_id = 0x1234, element_index = 42
// 결과: s00001234:42

parse_token()은 이 형식을 해석합니다. libs/cua-driver/rust/crates/cua-driver-core/src/snapshot_store.rs의 SnapshotStore::resolve()는 실제 보관 중인 스냅샷과 연결하고, 토큰의 창이 명시한 window_id와 다르면 conflicting_element_target으로 거절합니다. 사라진 스냅샷에 대한 호출은 stale_element_token을 돌려 새 상태를 읽도록 유도합니다.

LRU_CAP_PER_PID = 8은 프로세스별 스냅샷 보관 상한입니다. 이 토큰은 로그인 비밀값이나 암호화된 인증서가 아닙니다. 관찰한 요소를 특정 스냅샷·창에 연결하는 참조입니다. 저장소에 토큰이 남아 있다는 사실만으로 앱의 현재 상태가 같다고 보장되지는 않습니다.

상태 관찰 └─ 스냅샷 s00001234 / 창 A / 요소 42 | s00001234:42로 행동 요청 | +-----------+----------------+ | | 스냅샷·창 일치 스냅샷 없음 / 창 불일치 | | 요소를 해석하고 진행 거절 → 상태 다시 읽기 | 앱의 실제 결과 확인

SnapshotStore::screenshot_context()도 중요한 경계입니다. 스크린샷 소유 세션과 배율, 창 크기를 함께 관리하고, 프레임이 없거나 다른 세션의 것이면 screenshot_context_missing을 반환할 수 있습니다. 숫자 두 개의 좌표에도 어느 창의 어떤 크기 이미지에서 나온 좌표인가라는 문맥이 필요합니다.

출처: 요소 토큰, 스냅샷 해석과 좌표 문맥.

4-5. 패턴 ④ 정책과 실행 분리: 확신할 수 없으면 거절하기

libs/cua-driver/rust/crates/cua-driver-core/src/background_input.rs의 decide_background_input()는 대상에 관한 사실을 받아 Execute 또는 Refuse 결정을 반환합니다. 이 함수는 정책을 계산하며, 그 자체가 입력을 보내는 함수는 아닙니다. 해당 파일의 사실 모델에는 macOS WindowServer·AX 특성이 반영되어 있으므로 세부 조건을 모든 OS에 그대로 일반화하면 안 됩니다.

정책이 묻는 것왜 필요한가
창이 존재하고 예상 PID의 소유인가닫힌 창 번호나 다른 앱에 입력하는 일을 막습니다.
요소가 요청한 창의 자손인가같은 프로세스의 다른 창을 조작하는 일을 막습니다.
이 입력 방식이 숨김·최소화 상태에서도 가능한가접근성 액션과 원시 포인터 입력의 보장이 다릅니다.
키 입력의 목적지가 하나로 정해지는가프로세스 단위 키 전달은 같은 PID의 여러 창 사이에서 모호할 수 있습니다.
검증 증거가 요청한 바로 그 창에서 왔는가TargetBoundVerification::accepts_evidence_from()은 정확한 창 ID 일치만 받아들입니다.

libs/cua-driver/rust/crates/cua-driver-core/src/tool.rs의 Tool trait와 ToolRegistry::register()·invoke()는 각 도구를 등록하고 공통 호출 경계를 형성합니다. trait의 has_independent_input_lane() 기본값은 false입니다. 호출자가 “독립 입력”이라고 주장하는 것만으로는 부족하며, 구현이 이를 보장해야 한다는 뜻입니다.

백그라운드 조작의 경계
모든 앱에 포커스 없이 입력할 수 있는 것은 아닙니다

Wayland의 가려진 창에 대한 원시 입력, Windows의 더 높은 무결성 수준 앱, macOS의 일부 숨겨진 창 경로에는 제약이 있습니다. 구조화된 거절을 만나면 지원표와 대상 상태를 확인해야 합니다. 조용히 전경 입력으로 바꾸면 사용자의 현재 작업을 건드릴 수 있습니다.

출처: 백그라운드 입력 정책, 도구 계약과 등록소.

4-6. 평가 루프에서 같은 원칙 확인하기

libs/cua-bench/cua_bench/runners.py의 run_single_task()는 에이전트의 행동 뒤에 평가기를 호출합니다. 평가기가 없거나 보상이 숫자가 아니거나, 유한한 [0, 1] 범위를 벗어나면 오류로 처리합니다. 성공 기준은 이 함수에서 reward >= 0.5로 설정되어 있습니다. 모든 벤치마크에 통용되는 자연법칙이 아니라 이 실행기의 정책입니다.

finally에서 환경을 닫다가 실패하면 기존 성공도 실패로 바꾸고 보상을 0으로 바꿉니다. 에이전트가 “완료”를 말하는 것, 평가기가 결과를 인정하는 것, 실행 환경이 정리되는 것을 함께 추적하는 예입니다. 이 설계를 읽으며 자기 자동화에도 행동·채점·정리를 각각 기록해 보세요.

5디렉토리 구조 해부

제품·계약·실행기·테스트를 나누어 지도를 만듭니다
cua/ ├── apps/ │ ├── cua-spaces/ Tauri + React 앱 │ ├── cua-spaces-web/ 공유 웹 화면과 호스트 브리지 │ ├── cua-spaces-desktop/ Electron 셸 │ └── cua-spaces-macos/ 네이티브 SwiftUI 앱 ├── libs/ │ ├── cua/ │ │ ├── Cargo.toml SDK Rust workspace │ │ ├── proto/cua/ │ │ │ ├── env/v1/ 대상 컴퓨터의 RPC 계약 │ │ │ └── daemon/v1/ 클라이언트 daemon의 RPC 계약 │ │ ├── crates/ │ │ │ ├── cua-sdk/ 외부 언어로 공개할 API │ │ │ ├── cua-sandbox-core/ 생성·연결·준비·정리 │ │ │ ├── cua-vmm/ Lume·QEMU·컨테이너 실행 │ │ │ ├── cua-daemon/ 공유 런타임과 RPC │ │ │ ├── cua-cli/ cua 명령 │ │ │ └── cua-spaces-app-core/앱 공통 상태·의사결정 │ │ ├── python/ cua 바인딩·패키징 │ │ ├── typescript/ @trycua/cua │ │ ├── swift/ Swift 바인딩 │ │ └── kotlin/ Kotlin 바인딩 │ ├── cua-driver/ │ │ └── rust/crates/ │ │ ├── cua-driver-core/ 도구·세션·스냅샷·정책 │ │ ├── platform-macos/ macOS 구현 │ │ ├── platform-windows/ Windows 구현 │ │ ├── platform-linux/ X11·Wayland 구현 │ │ └── cua-driver-e2e/ 실제 데스크톱 테스트 │ ├── cua-spacesd/ 대상 컴퓨터 내부 서버 │ ├── lume/ Swift 기반 Apple VM 관리 │ ├── images/ 데스크톱 이미지와 이미지 목록 │ ├── cua-bench/ Python 과제·평가 도구 │ ├── cua-driver-bench/ 드라이버 비교 실험 │ ├── cua-s1/ 특화 모델 연구 │ ├── python/ 에이전트 등 Python 패키지 │ ├── typescript/ 별도 TypeScript 패키지군 │ └── fleet/ 읽기 전용 미러 ├── tests/e2e/cua-sdk/ 언어·실행 환경별 통합 시나리오 ├── scripts/ci/ OS별 검증 실행기 ├── .github/workflows/ CI·릴리스 파이프라인 ├── docs/ 공식 문서와 기여자 안내 ├── examples/ 기능별 사용 예제 └── legal/ 구성요소별 라이선스 안내

이 트리는 학습 경로를 보여 주기 위해 일부 항목만 담았습니다. libs/cua와 libs/cua-driver/rust는 독립 Cargo workspace입니다. 루트에 모든 Rust 코드를 한 번에 빌드하는 단일 workspace가 있다고 가정하지 마세요.

또한 libs/cua/typescript와 libs/typescript는 다른 위치입니다. 루트 개발 안내는 통합 cua SDK의 위치를 libs/cua로 지정합니다. 예전 예제나 패키지 이름을 발견하면 바로 현재 공개 API라고 가정하지 말고, 해당 폴더의 README·manifest·CI가 어떤 소비자를 대상으로 하는지 확인해야 합니다.

5-1. 직접 센 코드 규모

커밋 cdda707의 Git 추적 일반 파일은 9,219개입니다. 언어별 수치는 확장자를 기준으로 파일을 골라 줄바꿈을 세었으며, 마지막 줄에 줄바꿈이 없어도 한 줄로 계산했습니다. 빈 줄·주석·테스트·예제·생성 바인딩·미러 코드를 포함합니다. 심볼릭 링크와 Git 내부 파일은 제외한 수치입니다.

확장자파일 수물리적 줄 수
Rust · .rs1,751996,197줄 · 약 99.6만
Python · .py1,309374,874줄 · 약 37.5만
TypeScript · .ts886354,523줄 · 약 35.5만
TSX · .tsx34867,431줄 · 약 6.7만
Swift · .swift586269,086줄 · 약 26.9만
Go · .go23674,432줄 · 약 7.4만
Shell · .sh44550,779줄
JavaScript · .js5611,541줄
Protobuf · .proto206,494줄
C++ · .cpp / .cc235,258줄
C · .c5698줄
C/C++ 헤더 · .h816,832줄

이 표는 GitHub의 언어 비율과 같은 통계가 아닙니다. GitHub의 언어 판정은 별도 규칙을 사용하며, 물리적 줄 수는 코드의 난도나 직접 작성한 분량을 뜻하지 않습니다. .mdx·JSON·잠금 파일·이미지 등도 위 언어 표에 합산하지 않았습니다.

5-2. 원하는 기능에서 파일로 거꾸로 찾기

궁금한 질문먼저 읽을 파일이어 볼 곳
VM이 왜 안 준비될까libs/cua/crates/cua-sandbox-core/src/sandbox.rswait_ready() → libs/cua/crates/cua-vmm/src/probe.rs와 실행기
같은 명령을 Python으로 쓰려면libs/cua/crates/cua-sdk/src/native/libs/cua/python/의 공개 표면과 생성 코드
클릭이 왜 거절될까libs/cua-driver/rust/crates/cua-driver-core/src/background_input.rs해당 플랫폼 도구와 libs/cua-driver/rust/crates/cua-driver-core/src/snapshot_store.rs
화면에서 설정을 바꾸면apps/cua-spaces-web/src/bridge/transport.ts호스트 어댑터와 cua-spaces-app-core
성공률이 어떻게 계산될까libs/cua-bench/cua_bench/runners.pylibs/cua-bench/cua_bench/environment.py의 평가 호출과 과제별 평가기

한 함수에서 다음 책임으로 넘어가는 지점에 표시를 해 두면, 큰 파일을 모두 읽지 않고도 한 동작을 추적할 수 있습니다.

6학습 포인트 (기술별)

문법을 외우기보다 경계를 설계하는 이유를 익힙니다

6-1. Rust: trait와 enum으로 가능한 행동을 모델링하기

LocalRuntime은 기능 계약을, Backend는 실행 방식의 선택지를 나타냅니다. trait는 구현을 늘리는 축이고 enum은 미리 정한 경우를 나누는 축입니다. 어느 것을 택했는지 이유를 생각하며 읽어 보세요.

Arc<dyn LocalRuntime>은 여러 소유자가 같은 구현 객체를 공유하고, 구체적인 실행기 타입은 인터페이스 뒤에 감춘다는 뜻입니다. 반면 Backend::Embedded와 Backend::Daemon은 코드가 반드시 구별해 처리할 두 경로입니다.

작은 실습

가짜 실행기의 설계도 만들기

실제 VM 대신 메모리의 맵에 이름과 상태만 보관하는 FakeRuntime을 설계해 보세요. start·stop·delete의 입력과 반환값을 적고, 없는 이름을 지울 때의 오류를 정합니다. 하드웨어 없이도 수명 관리의 계약을 연습할 수 있습니다.

6-2. 비동기 프로그래밍: 시간 예산과 취소를 함께 다루기

wait_ready()는 준비되지 않은 상태와 복구할 수 없는 상태를 나눕니다. 단순히 10초 기다린 뒤 성공이라고 하는 방식은 컴퓨터 속도·다운로드·앱 기동 시간에 따라 흔들립니다. wait_spacesd()는 인증 오류를 즉시 반환하고, 종료한 인스턴스도 조기에 감지합니다.

같은 루프의 재시도 간격은 250ms입니다. 하지만 이 숫자만 복사하는 것이 핵심은 아닙니다. 마감 시각, 재시도할 오류, 즉시 중단할 오류, 마지막 실패 이유를 함께 보관하는 것이 핵심입니다.

# 소스의 아이디어를 옮긴 의사코드 · 특정 SDK API가 아닙니다
마감 = 현재시각 + 제한시간
반복:
    결과 = 상태확인()
    성공이면 반환
    인증오류 또는 대상종료이면 즉시 실패
    현재시각이 마감을 넘으면 마지막원인과 함께 실패
    250밀리초 대기
버스를 기다리는 방식

“5분 뒤에는 버스가 왔겠지”와 “도착 정보가 준비될 때까지 보되, 운행 중단이면 바로 다른 계획을 세운다”는 다릅니다. 준비 상태 확인은 후자입니다. 대기 시간이 길다는 이유만으로 모든 오류가 해결되지는 않습니다.

6-3. Protobuf와 gRPC: 기능을 계약으로 공개하기

libs/cua/proto/cua/env/v1/system.proto의 GetCapabilitiesResponse에는 protocol_version, protocol_revision, features, limits가 있습니다. 클라이언트는 버전 문자열만 비교하는 대신 어떤 기능이 있고 어떤 제한이 있는지 물을 수 있습니다.

메시지의 필드 번호는 통신 계약의 일부입니다. 새 필드를 추가하는 작업과 기존 필드의 의미를 바꾸는 작업은 호환성 위험이 다릅니다. 이 저장소가 buf breaking과 생성 코드의 변경 여부를 검사하는 이유를 해당 필드 목록에서 이해할 수 있습니다.

작은 실습

지원 여부를 묻는 클라이언트 흐름 그리기

“영상 기능이 있으면 스트림을 열고, 없으면 스크린샷만 사용한다”는 분기 표를 만드세요. 기능 없음, 인증 실패, 네트워크 실패를 각각 다른 결과로 다루면 기능 협상과 오류 처리를 구별할 수 있습니다.

6-4. OS 자동화: 좌표에 문맥을 붙이기

접근성 트리는 버튼의 역할·이름·값을 알려 주는 구조입니다. 픽셀은 이미지 위의 위치입니다. 접근성에 원하는 정보가 없으면 픽셀 경로가 필요할 수 있지만, 그 좌표는 창 이동·크기·DPI·스크린샷 축소의 영향을 받습니다.

libs/cua-driver/rust/crates/cua-driver-core/src/snapshot_store.rs의 ScreenshotContext와 ZoomContext::zoom_to_window()를 함께 읽어 보세요. 확대 이미지 좌표를 원래 창 좌표로 바꾸는 식은 origin + coordinate × scale_inv입니다. 같은 점을 여러 계층에서 중복 변환하면 오차가 커집니다.

실습으로 가로 1,000픽셀 창을 500픽셀 이미지로 표시했다고 가정하세요. 이미지의 x=120은 원래 x=240입니다. 창을 다시 확대했거나 이미지를 잘랐다면 배율뿐 아니라 원점도 필요합니다. 숫자 두 개를 전달하는 API보다 좌표계까지 담은 타입이 안전합니다.

6-5. TypeScript와 SwiftUI: 화면과 호스트의 책임 나누기

웹 화면의 HostTransport를 읽으며 요청 전송과 이벤트 구독을 분리한 이유를 찾아보세요. 버튼 클릭은 요청을 만들지만, 장시간 진행되는 연결이나 생성 상태는 나중에 이벤트로 도착할 수 있습니다.

apps/cua-spaces-macos/Package.swift는 SwiftUI 셸이 공유 Rust 앱 코어를 연결한다고 설명합니다. 화면마다 같은 규칙을 다시 쓰면 한쪽만 수정되는 문제가 생깁니다. 공통 코어와 얇은 호스트 계층은 이를 줄이는 방향입니다. 다만 UI 브리지의 형식과 스레드·객체 수명도 별도로 맞춰야 합니다.

작은 실습

연결 상태 네 가지를 그려 보기

미연결·연결 중·연결됨·실패 상태를 종이에 그리고, 각 상태에서 누를 수 있는 버튼과 들어올 수 있는 이벤트를 정하세요. 실패 후 재시도와 연결 도중 취소를 추가하면 UI 상태 기계가 필요한 이유가 드러납니다.

6-6. Python 평가: 행동과 채점을 독립시키기

libs/cua-bench/cua_bench/decorators.py는 tasks_config, setup_task, solve_task, evaluate_task로 함수의 역할을 표시합니다. 데코레이터는 함수에 _td_type과 _td_split 같은 메타데이터를 붙입니다.

Environment.make_from_module()이 그 표시를 읽고, Environment.evaluate()는 현재 과제와 세션을 평가 함수에 넘깁니다. _call_function()은 반환값이 awaitable인지 확인해 동기·비동기 함수를 모두 처리합니다. 과제 작성자와 실행기의 책임을 분리한 예입니다.

libs/cua-bench/cua_bench/core.py의 make()는 과제 디렉터리의 진입 파일(예: libs/cua-bench/tasks/miniwob/main.py)을 Python 모듈로 불러와 실행합니다. 따라서 과제는 단순 데이터 파일만이 아닙니다. 공개 데이터셋을 받더라도 평가 함수와 실행 환경 설정을 읽어야 재현성과 동작을 이해할 수 있습니다.

좋은 평가기는 에이전트의 완료 선언을 믿는 대신, 과제가 요구한 결과를 독립적인 증거로 확인합니다.

6-7. 빌드와 테스트: 한 가지 초록불로 모든 것을 설명하지 않기

docs/contributing/TESTING.md는 단일 루트 명령으로 모든 패키지·데스크톱·VM·이미지를 증명할 수 없다고 설명합니다. 문법·타입 검사, 프로토콜 검사, 실제 앱 조작은 서로 다른 실패를 찾습니다.

검사 층알아낼 수 있는 것그 검사만으로 모르는 것
타입·단위 검사토큰 파서, 상태 전이, 정책의 반환값실제 앱이 입력을 받았는지
계약·생성물 검사RPC 호환성, 바인딩이 원본과 일치하는지OS 권한과 GUI 세션이 올바른지
데스크톱 E2E실제 앱과 데스크톱 상태에서 관찰한 결과검증하지 않은 앱·OS·컴포지터의 보장

실습 아이디어는 “클릭 함수가 성공을 반환했는데 앱 값은 안 바뀌었다”는 가상 결함을 만드는 것입니다. 어떤 테스트가 이를 잡고 어떤 테스트는 지나치는지 적으면, 테스트를 많이 만드는 것과 강한 관찰 경계에 테스트를 두는 것의 차이가 보입니다.

7하드웨어 / 시스템 요구사항

소스 읽기, 현재 PC 조작, 가상 컴퓨터 실행은 요구사항이 다릅니다

7-1. 어떤 경로를 쓰는지 먼저 고르세요

목적필요 조건판단 근거
코드와 문서 학습 텍스트 편집기와 소스를 읽을 환경. VM·GPU·모델 키 불필요 인터페이스·정책·의존성·평가 흐름을 정적으로 읽는 단계
현재 데스크톱 제어 지원되는 macOS·Windows·Linux GUI 세션과 필요한 접근 권한 Driver 플랫폼 지원표. 모든 앱·입력 경로가 동일하게 지원되지는 않음
Lume VM Apple Silicon Mac과 Apple 가상화 기능. 패키지 선언의 macOS 하한은 14 libs/lume/Package.swift와 libs/cua/crates/cua-vmm/src/auto.rs. 게스트 이미지별 추가 조건 확인 필요
Spaces macOS 앱 macOS 26 이상. 로컬 macOS VM은 지원되는 Apple Silicon 실행 경로 필요 apps/cua-spaces-macos/Package.swift. Lume 자체의 하한과 앱의 하한을 구별
Linux 컨테이너 Docker API 호환 엔진과 선택한 gVisor·runc 실행 환경 libs/cua/crates/cua-vmm/src/auto.rs. 지원 경로에서는 관리 VM을 준비할 수도 있으며 최초 실행에 다운로드가 발생할 수 있음
QEMU VM 호스트·게스트 아키텍처에 맞는 QEMU와 펌웨어, 충분한 메모리·디스크 Linux KVM, macOS HVF, Windows WHPX 가속 경로. 조건에 따라 TCG 에뮬레이션으로 느려질 수 있음
로컬 모델 연구 모델별 가중치·실행 도구·메모리 별도 검토 libs/cua-s1/python/pyproject.toml의 PyTorch 의존성은 공통 VRAM 최소치를 정하지 않음

cua를 쓰는 데 필요한 자원은 선택한 실행 환경과 모델에 달려 있으며, 하나의 GPU·메모리 요구사항으로 전체 저장소를 설명할 수 없습니다.

7-2. 코드에 실제로 있는 기본값

libs/cua/crates/cua-sandbox-core/src/sandbox.rs의 CreateOptions::new()는 다음 값을 사용합니다. 이는 샌드박스에 전달하는 기본 설정이며 호스트 PC의 공식 최소 사양은 아닙니다. 실행기에 따라 자원 제한의 적용 방식도 다를 수 있습니다.

// CreateOptions::new()의 일부 설정
os: "linux".into(),
cpus: 2,
memory_mb: 4096,
ready_timeout: Duration::from_secs(600),
kind: Kind::Auto,
runtime: Runtime::Auto,

VM 하나에 약 4GiB를 할당하면 호스트 OS와 편집기·브라우저에 남길 메모리도 계산해야 합니다. 예를 들어 16GB 호스트에서 한 개를 먼저 실습하고, 여러 VM을 병렬 실행할 때는 수를 늘려 가며 여유를 측정하는 계획을 세울 수 있습니다. 이 예시는 학습용 자원 배분 예이며 공식 최소 사양이나 성능 실측값은 아닙니다.

7-3. 디스크는 이미지 크기와 여유 공간을 더해서 봅니다

libs/cua/crates/cua-vmm/src/disk.rs의 기본 최소 여유 공간은 5GiB, 경고 기준은 20GiB입니다. 이미지 크기를 미리 모를 때 쓸 추정값도 따로 있습니다.

대상소스의 추정값의미
컨테이너 가져오기2GiBCONTAINER_PULL_ESTIMATE
일반 VM 생성4GiBVM_CREATE_ESTIMATE
Lume 이미지30GiBLUME_PULL_ESTIMATE
Windows VM20GiBlibs/cua/crates/cua-vmm/src/preflight.rs의 WINDOWS_VM_ESTIMATE

이 값들은 다운로드의 실제 용량이나 설치 후 총 사용량을 보장하지 않습니다. ensure_space_in()은 필요한 바이트와 남겨 둘 최소 공간을 함께 확인합니다. 이미지 캐시·복제 디스크·기록 영상이 늘어나는 실험에서는 실제 사용량을 별도로 측정해야 합니다.

7-4. 시스템 권한과 개발 도구

원격 제어 포트도 자원과 함께 확인하세요. libs/cua-spacesd/crates/cua-spacesd-server/src/config.rs의 default_listen()은 토큰이 있으면 모든 인터페이스, 없으면 루프백을 기본값으로 택합니다. check_bind_policy()는 명시적인 bootstrap·토큰 대기 모드 등의 예외가 없을 때 토큰 없는 외부 바인딩을 거절합니다. 로컬 접속 성공을 외부 공개 설정의 안전성으로 일반화하지 않는 것이 중요합니다.

8직접 해볼 수 있는 실습 과제

다섯 과제 모두 “무엇을 만들고 어떻게 확인할지”부터 정합니다

1~3번은 저장소 코드나 설치 스크립트를 실행하지 않고도 수행할 수 있습니다. 별도 연습용 파일이나 문서로 시작하세요. 4~5번의 실제 실행은 공식 가이드에 맞춘 독립 실습 환경이 준비되었을 때 진행합니다.

실습의 완료 기준은 명령이 오류 없이 끝났다는 사실보다, 예상한 상태 변화와 실패 조건을 설명하고 확인할 수 있는가입니다.

과제 1 · 입문

계산기 작업의 책임 지도 만들기 예상 30~45분

목표: “6 × 7을 계산하고 결과를 확인한다”를 관찰·판단·입력·검증으로 나눕니다.

  1. 모델, Cua Driver, OS, 계산기 앱을 네 칸으로 그립니다.
  2. 현재 창 조회, 요소 선택, 클릭, 결과 조회를 어느 칸이 담당하는지 표시합니다.
  3. 샌드박스를 쓰는 경우와 현재 PC를 쓰는 경우의 추가 구성요소를 적습니다.

제출물: 화살표가 있는 한 장의 흐름도와 실패 사례 세 가지.

완료 기준: “도구는 성공했지만 결과는 틀림”, “드라이버 권한 없음”, “모델의 다음 행동이 틀림”을 서로 다른 문제로 설명할 수 있으면 완료입니다.

과제 2 · 입문

요소 토큰 형식 분석하기 예상 45~60분

목표: token_for()와 parse_token()을 읽고 형식의 허용·거절 조건을 정리합니다.

입력: s00001234:42, s1234:42, x00001234:42, s00001234:abc. 첫 토큰만 형식상 유효하며 스냅샷 값은 16진수 0x1234입니다.

확장: 연습용 프로그램에서 파싱 결과와 스냅샷 조회 결과를 별도로 표현해 보세요. 형식이 맞아도 스냅샷이 이미 사라진 경우를 추가합니다.

제출물: 입력 네 개의 결과 표와 “형식 유효”·“참조 유효”의 차이 설명.

완료 기준: 토큰이 파싱된다는 사실만으로 버튼을 눌러도 된다고 결론 내리지 않으면 완료입니다.

과제 3 · 중급

샌드박스 준비 상태를 표로 시뮬레이션하기 예상 1~2시간

목표: Sandboxes::create(), declares_spacesd(), wait_spacesd()를 연결해 읽습니다.

다음 입력을 종이 표나 독립적인 가짜 실행기로 모델링하세요. 실제 VM을 만들 필요는 없습니다.

상황예상 결과
일반 컨테이너, HTTP probe 통과선언하지 않은 spacesd를 기다리지 않고 준비 완료
spacesd 선언 이미지, 아직 Health 미응답시간 예산 안에서 재시도
spacesd 인증 토큰 오류오류를 즉시 반환하고 실패 정책 적용
준비 도중 인스턴스 종료남은 시간 전체를 기다리지 않고 원인과 함께 실패
준비 실패, 기존 같은 이름의 대상기존 대상 보존

제출물: 시간 순서가 있는 상태 전이 표와 자원 정리 결과.

완료 기준: 다운로드 시간과 부팅 준비 시간, 새 대상과 기존 대상의 정리 정책을 각각 구별하면 완료입니다.

과제 4 · 중급

계산기의 결과를 앱 상태로 확인하기 예상 1~2시간 · 별도 GUI 환경

목표: 공식 Driver 시작 안내의 흐름으로 작은 데스크톱 과제를 수행합니다. 현재 사용하는 구성요소의 설치 버전과 OS 지원 범위를 먼저 확인합니다.

  1. 계산기만 연 실습 환경에서 창을 식별하고 현재 상태를 읽습니다.
  2. 사용한 창 ID·관찰 토큰·좌표 기준을 기록하고 6 × 7을 입력합니다.
  3. 도구 응답과 별도로 화면 또는 접근성 값에서 42를 확인합니다.
  4. 앱 창이 여러 개일 때 대상 선택과 결과 검증이 같은 창에 묶이는지 살펴봅니다.

제출물: 관찰 → 행동 → 실제 값 확인을 나눈 기록. 화면에는 실습에 필요한 정보만 남깁니다.

완료 기준: 결과 42뿐 아니라 “다른 창의 42로 성공을 판정하지 않는다”는 검증 근거까지 남기면 완료입니다.

과제 5 · 고급

작은 평가기를 설계하고 실행 조건을 고정하기 예상 반나절 · 독립 샌드박스

목표: “특정 파일을 정확한 내용으로 저장한다”는 과제를 준비·해결·평가로 나눕니다. Bench의 함수 역할을 참고하되 현재 버전의 native 실행 경로를 확인합니다.

  1. Task의 설명과 metadata에 목표 경로·예상 내용을 기록합니다.
  2. 준비 단계에서는 이전 결과를 제거한 독립 환경을 만들고, 해결 단계에서는 작업을 수행합니다.
  3. 평가기는 완료 문장을 읽지 않고 실제 파일의 내용으로 0 또는 1을 반환하도록 설계합니다.
  4. 이미지 식별자·도구 버전·모델 설정·최대 단계 수·오류·정리 결과를 기록합니다.
  5. 파일 없음, 틀린 내용, 정리 실패를 각각 별도 사례로 확인합니다.

제출물: 과제 정의, 평가 조건, 정상·실패 사례의 결과 표와 실행 조건 목록.

완료 기준: 같은 입력에서 같은 평가가 나오고, 에이전트의 자기 보고가 성공 점수를 바꾸지 않으면 완료입니다. 대규모 모델 비교나 수치의 일반화는 그다음 단계입니다.

여기까지의 성취

1~3번을 끝냈다면 이미 타입·상태·참조 수명·실패 정리라는 시스템 설계 주제를 공부한 것입니다. 실제 입력을 보내기 전에 성공과 실패의 의미를 먼저 정의하는 습관을 가져가세요.

9관련 기술 심화 학습 로드맵

주 3~5시간을 가정한 여섯 주 계획 · 속도는 자유롭게 조절하세요

먼저 Python이나 TypeScript 중 익숙한 언어로 전체 흐름을 이해한 뒤 Rust 내부로 들어가는 순서가 좋습니다. Rust 문법을 처음부터 모두 끝내야 이 저장소를 읽을 수 있는 것은 아닙니다. 매주 작지만 설명 가능한 산출물을 남기세요.

주차배울 내용cua에서 읽을 곳남길 결과
1주프로세스·VM·컨테이너·SDK의 차이 README.md, docs/contributing/Development.md, libs/cua/crates/cua-sandbox-core/src/lib.rs 현재 PC / 샌드박스 / 호스트 daemon / 게스트 서버를 구별한 그림
2주Rust의 소유권, Result, enum, trait, Arc libs/cua/crates/cua-sandbox-core/src/runtime.rs의 LocalRuntime, libs/cua/crates/cua-sdk/src/native/cua.rs의 Backend 가짜 실행기의 인터페이스와 상태 표. 오류를 문자열 로그만으로 처리하지 않는 이유 설명
3주Tokio 비동기, 준비 상태 확인, 제한시간, 취소 Sandboxes::create(), wait_ready(), DiscardGuard 다운로드·부팅·probe·정리를 나눈 시퀀스와 실패 사례 표
4주접근성 트리, 픽셀 좌표, DPI, 스냅샷 참조 libs/cua-driver/rust/crates/cua-driver-core/src/element_token.rs, libs/cua-driver/rust/crates/cua-driver-core/src/snapshot_store.rs, 플랫폼 지원 문서 토큰 파싱과 유효성 표, 축소·확대 이미지의 좌표 변환 예시
5주Protobuf·RPC·FFI·UI 브리지의 차이 libs/cua/proto/cua/env/v1/system.proto, libs/cua/crates/cua-sdk/src/lib.rs, apps/cua-spaces-web/src/bridge/transport.ts Python 호출이 Rust와 daemon·게스트를 통과하는 경계 지도
6주평가 함수, 실행 조건 고정, E2E 증거 libs/cua-bench/cua_bench/runners.py, libs/cua-bench/cua_bench/decorators.py, docs/contributing/TESTING.md 작은 과제 하나의 성공 정의·실패 정의·검증 자료·재현 조건

학습의 진도는 읽은 파일 수보다, 한 번의 행동이 어떤 경계를 지나고 어디서 실패할 수 있는지 설명하는 능력으로 확인하세요.

관심 분야별 다음 갈림길

매주 스스로 확인할 세 가지

이 함수의 입력은 누가 만들었나요? 출력이 성공이어도 어떤 상태는 아직 보장하지 못하나요? 실패하면 누가 자원을 정리하나요? 세 질문에 답할 수 있는 기능을 하나씩 늘려 가세요.

10핵심 키워드 사전

이름보다 “어떤 문제를 해결하는가”를 기억하세요
용어쉬운 설명
Computer Use프로그램이 화면·앱·입력을 이용해 컴퓨터 작업을 수행하는 방식입니다.
Computer-Use 2.0cua 문서에서는 한 작업에서 코드·API·그래픽 인터페이스를 오가는 접근을 설명하는 표현입니다. 공통 표준 규격의 이름으로 단정하지 않습니다.
에이전트목표를 받아 관찰·판단·도구 호출을 반복하는 프로그램입니다. Driver 자체가 모든 계획을 세우지는 않습니다.
하네스에이전트나 도구를 정해진 조건에서 실행하고 결과를 수집하는 주변 실행 프로그램입니다.
모노레포서로 연결된 여러 제품·패키지를 같은 Git 저장소에서 관리하는 구조입니다.
샌드박스작업을 분리해 실행하는 환경입니다. 격리 수준은 선택한 VM·컨테이너·설정에 따라 달라집니다.
VM가상 하드웨어 위에서 별도 운영체제를 실행하는 가상 머신입니다.
컨테이너주로 호스트 커널을 바탕으로 프로세스·파일·네트워크 환경을 나누는 실행 방식입니다.
gVisor / runc컨테이너 실행 경로입니다. gVisor는 사용자 공간 커널 계층으로 격리를 강화하는 접근이며, 두 경로의 보장을 같다고 보면 안 됩니다.
하이퍼바이저가상 머신을 실행하고 하드웨어 자원을 중재하는 계층입니다. 가속 가능 여부가 VM 성능에 영향을 줍니다.
daemon요청을 받으며 지속적으로 동작하는 프로세스입니다. cua에서는 호스트 공유 런타임과 게스트 서버의 이름을 구별해야 합니다.
접근성 트리앱이 버튼·입력칸·이름·값 등을 보조 기술에 공개한 구조입니다. 앱이 노출하지 않는 정보까지 자동으로 생기지는 않습니다.
AX / UIA / AT-SPI각각 macOS·Windows·Linux의 접근성 API를 가리킬 때 사용하는 이름입니다.
컴포지터여러 창의 화면을 합성하고 표시하는 구성요소입니다. Wayland에서는 창 탐색·캡처·입력의 가능 범위가 컴포지터별로 달라집니다.
PID / window_id프로세스와 창의 식별자입니다. 한 프로세스에 창이 여러 개 있을 수 있으며 식별자는 영원히 유효하지 않습니다.
스냅샷어느 시점에 읽은 화면·요소 상태의 묶음입니다. 현재 앱 상태와 항상 같지는 않습니다.
element_token요소를 특정 스냅샷과 연결하는 참조입니다. 로그인 토큰과 역할이 다릅니다.
좌표계 / DPI위치를 어느 원점·배율·단위로 표현하는지 정하는 기준입니다. 이미지 픽셀과 OS 논리 좌표를 혼동하면 엉뚱한 곳을 누를 수 있습니다.
probe / readiness서비스가 실제로 응답할 준비가 되었는지 확인하는 검사와 상태입니다. 프로세스가 있다는 사실보다 구체적인 조건입니다.
trait / adaptertrait는 필요한 기능의 계약, adapter는 구체적인 실행기·OS를 그 계약에 맞추는 구현입니다.
FFI / UniFFIFFI는 다른 언어의 네이티브 함수를 호출하는 경계이고, UniFFI는 Rust API의 여러 언어 바인딩 생성을 돕는 도구입니다.
RPC / gRPC다른 프로세스나 컴퓨터의 함수를 요청·응답으로 호출하는 방식입니다. gRPC는 그 통신 체계 중 하나입니다.
Protobuf메시지와 서비스의 구조를 선언하고 여러 언어의 코드를 생성하는 계약 도구입니다.
MCPAI 클라이언트가 외부 도구·자원과 연결하는 프로토콜입니다. OS 입력 권한이나 도구의 정확성을 대신 보장하지 않습니다.
QUIC신뢰성·암호화 등을 제공하는 전송 프로토콜입니다. cua의 미디어 경로에서 사용되며 그 자체가 화면을 인코딩하는 코덱은 아닙니다.
H.264 / Opus각각 영상과 오디오 데이터를 압축·복원하는 데 사용하는 코덱입니다.
fail-closed필요한 조건을 확인하지 못하면 계속 실행하지 않고 거절하거나 중단하는 정책입니다.
궤적 · trajectory관찰·행동·결과를 시간 순서로 남긴 기록입니다. 학습 데이터와 실패 분석의 재료가 됩니다.
E2E 테스트여러 계층을 연결해 사용자 작업의 실제 결과를 확인하는 테스트입니다. 단순 함수 응답 검사보다 넓은 범위를 봅니다.
digest / SHA-256파일·이미지 내용을 구별하기 위한 해시 식별값입니다. 버전 이름만 적는 것보다 같은 내용인지 확인하기 좋습니다.
MIT / FSL-1.1-MIT이 저장소에 함께 존재하는 라이선스입니다. 루트 표기만 읽지 말고 사용하려는 구성요소의 LICENSE와 고지를 확인해야 합니다.

11참고 링크

공식 입구와 재현 가능한 소스 기준점을 함께 남깁니다

11-1. 프로젝트와 사용 안내

11-2. 코드와 설계를 이어 읽는 링크

11-3. 기반 기술의 공식 학습 자료

현재 상태 (2026-10-23 확인)

항목확인값
저장소trycua/cua · GitHub Trending Rust Monthly #4
스타 / 포크30,747 / 2,235 · 2026-10-23 GitHub 기준
생성일2025-01-31
주 언어Rust · Python·TypeScript·Swift·Go 등도 포함
최근 push2026-10-23
최신 릴리스cua-spaces-v0.13.1 · 2026-10-22. 저장소의 릴리스 항목이며 모든 구성요소가 이 버전이라는 뜻은 아님
최근 커밋cdda707 · 2026-10-23 · Browser Use CLI 비교 경로를 버전 고정·문제가 있으면 중단하는 점검으로 준비한 변경, PR #5765
전체 커밋 해시cdda707954413886907411c96dea8b910ee47143
코드 규모Git 추적 일반 파일 9,219개. Rust 약 99.6만 줄, Python 약 37.5만 줄, TypeScript·TSX 합계 약 42.2만 줄, Swift 약 26.9만 줄. 생성물·미러·테스트 포함
소스 버전 선언cua SDK 0.7.0, Driver workspace 0.38.0, Spaces 앱 0.13.1, Bench 0.3.1. 이 표만으로 개별 배포·설치 버전은 확정하지 않음
라이선스GitHub·루트는 MIT. Spaces·cua-spacesd·Driver Bench 등은 별도 FSL-1.1-MIT 표기. 기타 하위 디렉토리·모델의 고지도 확인 필요
설명 기준커밋 cdda707의 의존성·핵심 소스·이미지·CI·문서. 실제 지원 범위와 성능은 플랫폼·앱·실행 조건별로 판단
쓰기 전에 알아둘 한계
지원 범위·라이선스·검증 수준은 구성요소별로 판단하세요

실행 결과의 한계: 아키텍처 설명의 기준은 커밋 cdda707입니다. 실제 데스크톱 입력, VM 부팅, 모델 정확도, 처리량은 각 OS·앱·실행 조건에서 확인해야 합니다. 공개 데모와 코드만으로 모든 OS·앱에서 같은 동작을 보장할 수는 없습니다.

문서와 코드의 차이: README의 Spaces 수동 링크는 0.9.4, Bench 모의 provider 안내는 현행 설정과 차이가 있습니다. Browser Use 비교 경로의 사전 점검도 미구현 상태로 실패합니다. 예제를 실행할 때는 사용하려는 구성요소와 버전을 맞추세요.

라이선스의 차이: README는 미디어 전송 프로토콜을 MIT로 설명하지만, libs/cua/crates/cua-media-protocol/Cargo.toml과 legal/LICENSING.md는 FSL-1.1-MIT로 표시합니다. 제품에 포함하거나 서비스를 제공하려면 개별 LICENSE와 배포물의 고지를 직접 확인해야 합니다.

모델과 환경의 차이: CUA-S1 코드는 가중치 자체가 아니며 모델·데이터의 조건은 별도입니다. VM·컨테이너 격리도 실행기와 권한·네트워크 설정에 달려 있습니다. 자동화는 독립 실습 환경에서 작은 과제와 명확한 성공 조건으로 시작하세요.