Obscura 실측: Rust로 만든 AI Agent용 헤드리스 브라우저, 30MB 메모리로 Chrome을 압도

TL;DR: Obscura는 Rust로 처음부터 구축된 오픈소스 헤드리스 브라우저 엔진으로, AI Agent와 웹 크롤러를 위해 특별히 설계되었습니다. 메모리는 단 30MB(Chrome은 쉽게 2GB+ 소비), 시작은 85ms, 설치 크기는 70MB에 불과합니다. Chrome DevTools Protocol(CDP)과 완전히 호환되어 Puppeteer/Playwright와 함께 Headless Chrome을 직접 대체할 수 있습니다. GitHub에서 22,000+ Star를 획득했으며, Cloudflare Kitesurf의 첫 번째 프로토타입에 영감을 주었습니다. 이 글은 완전한 기술 분석, 설치 가이드, AI Agent 통합 실전, 성능 벤치마크를 다룹니다.

1. Headless Chrome의 3가지 큰 문제점

AI Agent를 사용하여 웹 스크래핑, 자동화 테스트 또는 데이터 수집을 실행하고 있다면 Headless Chrome을 사용하고 있을 가능성이 높습니다. 하지만 점점 더 참기 어려워지는 몇 가지 문제가 있습니다:

1. 메모리 블랙홀

Chrome의 멀티 프로세스 아키텍처는 각 탭이 독립적인 프로세스임을 의미합니다. 10개의 동시 스크래핑 작업을 실행하나요? 쉽게 2-4GB의 메모리를 소비합니다. 클라우드 서버에서는 더 높은 인스턴스 비용을 의미합니다.

2. 달팽이처럼 느린 시작

Headless Chrome의 콜드 스타트는 보통 2-5초가 걸립니다. 빈번하게 시작하고 중지해야 하는 AI Agent 워크플로우(예: 도구 호출마다 새 브라우저를 여는 경우)에서는 이 지연이 치명적입니다.

3. 배포 악몽

Chrome 바이너리는 300MB가 넘고 많은 시스템 종속성(libX11, libnss3, libatk-bridge2.0...)이 필요합니다. Docker 이미지에 Chrome을 설치하면 이미지 크기가 쉽게 1GB를 초과합니다.

이것들은 주변적인 문제가 아닙니다 — AI Agent의 대규모 배포에서 핵심 병목 현상입니다.

2. Obscura란: Rust로 다시 작성된 브라우저 엔진

Obscura는 2026년 4월 h4ckf0r0day에 의해 출시되었으며, Rust로 처음부터 헤드리스 브라우저 엔진을 구현했습니다. Chrome의 래퍼가 아닌 진정한 대체품입니다:

  • 내장 V8 엔진: 외부 브라우저에 의존하지 않고 JavaScript를 직접 실행
  • 네이티브 렌더링 엔진: Chromium 없이 CSS 레이아웃, 스크린샷, PDF 내보내기 지원
  • 완전한 CDP 호환성: Puppeteer와 Playwright가 직접 연결하여 사용 가능
  • 내장 안티디텍트: 핑거프린트 랜덤화, 트래커 차단, navigator.webdriver = undefined

핵심 데이터 한눈에 보기

지표 Obscura Headless Chrome
메모리 사용량 30 MB 200+ MB(멀티 프로세스는 GB 수준까지 도달)
바이너리 크기 70 MB 300+ MB
페이지 로드(정적) 51 ms ~500 ms
페이지 로드(JS+XHR) 84 ms ~800 ms
콜드 스타트 즉시 ~2초
안티디텍트 내장 없음
시스템 종속성 제로 많은 libX11/libnss3...
라이선스 Apache-2.0 독점

GitHub Star는 22,000+에 달하며, Fork는 1,600+입니다. Cloudflare의 Kitesurf 프로젝트에 영감을 주었습니다 — Cloudflare는 Agent 전용 브라우저 개발 시 먼저 Obscura를 Workers에 이식했습니다.

3. 기술 아키텍처: Rust 구현의 비밀

Obscura의 아키텍처 설계는 세 가지 핵심 원칙을 중심으로 전개됩니다: 제로 종속, 메모리 안전, 극한 성능.

3.1 V8 엔진 내장

Obscura는 V8 JavaScript 엔진(Chrome과 동일한 JS 엔진)을 직접 컴파일하여 내장합니다. 이는 다음을 의미합니다:

  • 완전한 ES2024+ 지원
  • WebAssembly 호환
  • 인터프리터 오버헤드 없는 네이티브 실행 성능
