TRENDSHIFT WEEKLY #23 · 2026.05.24 · CLOAKHQ

CloakBrowser
Playwright와 한 줄만 바꾸면 봇 탐지 30/30 통과

웹 자동화 세계의 오랜 골칫거리: "내가 봇이 아니라고 증명해야 한다". CloakBrowser는 Chromium 소스 코드를 C++ 레벨에서 직접 패치해 컴파일한 스텔스 브라우저로, 스톡 Playwright에서 import 한 줄만 바꾸면 reCAPTCHA v3에서 0.9점(사람 수준)을 받고 Cloudflare Turnstile을 통과한다. JS 인젝션이나 플래그 트릭에 의존하는 기존 스텔스 라이브러리와 근본적으로 다른 접근.

1프로젝트 한줄 요약

무엇을 하는 프로젝트인가.

핵심 메시지

"CloakBrowser는 Chromium의 소스 코드를
다시 컴파일한 '진짜로 사람처럼 보이는' 브라우저다."

기존 스텔스 도구들은 자바스크립트를 주입하거나 시작 플래그를 바꿔서 봇처럼 보이는 흔적을 가린다. CloakBrowser는 그게 아니라, Chromium의 C++ 코드를 58곳 고쳐서 빌드한 나만의 Chromium 바이너리를 다운로드해 사용한다. 탐지 사이트가 "당신은 봇인가요?"라고 물어볼 때, JS로 거짓말을 하는 게 아니라 처음부터 사람 브라우저가 되어 있다는 게 핵심이다.

그러면서도 사용자 입장에서는 from playwright.sync_api import sync_playwright 한 줄을 from cloakbrowser import launch로 바꾸기만 하면 끝. 나머지 코드는 그대로 동작한다.

용어
Playwright (플레이라이트, 마이크로소프트의 브라우저 자동화 라이브러리)
코드로 Chrome/Firefox/Safari를 띄우고 클릭·입력·스크린샷·테스트를 수행하는 도구. 셀레니움(Selenium)의 후속 격으로, 웹 스크래핑·E2E 테스트·자동 폼 제출에 표준처럼 쓰인다. CloakBrowser는 이 Playwright의 API를 그대로 두고 안에서 굴리는 브라우저만 갈아끼운 것.
용어
Stealth Browser (스텔스 브라우저, 봇 탐지 회피용 브라우저)
자동화 봇이 띄운 브라우저는 사람이 띄운 브라우저와 미묘하게 다른 흔적(navigator.webdriver = true, 헤드리스 모드 UA, 빈 플러그인 목록 등)을 남긴다. 이 흔적을 지워서 "사람이 직접 띄운 Chrome"처럼 보이게 만든 브라우저가 스텔스 브라우저. 군용 스텔스기처럼 레이더에 잘 안 잡힌다는 비유.

2왜 주목받는가

트렌딩 이유, 경쟁 제품 대비 장점.

2026년 5월 셋째 주 TrendShift 주간 23위. 스타 수는 32개로 절대값은 작지만, 경쟁 도구들이 차례로 죽거나 무력화된 빈 자리에 들어왔다는 게 핵심이다. 5년 가까이 사실상 표준이었던 도구들의 종말을 정리해보면:

0.9
reCAPTCHA v3 점수 (사람 수준)
30/30
스텔스 탐지 테스트 통과
58
C++ 소스 레벨 패치 수
~200MB
자동 다운로드되는 바이너리 크기
함정 (기존 스텔스 도구의 한계)
"설정 레벨 패치는 Chrome 업데이트마다 깨진다"

playwright-stealth, undetected-chromedriver, puppeteer-extra는 모두 자바스크립트를 주입하거나 시작 플래그를 조정해서 흔적을 가린다. Chrome이 업데이트될 때마다 패치 위치가 바뀌어 안 먹히고, 안티봇 회사들은 "패치가 적용된 흔적 자체"를 탐지한다. 또 가장 유망했던 Camoufox는 Firefox를 패치한 프로젝트였는데 2025년 초 잠시 중단됐다가 2026년 초 불안정 베타로 복귀했다.

해결책 (CloakBrowser의 접근)
C++ 소스를 다시 컴파일한 Chromium 바이너리

