oxi · Headless Browser · Rust
oxibrowser
Chromium fork가 아닌 순수 Rust 헤드리스 브라우저. 24MB 단일 바이너리, ~50ms cold start, ~8MB base RAM. AI 에이전트가 웹을 자동화하기 위한 CLI 우선 도구로 처음부터 설계됐다.
1. 왜 또 헤드리스 브라우저인가
기존 도구(Headless Chrome, Playwright/Puppeteer)는 강력하지만 AI 에이전트가 구동하기엔 무겁다. Chromium 설치 400MB, RAM 베이스 200MB, cold start 800ms. 100 인스턴스를 동시에 띄우는 일은 비현실적이다. oxibrowser는 이 사용 패턴에 맞춰 다음을 처음부터 다시 설계했다.
- 바이너리 크기: 24MB 단일 정적 바이너리
- Cold start: ~50ms
- Base memory: ~8MB
- JS 엔진:
boa_engine— Rust 순수, V8 없음 - TLS:
btls(BoringSSL C binding) — 스텔스 핑거프린트 에뮬레이션을 위해
2. 비교 표
OxiBrowser
- 24MB 바이너리
- ~8MB base RAM
- ~50ms cold start
- Pure Rust (boa)
- MIT
Headless Chrome
- ~400MB 설치
- ~200MB base RAM
- ~800ms cold start
- C++ (V8)
- BSD / ToS
3. 아키텍처
워크스페이스 4개 크레이트.
oxibrowser-core
URL fetch, HTML 파싱, 리소스 로더, 네트워크 스택
oxibrowser
DOM 트리, CSS cascade, 레이아웃, 이벤트 루프, 렌더 트리
oxibrowser-webapi
WebAPI 구현 — fetch · DOM · Events · innerHTML · rAF
oxibrowser-cdp
Chrome DevTools Protocol 서버 — Puppeteer/Playwright 호환
3.1 v0.17에서 닫힌 갭
단순 HTML fetcher와 "진짜 헤드리스 브라우저" 사이의 간격을 대부분 메웠다.
- 이벤트: 생성자가 init dict 존중 —
clientX,ctrlKey등 실제 필드로 전달.dispatchEvent가event.target/currentTarget설정.preventDefault/stopPropagation/stopImmediatePropagation완전 동작. 이벤트 버블링이 부모 체인을 따라 걷는다 (이전엔parent.addEventListener가child.dispatchEvent에 안 보였던 버그 수정). - requestAnimationFrame: 16ms 데드라인으로 스케줄,
DOMHighResTimeStamp콜백에 전달 - innerHTML: SPA-style DOM 인젝션 정상 동작
- fetch: 스펙 준수
Response+arrayBuffer()등 메서드 완비 - innerText getter, 독립
performance글로벌
4. AI 에이전트 우선 CLI
CLI는 인간보다 에이전트를 1순위 사용자로 가정한다.
--json출력으로 머신 파싱 가능describe— 스키마 제공 (스킬 프롬프트용)skill— LLM 프롬프트에 바로 주입되는 스킬 정의 출력session— 다단계 워크플로우 상태 유지
4.1 CDP 호환
oxibrowser-cdp가 Chrome DevTools Protocol 서버를 구현한다. Puppeteer · Playwright · 그리고 어떤 CDP 클라이언트도
별도 수정 없이 붙는다. Playwright의 chromium launch를 oxibrowser 바이너리로 가리키면
같은 테스트 스위트가 그대로 동작한다.
5. 보안 기본값
- SSRF 방지: CIDR 기반 차단 (사설/루프백/멀티캐스트)
- robots.txt 존중: 기본 ON,
--no-robots로 opt-out - 샌드박스 escape 표면 제거: 렌더링 없는 텍스트 기반 엔진이므로 GPU/오디오/확장 표면 자체가 없음
6. 사용 시나리오
- AI 에이전트 웹 자동화 — oxios가 oxibrowser를 내장 브라우저로 사용 (oxibrowser는 oxios의 의존성)
- 스케일링 스크래퍼 — 100 인스턴스를 동시에 띄워도 RAM 800MB
- 테스트 인프라 — CI에서 Playwright의 launch 타겟만 교체, 테스트는 그대로
- 스텔스 핑거프린트 — btls 기반 TLS 핸드셰이크가 일반 브라우저와 구분 어려움
7. oxios 통합 — in-process 브라우저
oxios가 oxibrowser를 내장 브라우저로 사용한다 — 별도 Chromium 설치나 헤드리스 브라우저 subprocess 없이.
AI 에이전트는 kernel.browser API 한 줄로 웹 자동화를 시작한다.
// oxios 측 (Rust)
let browser = kernel.browser();
browser.goto("https://example.com").await?;
let form = browser.query("form#login").await?;
form.fill("#email", "agent@oxi.dev").await?;
form.click("button[type=submit]").await?;
// 또는 CDP 클라이언트 경유
let client = Browser::connect("http://localhost:9222").await?;
let page = client.new_page().await?; 이 통합이 가능한 이유는 둘 다 단일 정적 바이너리이기 때문이다. oxibrowser가 24MB, oxios는 컨테이너 없이 in-process. 100개 에이전트가 동시에 브라우저를 띄워도 시스템 부하가 작다.
7.1 통합의 의의
다른 AI 에이전트 도구는 보통 Playwright/Puppeteer를 subprocess로 띄운다. 매 에이전트마다 별도 프로세스·RAM 200MB. oxicode와 oxios 모두 oxibrowser를 같은 프로세스 안에서 사용한다 — AI 에이전트의 웹 작업이 시스템 콜 수준으로 가볍다.
- oxicode:
oxicode-agent이oxibrowser를 필수 의존.oxicode-sdk의native-browserfeature가oxibrowser-core를 가져와BrowserEvent를 re-export. - oxios:
oxios/Cargo.toml의oxibrowser = "0.16"의존.kernel.browserAPI가 in-process 임베드.
둘 다 같은 foundation 위에 다른 추상화(browser 트레잇 vs kernel.browser API)를 얹는다 — 같은 인프라를 공유하지만 각자의 도구 호출 모델에 맞게 노출한다.