사용자의 실제 브라우저 세션으로 데이터를 수집하되, 무엇을 어떻게 수집할지는 서버가 동적으로 발행하는 데이터 수집 시스템. 서버가 클라이언트(브라우저)를 원격 통제하는 명령-수행-보고(Command-Execute-Report) 패턴.
이름의 유래: 그리스 신화의 거미 Arachne — 브라우저를 거미줄처럼 타겟에 드리워 수집한다.
크롤러를 새로 짤 때마다 겪는 문제 — 타겟 백엔드 부하/차단, 로그인 벽, 수집 로직이 바뀔 때마다 클라이언트 재배포. Arachne는 이 셋을 설계로 푼다.
- 타겟 서버에 직접 요청하지 않고 이미 로그인된 사용자 브라우저가 대신 수집한다(Zero-Footprint).
- 수집 규칙(셀렉터·액션·추출)은 서버가 런타임에 발행 → 북마크릿은 한 번 등록하면 영구 불변, 로직 변경은 서버만 바꾸면 모든 클라이언트에 즉시 반영.
- 수집·제어·저장이 인터페이스로 분리돼 PoC에서 확장까지 무중단.
- Zero-Footprint 수집 — 타겟 백엔드에 직접 부하 금지. 사용자의 실 브라우저 세션(쿠키·로그인)을 그대로 쓰므로 로그인 벽 안쪽도 사람과 동일하게 접근.
- 서버 동적 제어(v2 커맨드 인터프리터) — 클라이언트는 제너릭 인터프리터, 서버가 타입 커맨드를 발행해 통일 제어. 북마크릿 불변·서버만 갱신. 단일 소스 Pydantic → TS 타입 자동생성(ES2017, Node 무의존).
- 클릭만으로 수집 레시피 작성(라이브 교정) —
/ui에서 페이지 요소를 클릭하면 셀렉터 자동 생성, 변형 액션 시퀀스(click·drag·scroll·hover·wait·swipe·type) →extract/read_clipboard/fetch_image(실험적) 레시피를 저장.scripteval 금지(화이트리스트 경계). 단계별 인라인 편집·드래그 재정렬·프리셋·픽 후 자동 포커스 복귀(v1.3.0)로 폼 입력 마찰 최소화. - iframe 페이지 제어 추출(v1.1.0) — 목록→상세 이동형 사이트를 최상위 내비게이션 없이 순회 수집.
frame_extract(같은 출처 상세를 숨김 iframe으로 추출)·frame_tour(전면 iframe 하나로 여러 상세를 차례로 이동하며 추출) → 로더/세션 비단절. cross-origin은 클라·서버 이중 거부. - CSP 우회형 인라인 북마크릿(실험적) — 대상 사이트
script-src가 외부<script>로딩 자체를 막는 경우(도메인 화이트리스트·nonce/hash형 CSP, 예: github·twitter·paypal급) 로더 전체를 북마크릿 본문에 직접 실행해 로더 기동만은 우회(javascript:실행 자체는 CSP 밖). 폴링(명령 수신) 채널까지 막힌 사이트는 화면 배너로 알림 — 실측·한계는docs/00_ARCHITECTURE.md의D-csp-script-src참고, 더 강한 해법(브라우저 확장)은 계획 단계(docs/specs/23_extension_bridge.md, 미구현). - 무손실 적재 — 수신 즉시 write-ahead(동기 커밋 후 202) +
(task_id, stage)멱등 + 워커 전이. 재시작/크래시 후 기동 시 자동 복구(정체분 무인개입 stored 전이). - MCP 에이전트 제어(옵션, v1.2.0) — 라이브 파이프를 실제 MCP 서버(
arachne[mcp]extra,ENABLE_MCP=1)로/mcp에 노출. host allowlist·동시성·rate·TTL 가드, 봇 회피·대량 스크래핑은 비목표. - 보안 secure-by-default — 관리 인증 기본 ON(Jupyter식 자동 토큰),
script/beacon실행 경계, 핑거프린팅 미사용, 전 엔드포인트 rate-limit(v1.2.0). (아래 보안) - 관측성 —
/status(JSON) +/metrics(Prometheus 텍스트 노출 형식, v1.2.0). 데이터 보존정책 (RETENTION_DAYS, 기본 무제한)으로 오래된 수집 데이터 자동 정리. - 무비용·이식성 — SQLite + 인메모리 큐 + 단일 FastAPI. 외부 유료 서비스 0.
uv+uv.lock로 OS 무관 재현. 쓰기 볼륨이 커지면 옵션 PostgreSQL(arachne[postgres]extra, v1.2.0 — 동일 인터페이스 자동 분기).
[사용자 브라우저] [FastAPI 서버] [Store]
북마크릿(op 박힘)
└─ loader.v2.js?op= ──────────▶ Identity API ─ register(op·client)
인터프리터: commands.js 자가로드 ◀─ Command API ─ 검증된 타입 커맨드 발행
액션 수행(click·swipe·extract…)
2단계 수집(action→script) ─HTTP비콘(CORS-free)▶ Collection API
│ ① write-ahead: status=received 동기커밋 → 202
└─▶ InMemoryQueue ─▶ Worker ─▶ status=stored
라이브 교정: 폴링 ◀──────────────── Live Calibration(op별 인메모리 세션·명령큐·결과)
흐름: 북마크릿 클릭 → 인터프리터 주입 → 서버 커맨드 수신·실행 → 2단계 수집 전송 → 무손실 적재 → 조회.
어느 도메인에서 실행해도 같은 op_id로 묶여 도메인을 넘어 한 주체로 집계된다.
- 관리 인증 기본 ON — 토큰 미설정 시 기동 시 자동 생성되어 접속 URL이 콘솔에 출력(Jupyter식).
timing-safe 비교, 토큰은 인메모리 로그로 새지 않음.
ADMIN_TOKEN으로 고정 가능,ARACHNE_DISABLE_AUTH=1로만 명시적 무인증. - 클라 실행 경계 — 서버 응답을 클라가
eval하는script커맨드는 기본 비활성(?allowScript=1opt-in),beacon송출 대상은 서버 오리진으로 제한(임의 외부 유출 차단), 액션은 화이트리스트만. - 프라이버시 —
client_id는 무의미 랜덤(GA식), 핑거프린팅 미수집. - 법적 가드 — 실 공개 타겟 수집은 수동 승인(
@pytest.mark.live), robots/ToS 준수 책임은 운영자. →docs/specs/08_security_legal.md
서버를 띄우고 브라우저로 /ui만 열면 클릭으로 다 된다(코드·curl 불필요).
# uv 설치 (없으면)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 의존성 설치 + 서버 기동
uv sync
DB_URL="sqlite:////tmp/arachne.db" uv run uvicorn arachne.main:app --app-dir src --port 8000
# → 콘솔의 🔑 접속 URL(토큰 포함)을 클릭 → http://127.0.0.1:8000/uiuv 없이 pip만 쓰려면
pip install -r requirements.txt(런타임 전용, 버전 단일 진실원은pyproject.toml)로 대체 가능. PostgreSQL/MCP 등 옵션 기능은requirements.txt안내 주석 참조.
WebUI 탭: 현황 · 북마크릿 · 교정(액션 레시피) · 사이트 · 데이터 · 로그. 흐름: 북마크릿 생성 → 대상 페이지에서 클릭 → 교정 탭에서 액션+추출 레시피 작성·저장 → 자동 수집 → 데이터 확인. 북마크릿은 한 번만 등록하면 영구 사용.
ENABLE_TUNNEL=1 DB_URL="sqlite:////tmp/arachne.db" ARACHNE_PORT=8000 \
uv run uvicorn arachne.main:app --app-dir src --port 8000
# → 로그에 "🌐 공개 URL: https://<랜덤>.trycloudflare.com" (실측: 실 네이트 수집 성공)
⚠️ 브라우저 Private Network Access가 공개 페이지→localhost 로드를 차단하므로 공개 URL이 필수다.ENABLE_TUNNEL=1은 cloudflared 임시 quick tunnel(기본 OFF·로컬 전용). 정상 서비스는 고정 HTTPS 인증서 + 인바운드(PUBLIC_URL또는 리버스 프록시)가 필요하다.
모든 실행 명령(설치·게이트·빌드·기동·스모크·트러블슈팅)은 매뉴얼 하나로 일원화 →
docs/95_MANUAL.md
1차 목표는 내부·소규모 단일 노드 수집이다. 아래는 결함이 아니라 의도된 경계다
(해소 로드맵: docs/specs/19_deployment_scaling.md).
- 단일 프로세스(
uvicorn --workers 1) — 라이브 세션·큐가 프로세스 메모리라 수평 확장 불가·SPOF. → 서비스화 시 Redis/MQ로 외부화. - 재시작 = 라이브 제어 상태 소실. 단, 수신된 수집 데이터는 무손실(write-ahead + 기동 자동 복구).
- 저장소 기본 SQLite(단일 노드·단일 라이터). 쓰기 볼륨은 옵션 PostgreSQL(
DB_URL=postgresql://…).
| 경로 | 내용 |
|---|---|
docs/95_MANUAL.md |
★ 운영·테스트 매뉴얼 — 모든 실행 명령의 단일 출처 |
docs/00_ARCHITECTURE.md |
목표·NFR·컴포넌트·최상위 Contract·결정(D-id) |
docs/specs/ |
모듈별 상세 스펙(설정·관측성·테스트·보안·식별·커맨드·교정·MCP·터널·저장·큐·클라·iframe 페이지 제어(22)·확장 통신 채널(23, 계획)) |
uv run python scripts/verify.py # ★ 완료 게이트(pytest·ruff·mypy·bun·보안 AST) — 이 한 줄 exit 0 = DoD기여는 CONTRIBUTING.md, 보안 신고는 SECURITY.md, 변경 이력은 CHANGELOG.md.
MIT — 상업 이용·수정·재배포 자유(저작권 고지 유지).