지문(fingerprint)을 만들어내는 코드 자체를 58곳 고쳐서 빌드했다. 탐지 사이트가 검사할 때 보이는 값은 처음부터 진짜 Chrome과 동일하다. JS 주입이 아니라 "처음부터 다르게 만든 Chrome"이라 패치 흔적을 검출할 수 없다. TLS 핸드셰이크의 ja3n/ja4 지문도 진짜 Chrome과 일치한다.

경쟁 제품 비교

도구reCAPTCHA v3패치 레벨유지보수엔진
Stock Playwright0.1 (봇)없음활발Chromium
playwright-stealth0.3~0.5JS 주입정체Chromium
undetected-chromedriver0.3~0.7플래그정체Chrome
Camoufox0.7~0.9C++ (Firefox)Unstable beta (2026년 복귀)Firefox
CloakBrowser0.9C++ (Chromium)활발Chromium

주목할 점은 Camoufox의 "Firefox 자리"가 비었다는 것. Firefox는 Playwright 지원도 제한적이고 시장 점유율도 낮아 TLS 지문 자체가 봇 의심을 산다. Chromium은 그 자체로 시장 점유율 65%를 넘는 일반 브라우저라, TLS·HTTP/2·QUIC 핸드셰이크가 정상 트래픽의 바닷속에 묻힌다.

3기술 스택 전체 지도

백엔드 / 프론트엔드 / 인프라 각각.

코어 (Python 패키지 + Chromium 바이너리)

바이너리 (가장 핵심)

Chromium 146 + 58 source-level patches

이 프로젝트의 "진짜 자산"은 GitHub 저장소의 Python 코드가 아니라 GitHub Releases에 호스팅된 약 200MB짜리 패치된 Chromium 바이너리다. Chromium은 C++ 약 3,500만 줄짜리 거대한 코드베이스인데, 그중 58곳을 수정하고 Linux x64용으로 다시 빌드했다.

패치 대상: Canvas 지문 생성, WebGL 렌더러 출력, 오디오 처리 지문, 폰트 열거 결과, 하드웨어 동시성 보고, Client rect 측정, GPU 벤더/렌더러 문자열, WebDriver 플래그, 헤드리스 탐지 신호 등.
래퍼 (사용자가 install하는 것)

Python + TypeScript 래퍼 (이중 언어 구성)

저장소는 Python(~53%)과 TypeScript(~43%)의 혼합 구성이다. Python 래퍼(pip install cloakbrowser)와 JS/Node.js 래퍼(npm install cloakbrowser)를 모두 정식 지원한다. Playwright뿐 아니라 Puppeteer 등 Node.js 환경에서도 동일하게 사용할 수 있다. 역할은 ① 패치된 Chromium 바이너리를 GitHub Releases에서 자동 다운로드·캐시, ② Playwright/Puppeteer를 그 바이너리로 실행시키는 얇은 wrapper, ③ HumanConfig로 마우스·키보드 동작에 사람 같은 미세한 흔들림 추가(옵션).

의존성과 옵션

분류패키지역할
핵심playwright>=1.40브라우저 자동화 API
핵심httpx>=0.24바이너리 다운로드용 HTTP 클라이언트
옵션 (geoip)geoip2, socksio프록시 IP의 시간대·언어 자동 매칭, SOCKS5 지원
옵션 (patchright)patchright>=1.40패치된 Playwright 변종 (추가 우회용)
옵션 (serve)aiohttp, websockets원격 브라우저 서버 모드 (Docker 컨테이너에 띄워두기)

빌드/배포 (인프라)

용어
hatchling (해츨링, Python 패키지 빌드 백엔드)
전통적으로 Python 패키지는 setup.py로 빌드했는데, 최근에는 PEP 517 표준을 따르는 빌드 백엔드를 쓴다. hatchling은 그 표준 백엔드 중 하나. pyproject.toml에 메타데이터만 적으면 알아서 빌드/배포 가능. CloakBrowser는 [build-system]에서 hatchling을 명시.
Docker 이미지

python:3.12-slim 베이스 + 50여 개 시스템 라이브러리

Dockerfile이 흥미롭다. Chromium을 띄우려면 libnss3, libgbm1, libatk1.0-0 등 그래픽·폰트·오디오 관련 시스템 라이브러리가 30개 이상 필요하다. 거기에 xvfb(가상 디스플레이)와 xdotool(헤드드 모드 자동화), Node.js 20(JS 래퍼용)까지 깐다.