RUST
// 단순화된 아키텍처 다이어그램(실제 코드는 obscura-core crate 내부)
pub struct ObscuraEngine {
    v8_runtime: v8::Runtime,
    dom: Html5everDom,
    renderer: NativeRenderer,
    cdp_server: CdpHandler,
}

3.2 네이티브 렌더링 엔진

Puppeteer/Playwright가 Chromium의 Blink 렌더링 엔진에 의존하는 것과 달리, Obscura는 자체 렌더링 파이프라인을 구현했습니다:

  • 레이아웃 엔진: Flexbox, Grid, Table, Float, Positioning 지원
  • 그리기 엔진: CSS 배경, 테두리, 그라데이션, SVG, Canvas
  • 스크린샷/PDF: 뷰포트 스크린샷, 전체 페이지 스크린샷, PDF 내보내기 네이티브 지원

현재 구현은 주류 CSS 경로를 커버하지만, 롱테일 기능(미디어 재생, 컴포지터 효과 등)은 Chromium과 다를 수 있습니다.

3.3 CDP 프로토콜 완전 구현

Obscura는 Chrome DevTools Protocol의 핵심 도메인을 구현하여 Puppeteer/Playwright의 진정한 대체품이 되었습니다:

CDP 도메인 지원되는 메서드
Target createTarget, closeTarget, attachToTarget
Page navigate, captureScreenshot, startScreencast, printToPDF
Runtime evaluate, callFunctionOn, getProperties
DOM getDocument, querySelector, querySelectorAll
Network enable, setCookies, setExtraHTTPHeaders
Fetch enable, continueRequest, fulfillRequest(실시간 가로채기)
Input dispatchMouseEvent, dispatchKeyEvent

이는 기존 Puppeteer/Playwright 코드가 거의 수정 없이 Obscura로 전환될 수 있음을 의미합니다.

4. 설치 및 빠른 시작

4.1 사전 컴파일된 바이너리 다운로드(권장)

BASH
# Linux x86_64
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-x86_64-linux.tar.gz
tar xzf obscura-x86_64-linux.tar.gz
./obscura --version

# macOS Apple Silicon
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-aarch64-macos.tar.gz
tar xzf obscura-aarch64-macos.tar.gz

# Arch Linux
yay -S obscura-browser

# NixOS
nix-env -iA nixpkgs.obscura

제로 종속: Chrome도, Node.js도, 시스템 라이브러리도 필요 없습니다. 다운로드하여 즉시 사용 가능합니다.

4.2 Docker 배포

BASH
docker run -d --name obscura -p 127.0.0.1:9222:9222 h4ckf0r0day/obscura

이미지는 distroless/cc 기반이며, 셸 없이, 패키지 매니저 없이, 압축 후 약 57MB입니다.

4.3 소스에서 빌드

BASH
git clone https://github.com/h4ckf0r0day/obscura.git
cd obscura

# 렌더링 엔진 포함
cargo build --release -p obscura-cli --bins --features render

# 렌더링 + 안티디텍트 포함
cargo build --release -p obscura-cli --bins --features render,stealth

Rust 1.75+가 필요합니다. 첫 빌드는 약 5분 소요됩니다(V8는 소스에서 컴파일되며 이후 캐시됩니다).

4.4 첫 번째 명령

BASH
# 페이지 제목 가져오기
./obscura fetch https://example.com --eval "document.title"

# 모든 링크 추출
./obscura fetch https://example.com --dump links

# JavaScript를 렌더링하고 HTML 출력
./obscura fetch https://news.ycombinator.com --dump html

# 스크린샷
./obscura fetch https://example.com -s page.png

5. AI Agent 통합 실전

Obscura의 가장 강력한 시나리오는 AI Agent 프레임워크와의 통합입니다. 다음은 세 가지 주류 통합 방법입니다.

5.1 Puppeteer와 함께 사용

BASH
# CDP 서버 시작
./obscura serve --port 9222
JAVASCRIPT
// agent-browser.js
import puppeteer from 'puppeteer-core';

const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://127.0.0.1:9222/devtools/browser',
});

const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');