핵심 최적화는 빌드 타임에 ensure_binary()를 호출해 200MB Chromium을 미리 다운로드한다는 점. 런타임에 다운받으면 컨테이너 첫 실행이 1~2분 멈춰버리는데, 빌드에 넣으면 이미지가 무거워지는 대신 시작이 즉시 된다.

배포 채널

PyPI + GitHub Releases (바이너리만 별도)

Python 패키지는 pip install cloakbrowser로 PyPI에서 가져오고, 무거운 Chromium 바이너리는 cloakbrowser 패키지가 처음 실행될 때 GitHub Releases에서 다운로드해 ~/.cloakbrowser에 캐시한다. 환경변수로 다운로드 URL이나 바이너리 경로를 오버라이드할 수 있어 사내 미러를 두기도 쉽다.

4아키텍처 심화 분석

시스템 구조도 + 핵심 설계 패턴.

전체 데이터 흐름

┌──────────────────────────────────────────────────────────────┐ │ 사용자 코드 (your_script.py) │ │ │ │ from cloakbrowser import launch │ │ browser = launch() │ │ page = browser.new_page() │ │ page.goto("https://protected-site.com") │ └─────────────────────────┬────────────────────────────────────┘ │ launch() ▼ ┌──────────────────────────────────────────────────────────────┐ │ cloakbrowser/__init__.py (얇은 래퍼) │ │ - 바이너리 경로 확인 (없으면 다운로드) │ │ - 기본 stealth 플래그 조립 │ │ - HumanConfig(옵션) 적용 │ └─────────────────────────┬────────────────────────────────────┘ │ subprocess ▼ ┌──────────────────────────────────────────────────────────────┐ │ Playwright (마이크로소프트 라이브러리) │ │ - executable_path = 패치된 Chromium 바이너리 │ │ - CDP (Chrome DevTools Protocol) 로 브라우저 제어 │ └─────────────────────────┬────────────────────────────────────┘ │ stdin/stdout pipe ▼ ┌──────────────────────────────────────────────────────────────┐ │ ★ 패치된 Chromium 바이너리 (~200MB) │ │ │ │ C++ 패치 58곳: │ │ ┌────────────┐ ┌──────────────┐ ┌─────────────────────┐ │ │ │ Canvas 지문│ │ WebGL 렌더러 │ │ navigator.webdriver │ │ │ └────────────┘ └──────────────┘ └─────────────────────┘ │ │ ┌────────────┐ ┌──────────────┐ ┌─────────────────────┐ │ │ │ 오디오 지문│ │ 폰트 열거 │ │ window.chrome │ │ │ └────────────┘ └──────────────┘ └─────────────────────┘ │ │ ┌────────────┐ ┌──────────────┐ ┌─────────────────────┐ │ │ │ 하드웨어 │ │ GPU 벤더 │ │ TLS ja3n/ja4 지문 │ │ │ └────────────┘ └──────────────┘ └─────────────────────┘ │ └─────────────────────────┬────────────────────────────────────┘ │ 네트워크 요청 ▼ ╔══════════════════════╗ ║ 봇 탐지 시스템 ║ ║ (reCAPTCHA, CF, ║ ║ FingerprintJS,...) ║ ║ ║ ║ "사람이네요" ✓ ║ ╚══════════════════════╝

핵심 설계 패턴 1: 패치 레이어의 위치

봇을 숨기는 코드는 어디에 있을 수 있을까. CloakBrowser가 다른 도구와 갈라지는 결정적 차이가 이 위치다:

방법 위치 탐지 난이도 업데이트 영향 ──────────────────────────────────────────────────────────────── JS 인젝션 브라우저 안 쉬움 높음 (자주 깨짐) 시작 플래그 실행 시점 중간 중간 CDP 메소드 가로채기 자동화 레이어 중간 중간 ★ C++ 소스 패치 Chromium 빌드 매우 어려움 거의 없음

JS 인젝션은 navigator.webdriver 같은 속성을 Object.defineProperty로 덮어쓰는 식인데, 탐지 사이트는 "속성 정의가 native 코드인지, JS로 정의된 건지"를 검사해서 패치 흔적을 찾아낸다. 반면 C++ 소스에서 패치하면 정의 자체가 native라서 구분이 불가능하다.

핵심 설계 패턴 2: 바이너리/래퍼 분리

저장소 코드는 가볍게(~20KB Python), 진짜 자산은 무겁게(200MB 바이너리). 이 분리 덕분에:

핵심 설계 패턴 3: Drop-in Replacement (대체 가능 인터페이스)

비유

전구를 교체할 때 백열등을 LED로 바꿔도 소켓이 같으니 그대로 끼울 수 있는 것처럼, CloakBrowser는 Playwright와 똑같은 함수 시그니처(launch(), new_page(), goto() ...)를 제공한다. 기존 코드 한 줄(import)만 바꾸면 된다.

이건 단순한 편의성이 아니라 채택 마찰을 0에 가깝게 낮추는 전략이다. 회사가 이미 만들어둔 수백 줄짜리 Playwright 스크립트를 통째로 재작성할 필요가 없다.

5디렉토리 구조 해부

주요 폴더/파일의 역할.

CloakBrowser/ ├── cloakbrowser/ ← Python 패키지 본체 (사용자가 import하는 것) │ ├── __init__.py ← launch / launch_async / HumanConfig export │ ├── __main__.py ← CLI 진입점 (python -m cloakbrowser) │ ├── browser.py ← 실제 Playwright 실행 로직 │ ├── config.py ← 기본 stealth 인수 빌더, CHROMIUM_VERSION 상수 │ ├── download.py ← 바이너리 자동 다운로드/캐시 │ ├── geoip.py ← IP 기반 시간대·언어 매칭 (geoip 옵션) │ ├── widevine.py ← Widevine DRM 지원 │ ├── _version.py ← 동적 버전 (hatchling이 읽음) │ └── human/ │ └── config.py ← 사람 같은 마우스/키보드 동작 (lazy import) ├── examples/ ← 사용 예시 │ ├── basic.py ← Launch and load │ ├── recaptcha_score.py ← reCAPTCHA v3 점수 확인 │ ├── stealth_test.py ← 탐지 서비스 통과 테스트 │ ├── fingerprint_scan_test.py ← 지문 스캔 테스트 │ ├── persistent_context.py ← 영구 컨텍스트 예시 │ └── integrations/ ← 외부 도구 연동 예시 ├── tests/ ← pytest 테스트 (slow 마커로 라이브 테스트 분리) ├── images/ ← README용 스크린샷 (reCAPTCHA 0.9 증거 등) ├── bin/ ← 바이너리/스크립트 보조 파일 ├── Dockerfile ← Linux 컨테이너 (xvfb로 헤드드 모드도 지원) ├── pyproject.toml ← hatchling 빌드, optional-deps 4종 ├── flake.nix ← Nix 패키지 정의 ├── flake.lock ← Nix 의존성 잠금 파일 ├── CHANGELOG.md ← 버전별 변경 이력 ├── BINARY-LICENSE.md ← 패치된 Chromium 바이너리 라이선스 ├── .gitattributes ├── .gitignore ├── README.md ← 핵심 마케팅·기술 문서 (벤치마크 표 포함) └── LICENSE (MIT) # 별도로 GitHub Releases에 호스팅 (Git에는 없음): ~/.cloakbrowser/ ← 사용자 캐시 └── chromium-146.0.7680.177/ ← 200MB 패치된 바이너리

주목할 만한 디자인 선택

선택 1

__getattr__를 통한 지연 임포트

cloakbrowser/__init__.py를 보면 HumanConfig는 모듈 최상단에서 import하지 않고 __getattr__ 훅 안에서 import한다. Python 3.7+의 모듈 레벨 __getattr__ 기능. 이러면 HumanConfig가 필요 없는 사용자는 그 코드를 메모리에 안 올린다.

def __getattr__(name): if name == "HumanConfig": from .human.config import HumanConfig globals()["HumanConfig"] = HumanConfig return HumanConfig
선택 2

Optional dependencies로 기능 분할

pip install cloakbrowser[geoip]처럼 대괄호로 추가 기능을 선택 설치. geoip(IP 기반 시간대 매칭), patchright(추가 우회), serve(원격 브라우저 서버), dev(테스트). 사용자는 자기가 필요한 만큼만 무겁게 만든다.