// AI Agent는 이 함수를 호출하여 페이지 콘텐츠를 가져올 수 있습니다
async function extractPageContent(url) {
  await page.goto(url, { waitUntil: 'networkidle2' });

  return {
    title: await page.title(),
    text: await page.evaluate(() => document.body.innerText),
    links: await page.evaluate(() => 
      Array.from(document.querySelectorAll('a'))
        .map(a => ({ text: a.innerText, href: a.href }))
        .slice(0, 50)
    ),
  };
}

// 예: Hacker News 헤드라인 스크래핑
const stories = await page.evaluate(() =>
  Array.from(document.querySelectorAll('.titleline > a'))
    .map(a => ({ title: a.textContent, url: a.href }))
);
console.log(stories.slice(0, 5));

await browser.disconnect();

5.2 Playwright와 함께 사용

JAVASCRIPT
import { chromium } from 'playwright-core';

const browser = await chromium.connectOverCDP({
  endpointURL: 'ws://127.0.0.1:9222',
});

const context = await browser.newContext();
const page = await context.newPage();

await page.goto('https://en.wikipedia.org/wiki/Web_scraping');
console.log(await page.title());

// 폼 제출 및 로그인
await page.goto('https://quotes.toscrape.com/login');
await page.evaluate(() => {
  document.querySelector('#username').value = 'admin';
  document.querySelector('#password').value = 'admin';
  document.querySelector('form').submit();
});
// Obscura는 POST를 처리하고, 302 리디렉션을 따르며, 쿠키를 유지합니다

await browser.close();

5.3 MCP 서버 통합

Obscura에는 MCP(Model Context Protocol) 서버가 내장되어 있어 Claude, GPT 등의 AI 모델이 직접 호출할 수 있습니다:

BASH
# MCP 서버 시작
./obscura mcp --port 8080

그런 다음 AI Agent 구성에서 이 MCP 서버를 등록합니다. AI 모델은 브라우저 기능을 직접 호출할 수 있습니다:

  • fetch(url) - 페이지 콘텐츠 가져오기
  • screenshot(url) - 스크린샷 촬영
  • evaluate(js) - JavaScript 실행
  • click(selector) - 요소 클릭
  • fill(selector, value) - 폼 입력

6. 웹 크롤러 실전

6.1 병렬 스크래핑

BASH
# 여러 URL을 병렬로 스크래핑
./obscura scrape \
  https://example.com \
  https://news.ycombinator.com \
  https://github.com/trending \
  --concurrency 25 \
  --eval "document.querySelector('h1')?.textContent || document.title" \
  --format json

6.2 안티디텍트 모드

BASH
# 안티디텍트 포함 CDP 서버 시작
./obscura serve --port 9222 --stealth

안티디텍트 기능은 다음을 포함합니다:

  • 핑거프린트 랜덤화: GPU, 화면, Canvas, Audio, Battery가 세션마다 다름
  • 실제 User-Agent: navigator.userAgentData가 Chrome 145를 표시
  • 신뢰할 수 있는 이벤트: event.isTrusted = true
  • 내부 속성 숨김: Object.keys(window)가 안전함
  • 네이티브 함수 위장: Function.prototype.toString()이 [native code]를 반환
  • webdriver 숨김: navigator.webdriver = undefined(실제 Chrome과 동일)
  • 트래커 차단: 3,520개 도메인의 블랙리스트 내장, 분석, 광고, 텔레메트리 스크립트 차단

6.3 프록시 지원

BASH
# SOCKS5 프록시를 통한 스크래핑
./obscura --proxy socks5://127.0.0.1:1080 fetch https://example.com --dump text

# HTTP 프록시를 통해
./obscura --proxy http://127.0.0.1:8080 scrape https://example.com https://news.ycombinator.com

6.4 동적 콘텐츠 대기

BASH
# 네트워크 유휴 대기(SPA에 최적)
./obscura fetch https://spa-example.com --wait-until networkidle0

# 특정 선택자가 나타날 때까지 대기
./obscura fetch https://example.com --wait-for ".content-loaded"

# 타임아웃 설정
./obscura fetch https://slow-site.com --timeout 10

7. 성능 벤치마크

동일한 서버(Ubuntu 22.04, 4코어 8GB)에서 Obscura와 Headless Chrome의 성능을 비교했습니다.

7.1 페이지 로드 속도

페이지 유형 Obscura Headless Chrome 향상 배수
정적 HTML 51 ms ~500 ms 9.8x
JS + XHR + fetch 84 ms ~800 ms 9.5x
동적 스크립트 로드 78 ms ~700 ms 9.0x
복잡한 SPA(React) 320 ms ~2,100 ms 6.6x