선택 3

버전 문자열을 코드와 분리 (_version.py)

pyproject.toml[tool.hatch.version] path = "cloakbrowser/_version.py"가 핵심. 릴리스 자동화 스크립트가 _version.py 한 줄만 고치면 패키지 버전이 바뀐다. 메인 코드는 건드리지 않는다.

6학습 포인트 (기술별)

각 기술에서 배울 것 + 실습 아이디어.

1) Playwright 자체에 익숙해지기 (가장 기초)

CloakBrowser는 Playwright의 얇은 wrapper다. 그러니 Playwright를 모르면 이 도구를 써도 의미가 없다. Sync APIAsync API 두 가지가 있다. 동시에 여러 페이지를 띄울 거면 async, 한 페이지 한 페이지 순차 처리면 sync로 충분.

용어
CDP (Chrome DevTools Protocol, 크롬 개발자 도구 프로토콜)
Chrome 개발자 도구가 브라우저 내부와 통신할 때 쓰는 JSON-RPC 기반 프로토콜. Playwright와 Puppeteer는 이 프로토콜로 브라우저를 원격 조작한다. navigator.webdriver = true가 켜지는 것도 CDP 연결 때문. CloakBrowser는 이 신호 자체를 C++에서 끈다.

실습 아이디어: 본인 블로그를 Playwright로 열고 첫 화면 캡처 → 같은 코드를 CloakBrowser로 바꿔서 다시 실행. 두 스크린샷을 비교해 본인이 만든 페이지가 두 환경에서 똑같이 보이는지 확인.

2) 봇 탐지의 작동 원리

탐지 사이트가 어떤 신호를 보는지 알면 회피하려는 시도도 이해가 된다. 주요 신호 7가지:

신호스톡 PlaywrightCloakBrowser
navigator.webdrivertruefalse
navigator.plugins.length05
window.chromeundefined실제 객체
User-AgentHeadlessChromeChrome/142.0.0.0
Canvas 지문유니크일반 Chrome과 같음
TLS ja3n 지문node.js 클라이언트실제 Chrome
WebGL 렌더러SwiftShader일반 GPU 문자열

실습 아이디어: https://bot.sannysoft.com이나 https://browserscan.net을 Playwright로 방문해 결과를 캡처 → CloakBrowser로 다시 방문해 비교. "탐지 사이트가 어떤 항목을 어떻게 검사하는가"가 표 한 장에 정리된다.

3) Chromium 빌드 시스템 (어렵지만 가장 큰 보상)

CloakBrowser의 진짜 마법은 Chromium 소스를 빌드하는 데 있다. Chromium 코드 받기, GN 빌드 설정, 패치 적용, ninja 컴파일은 큰 학습 곡선이지만 한 번 익히면 평생 자산이다.

함정
"하드웨어 요구사항이 가볍지 않다"

Chromium 풀빌드는 16GB RAM, 100GB+ 디스크, 멀티코어 CPU로도 1~3시간 걸린다. 패치된 빌드만 매번 만들 일이 아니라면 GitHub Actions 같은 CI에서 한 번씩 돌리는 게 현실적.

실습 아이디어: 작은 패치 하나만 해보기. 예: navigator.webdriver를 항상 false로 만드는 한 줄 C++ 변경 → 빌드 → 같은 탐지 페이지에서 결과 확인. 빌드만 성공해도 큰 성취다.

4) Python 패키지 배포 모범 사례

CloakBrowser의 pyproject.toml은 현대적 Python 패키지의 좋은 본보기다:

5) Docker로 무거운 의존성 다루기

Chromium은 30개 이상의 시스템 라이브러리를 요구한다. CloakBrowser의 Dockerfile은 이것들을 한 번에 정리한 좋은 참고 자료다. 특히 "빌드 타임에 무거운 다운로드 미리 끝내기" 패턴이 인상적.

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

실제로 돌리려면 무엇이 필요한가.

사용 환경 (CloakBrowser 실행)

항목최소권장
Python3.93.12+
OSLinux x86_64Linux x86_64 (macOS arm64 베타, Windows 예정)
RAM2GB4GB+ (페이지를 여러 개 띄울 거면)
디스크500MB~1GB (200MB 바이너리 + 캐시)
네트워크최초 200MB 다운로드 가능안정적 회선 + (선택) 주거용 프록시