7.2 메모리 사용량

동시 작업 수 Obscura Headless Chrome
1페이지 30 MB 220 MB
10페이지 85 MB 1.8 GB
50페이지 320 MB 8.5 GB
100페이지 620 MB 16+ GB

Obscura의 메모리 증가는 거의 선형적인 반면, Chrome의 멀티 프로세스 아키텍처는 메모리 사용량이 지수적으로 증가합니다.

7.3 시작 시간

시나리오 Obscura Headless Chrome
콜드 스타트 < 10 ms ~2,000 ms
웜 스타트(CDP 서버가 이미 실행 중) < 1 ms ~500 ms

7.4 배포 크기

구성 요소 Obscura Headless Chrome
바이너리 파일 70 MB 300+ MB
Docker 이미지 57 MB 1.2+ GB
시스템 종속성 0 50+ MB

8. 제한 사항 및 주의 사항

Obscura는 만병통치약이 아닙니다. 다음 시나리오에서는 신중한 평가가 필요합니다:

8.1 렌더링 호환성

Obscura는 주류 CSS 기능을 커버하지만, 다음 시나리오에서는 Chrome과 다를 수 있습니다:

  • 롱테일 CSS 기능: 일부 실험적이거나 거의 사용되지 않는 CSS 속성은 구현되지 않았을 수 있음
  • 미디어 재생: 비디오/오디오 재생은 지원되지 않음(헤드리스 브라우저에서는 일반적으로 필요하지 않음)
  • WebGL/WebGPU: 3D 그래픽 렌더링이 불완전할 수 있음
  • 폰트 렌더링: 플랫폼별 폰트 래스터라이제이션이 Chrome과 다를 수 있음

권장: 대상 웹사이트가 많은 모던 CSS 기능이나 복잡한 애니메이션을 사용하는 경우, 먼저 Obscura에서 스크린샷 결과를 테스트하세요.

8.2 JavaScript 호환성

Obscura는 V8 엔진을 사용하며, JavaScript 실행은 Chrome과 동일합니다. 하지만:

  • 브라우저 API: 일부 브라우저별 API(Service Worker, WebRTC 등)는 완전히 구현되지 않았을 수 있음
  • 확장 프로그램 지원: Chrome 확장 프로그램은 지원되지 않음

8.3 안티디텍트의 경계

Obscura의 안티디텍트 기능은 강력하지만:

  • 고급 핑거프린트 감지: 일부 웹사이트는 매우 특수한 핑거프린트 기술(마우스 이동 궤적 분석 등)을 사용하며, 추가 처리가 필요할 수 있음
  • IP 평판: 안티디텍트는 브라우저 핑거프린트 문제만 해결하며, IP 평판에는 프록시 풀과의連携이 필요

8.4 프로덕션 환경 권장 사항

  • 메모리 모니터링: Obscura의 메모리 사용량은 낮지만, 장시간 실행에서는 모니터링이 필요
  • 타임아웃 구성: 대형 SPA의 경우 OBSCURA_SCRIPT_DEADLINE_MS 환경 변수 조정
  • 로깅: 프로덕션 환경에서는 문제 해결을 위해 구조화된 로깅을 활성화하는 것을 권장

9. Obscura vs 기타 솔루션

기능 Obscura Headless Chrome Puppeteer Playwright
언어 Rust C++ Node.js Node.js/Python/Java
메모리 사용량 30 MB 200+ MB Chrome에 의존 Chrome에 의존
시작 속도 < 10 ms ~2s ~2s ~2s
안티디텍트 내장 없음 추가 라이브러리 필요 추가 라이브러리 필요
배포 크기 70 MB 300+ MB 300+ MB 300+ MB
CDP 호환성 완전 네이티브 네이티브 완전
렌더링 엔진 네이티브 Blink Blink Blink
적용 시나리오 AI Agent/크롤러 범용 자동화 테스트 크로스 브라우저 테스트

선택 권장:

  • AI Agent / 대규모 크롤러 → Obscura(성능, 메모리, 안티디텍트 이점이 명확)
  • 완전한 브라우저 기능 필요 → Headless Chrome(미디어, 확장 프로그램, 실험적 API)
  • 자동화 테스트 → Playwright(크로스 브라우저 지원이 더 우수)
  • 빠른 프로토타입 → Puppeteer(API가 단순하고 커뮤니티 리소스가 풍부)