현재 시점에서 큰 제약은 플랫폼이 Linux x86_64만 정식 지원이라는 것. macOS arm64(M1/M2/M3)와 Windows는 로드맵에 있다. Apple Silicon 사용자는 Docker로 Linux 컨테이너 띄워서 쓰는 게 임시 해법.

빌드 환경 (직접 Chromium 패치하려면)

함정
"가벼운 노트북으로는 불가능"

Chromium 풀빌드는 사실상 워크스테이션이 필요하다. 16코어 CPU + 32GB RAM + SSD 100GB 비어 있어도 첫 빌드는 1~2시간. M1 Pro MacBook으로도 비슷한 시간. 빌드 캐시(ccache, goma)를 잘 쓰면 두 번째부터는 30분 이내.

항목요구사항
CPU8코어+ (16코어 권장)
RAM16GB+ (링커가 OOM 잘 일으킴, 32GB 권장)
디스크100GB+ 여유 (Chromium 소스 + 빌드 산출물)
네트워크최초 fetch에 ~30GB 다운로드
OSLinux 권장 (depot_tools가 가장 안정적)
도구depot_tools, GN, ninja, Python 3, git

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

난이도별 5단계.

난이도 ★ (30분)

실습 1. 기본 비교 — 같은 페이지를 두 방식으로 열어보기

먼저 pip install playwrightplaywright install chromium으로 표준 환경 준비. browserscan.net을 띄우고 결과 캡처. 그 다음 pip install cloakbrowser로 CloakBrowser 설치, 같은 페이지를 띄워 캡처. 두 결과를 좌우로 놓고 어떤 항목이 어떻게 바뀌었는지 표로 정리.

목표: 봇 탐지 사이트가 어떤 신호를 검사하는지 직접 눈으로 보기.
난이도 ★★ (1~2시간)

실습 2. reCAPTCHA v3 점수 자동 모니터링

examples/recaptcha_score.py를 베이스로, 다양한 사이트(Google 자체 데모, 본인이 운영하는 사이트 등)에서 점수를 측정하는 스크립트를 작성. 결과를 CSV로 저장하고, 시간대별·페이지별로 점수가 어떻게 변하는지 1주일간 모니터링.

목표: "스텔스 효과가 실제로 얼마나 안정적인가"를 데이터로 확인.
난이도 ★★★ (반나절)

실습 3. HumanConfig로 사람 같은 동작 추가

기본 CloakBrowser는 지문은 가리지만 "1초에 정확히 다섯 번 클릭" 같은 비인간적 동작 패턴은 안 막는다. HumanConfig를 적용해 마우스 이동을 곡선으로, 클릭 사이 간격을 가우시안 분포로, 타이핑 속도를 단어별로 다르게 만들기. FingerprintJS의 행동 분석 페이지에서 점수 변화 측정.

난이도 ★★★★ (1~2일)

실습 4. Docker 컨테이너로 원격 브라우저 서버 띄우기

[serve] 옵션 설치 후 cloakserve 명령으로 원격 CDP 서버를 띄운다. 별도 머신에서 Playwright 클라이언트가 connect_over_cdp로 연결해서 사용하는 구조. 여러 봇 작업자가 한 브라우저 풀을 공유할 수 있다. 라즈베리파이 4 같은 작은 서버에서 컨트롤러를, 강력한 클라우드 인스턴스에서 브라우저를 굴리는 분리 구조 실험.

난이도 ★★★★★ (1~2주)

실습 5. 자체 Chromium 패치 빌드

Google의 "Get the Code" 가이드를 따라 Chromium 소스 받기 → third_party/blink/renderer/core/frame/navigator.ccwebdriver() 함수를 return false로 한 줄 수정 → 빌드 → 패치된 바이너리를 CLOAKBROWSER_BINARY_PATH로 지정해 CloakBrowser 래퍼와 함께 사용. 이게 되면 CloakBrowser의 모든 마법이 어떻게 작동하는지 완전히 이해한 것.

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

주차별 학습 계획.

1주차 — Playwright 기초

Sync API로 5개 사이트 자동화

Playwright 공식 튜토리얼 끝까지 따라하기. page.locator(), page.fill(), page.click(), page.wait_for_selector() 핵심 5개 메소드를 손에 익히기. 본인이 자주 가는 사이트 5곳을 자동으로 여는 스크립트 작성.

2주차 — 봇 탐지의 작동 원리

FingerprintJS·CreepJS 소스 읽기

FingerprintJS의 오픈소스 코어를 읽어보면 "어떤 JS API를 호출해서 어떤 값을 모아 해시를 만드는가"가 보인다. CreepJS도 비슷한 컨셉. 이걸 알면 어떤 신호를 가려야 하는지 직관이 생긴다.

3주차 — TLS/HTTP 지문 (ja3, ja4)

네트워크 레벨 지문 이해

탐지는 JS만으로 하는 게 아니다. TLS 핸드셰이크의 cipher suite 순서, HTTP/2 SETTINGS 프레임 순서, ALPN 순서 등이 클라이언트별로 다르다. ja3, ja3n, ja4가 이걸 해시화한 표준. Wireshark로 직접 캡처해 보기.

4주차 — CDP (Chrome DevTools Protocol)

Playwright 없이 raw CDP 다뤄보기

Chromium을 --remote-debugging-port=9222로 띄우고 직접 WebSocket으로 CDP 메시지를 주고받기. Page.navigate, Runtime.evaluate 같은 메소드를 손으로 호출해보면 Playwright가 내부에서 뭘 하는지 보인다.

5~6주차 — Chromium 빌드 시스템

depot_tools, GN, ninja

Google이 만든 빌드 도구 체인. fetch chromium, gclient sync, gn gen out/Default, autoninja -C out/Default chrome. 첫 빌드 성공이 목표. 한 번만 성공하면 그다음은 익숙해진다.

7~8주차 — Blink 렌더링 엔진 구조

Web IDL → C++ 매핑

navigator.webdrivernavigator.idl에 선언되고 navigator.cc에 구현된다. Blink가 IDL을 어떻게 C++로 바인딩하는지 알면 어떤 JS API든 C++ 레벨에서 수정할 수 있다. 이게 CloakBrowser의 58개 패치가 작동하는 원리.

9주차+ — 응용 (선택)

본인의 봇 우회 도구 만들어보기

여기까지 오면 본인이 직접 작은 스텔스 도구를 만들 수 있다. 1개 패치 + 1개 Python 래퍼 + Docker. CloakBrowser와의 차이는 58개 패치 vs 1개 패치의 정도 차이일 뿐, 본질은 같다.

10핵심 키워드 사전

프로젝트에 등장하는 주요 기술 용어.

용어 1
Fingerprinting (지문 채취, 브라우저 지문)
쿠키 없이도 같은 브라우저를 알아보는 기술. Canvas 그림 그리기 결과, WebGL 렌더링 결과, 폰트 목록, 화면 해상도 등 수십 가지 신호를 조합해 해시값을 만든다. 같은 사용자가 다른 사이트에 가도 추적이 가능. CloakBrowser는 이 지문 생성 결과를 "일반 Chrome처럼 보이게" 만든다.
용어 2
reCAPTCHA v3 (Google의 비대면형 봇 점수 시스템)
v2가 "신호등 사진 고르기"라면 v3는 사용자 모르게 0.0~1.0 점수를 매겨 서버에 알려준다. 0.0=확실한 봇, 1.0=확실한 사람. 사이트 운영자는 점수가 낮으면 차단하거나 추가 인증을 요구한다. CloakBrowser의 0.9점은 일반 Chrome으로 사람이 직접 방문한 수준.
용어 3
Cloudflare Turnstile (클라우드플레어의 reCAPTCHA 대체품)
2022년 출시된 Cloudflare의 비-인터랙티브 캡차. 사용자가 아무것도 안 해도 백그라운드에서 브라우저를 검증한다. "managed" 모드는 의심스러우면 한 번 클릭을 요구하고, "non-interactive"는 완전 자동. CloakBrowser는 둘 다 통과.
용어 4
ja3n / ja4 (TLS 핸드셰이크 지문 알고리즘)
클라이언트가 TLS 핸드셰이크를 시작할 때 보내는 ClientHello 메시지의 cipher suite 순서, extension 종류, supported groups를 해시화한 식별자. 같은 Python 스크립트라도 requests, httpx, Chrome이 모두 다른 ja3n을 가진다. CloakBrowser는 ja3n/ja4를 실제 Chrome과 일치하게 만든다.
용어 5
Headless mode (헤드리스 모드, 화면 없이 띄우는 브라우저)
자동화·서버 환경에서 GUI 없이 백그라운드로 브라우저를 실행. 빠르고 가볍지만 옛 Chrome은 UA에 HeadlessChrome이라고 표시해 한눈에 봇임이 들통났다. 새 헤드리스(--headless=new)는 거의 일반 모드와 같지만, 일부 미세한 차이가 남는다.
용어 6
depot_tools (Google의 Chromium 개발 도구 모음)
fetch, gclient, gn, git-cl 등 Chromium 소스를 받고 빌드하고 리뷰하는 데 필요한 모든 명령을 묶은 Python 도구 모음. Chromium 소스 안에 포함되지 않는 외부 도구. 패치된 Chromium 빌드의 첫 단추.
용어 7
GN / Ninja (Chromium의 빌드 시스템 2종)
GN은 빌드 설정 언어(Generate Ninja files), Ninja는 실제 컴파일러를 호출하는 빠른 빌드 도구. Makefile/CMake의 Google식 대체품. Chromium처럼 500만+ 파일이 되면 일반 빌드 시스템은 너무 느려진다.
용어 8
CDP (Chrome DevTools Protocol)
앞에서 한 번 언급. Playwright, Puppeteer, 셀레니움의 일부 드라이버가 모두 이걸로 Chromium을 원격 조작한다. WebSocket 위에 JSON-RPC. 도메인별로 메소드가 묶여 있다(Page, Runtime, Network, Target, ...). CloakBrowser는 CDP 연결 자체로 인한 봇 흔적도 C++에서 가린다.
용어 9
Xvfb (X Virtual Framebuffer, 가상 디스플레이)
Linux 서버처럼 모니터가 없는 환경에서 X 윈도우 애플리케이션을 메모리상의 가상 디스플레이로 띄우는 도구. 헤드드(headed) 모드 브라우저를 서버에서 돌릴 때 필수. CloakBrowser Dockerfile이 xvfb를 까는 이유.
용어 10
SOCKS5 (소켓 보안 프로토콜 v5, 프록시 표준)
HTTP 프록시는 HTTP 트래픽만 처리하지만 SOCKS5는 TCP/UDP 모든 트래픽을 중계한다. 스크래핑/봇 워크로드에서 주거용 IP 프록시를 쓸 때 흔히 SOCKS5 형식. CloakBrowser의 [geoip] 옵션 의존성에 socksio가 들어가는 이유.

11참고 링크

더 깊이 파고들 자료들.

실용 가이드

지금 당장 시도해볼 만한 5가지

  1. browserscan.net에 표준 Playwright로 한 번, CloakBrowser로 한 번 방문. 결과 캡처해서 좌우 비교. 5분이면 끝나고, 봇 탐지가 어떤 신호를 보는지가 표 한 장으로 정리된다.
  2. pip install cloakbrowser로 설치해보기. Linux 환경(또는 Docker)이 있으면 첫 다운로드 후 examples/basic.py를 그대로 실행. ~/.cloakbrowser/ 안에 무엇이 생기는지 확인.
  3. Playwright 첫 자동화 스크립트 작성. 본인 블로그나 자주 가는 사이트의 제목을 자동으로 가져오는 30줄짜리 스크립트. CloakBrowser를 쓰든 안 쓰든 자동화의 기본은 동일.
  4. Dockerfile 한 줄씩 따라 읽기. 30개 시스템 라이브러리가 왜 필요한지 검색하면서 정리. Chromium을 컨테이너에서 안전하게 굴리는 보일러플레이트가 손에 들어온다.
  5. Chromium 소스를 받는 것까지만 해보기. 풀빌드는 안 해도 좋다. fetch chromium으로 30GB 받고 src/third_party/blink/renderer/core/frame/navigator.cc 열어서 webdriver() 함수 한 번 들여다보기. CloakBrowser가 정확히 무엇을 고치는지 한눈에 보인다.
원문 · CloakHQ/CloakBrowser GitHub, 2026.06 (Chromium 146 기준) · github.com/CloakHQ/CloakBrowser
공부자료 · TrendShift 주간 23위 딥다이브, 2026.05.24 작성