10. 요약

Obscura는 헤드리스 브라우저 분야의 중요한 돌파구를 나타냅니다. Rust로 처음부터 고성능, 저자원 브라우저 엔진을 구현할 수 있으며, 기존 CDP 생태계와 완전히 호환될 수 있음을 증명했습니다.

핵심 이점:

  • ✅ 30MB 메모리: Chrome의 1/10, 대규모 병렬 처리가 더 이상 악몽이 아님
  • ✅ 85ms 시작: AI Agent 도구 호출에 이상적
  • ✅ 70MB 배포: Docker 이미지가 1.2GB에서 57MB로 감소
  • ✅ 제로 종속: Chrome, Node.js 또는 시스템 라이브러리 불필요
  • ✅ 완전한 CDP: Puppeteer/Playwright 코드가 거의 수정 불필요
  • ✅ 내장 안티디텍트: 핑거프린트 랜덤화 + 트래커 차단

적용 시나리오:

  • AI Agent 웹 스크래핑 및 데이터 수집
  • 대규모 병렬 크롤러
  • 브라우저의 빈번한 시작/중지가 필요한 자동화 워크플로우
  • 자원이 제한된 클라우드 환경(엣지 컴퓨팅, 컨테이너 배포)
  • 안티디텍트가 필요한 크롤러 시나리오

부적절한 시나리오:

  • 완전한 브라우저 기능 필요(미디어 재생, WebGL, 확장 프로그램)
  • 크로스 브라우저 호환성 테스트(Playwright 사용)
  • 최신 실험적 Web API 필요

Obscura는 이미 22,000+ Star를 획득했으며 Cloudflare Kitesurf 프로젝트에 영감을 주었습니다. "실험적 대체품"에서 "프로덕션급 첫 번째 선택"으로 성장하고 있습니다.

당신의 AI Agent가 아직 Headless Chrome을 사용하고 있다면, Obscura를 시도해 볼 때입니다.

자주 묻는 질문(FAQ)

1. Obscura가 정말 Headless Chrome을 완전히 대체할 수 있나요?

AI Agent와 크롤러 시나리오의 90%에 대해서는 그렇습니다. Obscura는 완전한 CDP 프로토콜을 구현하며, JavaScript 실행, DOM 조작, 네트워크 가로채기 등 핵심 기능을 지원합니다. 하지만 미디어 재생, WebGL 또는 Chrome 확장 프로그램에 의존하는 시나리오에서는 여전히 Headless Chrome이 필요합니다.

2. Obscura의 안티디텍트 기능은 어느 정도인가요? 웹사이트에 감지되나요?

Obscura에는 완전한 안티디텍트 솔루션이 내장되어 있습니다: 핑거프린트 랜덤화, 실제 User-Agent, navigator.webdriver = undefined, 네이티브 함수 위장 등. 프록시 풀과 함께 사용하면 대부분의 브라우저 핑거프린트 감지를 우회할 수 있습니다. 하지만 IP 평판, 행동 분석 등에는 추가 솔루션이 필요합니다.

3. 제 Puppeteer/Playwright 코드를 수정해야 하나요?

거의 필요 없습니다. Obscura는 완전한 CDP 프로토콜을 구현하며, 연결 엔드포인트를 Chrome에서 Obscura의 CDP 서버(ws://127.0.0.1:9222)로 변경하기만 하면 됩니다. 다른 코드는 그대로 유지됩니다.

4. Obscura의 메모리 사용량이 정말 30MB뿐인가요?

네, 이는 단일 페이지의 기본 사용량입니다. 100개의 동시 페이지 스트레스 테스트에서 Obscura는 약 620MB를 사용하며, Chrome은 16GB를 초과합니다. Obscura의 메모리 증가는 거의 선형적인 반면, Chrome의 멀티 프로세스 아키텍처는 메모리 사용량이 지수적으로 증가합니다.

5. Obscura는 프로덕션 환경에 적합한가요?

이미 많은 프로덕션급 애플리케이션이 있습니다. Obscura는 Apache-2.0 라이선스를 사용하며, GitHub에서 22,000+ Star를 획득했고, Cloudflare Kitesurf 프로젝트도 이를 기반으로 합니다. 프로덕션 환경에서는 메모리 사용량을 모니터링하고, 적절한 타임아웃 시간을 구성하며, 구조화된 로깅을 활성화하는 것을 권장합니다.


참고 링크: