launch() 한 줄이지만, 속을 열어보면 라이선스 서버 호출, Ed25519 서명 검증, 좌석(세션) 수 관리, 플랫폼×버전별 기능 매트릭스까지 갖춘 소규모 SaaS 인프라가 자리 잡고 있다.
무료 티어는 Chromium 146(58패치, macOS는 145/26패치)에 멈춰 있고, Pro 구독자만 최신 Chromium 150(71패치, 전 플랫폼)을 받는다 — "오픈 코어(open core)" 비즈니스 모델의 교과서적인 사례로 다시 읽을 가치가 있다.
이 문서는 2026-05-24 작성된 이전 버전을 완전히 대체한다 — 같은 파일명, 최신 소스(git clone --depth 1, 2026-07-18 커밋 fd2b602 / v0.4.12) 기준으로 전면 재작성했다.
여전히 from cloakbrowser import launch 한 줄이면 Playwright/Puppeteer가 패치된 Chromium 바이너리로 뜬다. 지문(fingerprint)을 만드는 코드 자체가 C++ 소스 레벨에서 수정돼 있어 navigator.webdriver, Canvas, WebGL, 오디오, TLS 핸드셰이크까지 진짜 Chrome과 구분이 안 된다는 핵심 원리는 그대로다.
달라진 건 그 바이너리가 이제 두 갈래로 나뉜다는 점. 무료 사용자는 몇 주 전 빌드(Chromium 146, 58패치)를 받고, CLOAKBROWSER_LICENSE_KEY를 설정한 Pro 구독자만 최신 빌드(Chromium 150, 71패치)를 받는다. 래퍼 코드(Python·JS·.NET) 자체는 여전히 MIT로 전부 공개돼 있다 — 유료화된 건 "코드"가 아니라 "최신 바이너리를 받을 권리"다.
이전 분석(2026-05-24) 당시 CloakBrowser는 별 32개짜리 신생 프로젝트였다. 지금 GitHub API로 다시 조회하면(2026-07-19 기준) 스타 20,323개, 포크 1,610개, 열린 이슈 86개다. 두 달 사이 별이 600배 넘게 늘었다는 뜻인데, 소스를 뜯어보면 그 사이 실제로 일어난 일이 숫자만큼이나 크다는 걸 알 수 있다.
| 지표 | 2026-05-24 (이전 분석) | 2026-07-19 (현재) |
|---|---|---|
| GitHub 스타 | 32개 | 20,323개 (API 조회 시점, 지연 가능) |
| 최신 Chromium(무료) | 146.0.7680.177 · 58패치 | 동일(146) · 무료 티어는 정체됨 |
| 최신 Chromium(전체) | 146이 곧 최신 | 150.0.7871.114.3 · 71패치 (Pro 전용) |
| 공식 언어 클라이언트 | Python + JS(2개) | Python + JS + .NET/C#(3개) |
| 비즈니스 모델 | 순수 MIT, 바이너리도 무료 | 오픈 코어 — 래퍼 MIT / 최신 바이너리 구독제 |
| 배포 채널 | PyPI + GitHub Releases | + npm 정식, Docker Hub, NuGet, AWS Lambda 레이어 |
| 공급망 보안 | 언급 없음 | Ed25519 서명 검증 + GPG + Sigstore + Cosign 4중 |
README는 이렇게 적어 놨다: "Free (v146) — the previous binary... Goes stale within weeks as detection evolves." 안티봇 시스템은 계속 진화하는데 무료 바이너리는 업데이트가 멈춰 있으니, 실제 프로덕션 스크래핑에 쓰려면 사실상 Pro 구독이 전제라는 뜻이다. 게다가 플랫폼별 무료 패치 수도 다르다 — Linux/Windows 무료는 58패치인데 macOS 무료는 26패치뿐(Chromium 145 기준)이라, 무료로 macOS에서 쓰면 다른 플랫폼보다 약한 스텔스를 받는 셈이다.
Python·JS·.NET 래퍼 코드는 전부 공개돼 있고 라이선스도 MIT다. 라이선스 키가 없어도 launch()는 정상 작동하며 무료 바이너리로 실행된다 — 코드를 읽고 배우고 포크하는 데는 아무 제약이 없다. Pro는 "7일 무료 체험"도 제공해 최신 빌드를 부담 없이 테스트해볼 수 있게 해준다.
| 도구 | reCAPTCHA v3 | 패치 레벨 | 유지보수 | 엔진 |
|---|---|---|---|---|
| Stock Playwright | 0.1 (봇) | 없음 | 활발 | Chromium |
| playwright-stealth | 0.3~0.5 | JS 주입 | 정체 | Chromium |
| undetected-chromedriver | 0.3~0.7 | 설정 패치 | 정체 | Chrome (Selenium) |
| Camoufox | 0.7~0.9 | C++ (Firefox) | Unstable | Firefox |
| CloakBrowser (Pro) | 0.9 | C++ (Chromium) | 활발 | Chromium |
주목할 점 두 가지. 첫째, Camoufox(Firefox 진영)는 여전히 불안정 베타라 CloakBrowser의 "Chromium 채택" 전략이 상대적으로 안전해 보인다 — Chromium은 시장 점유율이 압도적이라 TLS·HTTP/2 지문이 정상 트래픽 바닷속에 묻힌다. 둘째, 이번 버전에서 처음 등장한 행동(behavioral) 탐지 대응 — humanize=True 한 줄로 마우스 궤적·타이핑 리듬·스크롤 패턴까지 사람처럼 만들어, deviceandbrowserinfo.com의 24개 행동 신호를 전부 통과("You are human!")했다고 README가 캡처와 함께 밝히고 있다. 지문 위장을 넘어 "행동 위장"까지 확장한 것.
지금까지 비교한 건 "자동화 라이브러리" 계열(playwright-stealth, undetected-chromedriver, Camoufox)이다. 하지만 안티디텍트 브라우저 시장에는 Multilogin, AdsPower, GoLogin 같은 GUI 기반 상용 제품군이 이미 자리 잡고 있다. 이들은 프로필 매니저 화면·팀 협업·클라우드 프로필 동기화·내장 프록시 관리를 갖춘 "완제품"이고, 월 구독으로 프로필 개수만큼 과금하는 SaaS 모델이다. CloakBrowser는 정반대 방향에서 접근한다 — GUI가 없는 대신 Playwright/Puppeteer 코드에 바로 꽂히고, 팀 대시보드가 없는 대신 CI/CD 파이프라인이나 Lambda 함수 안에 그대로 심을 수 있다. "비개발자가 클릭으로 운영"하는 시장과 "개발자가 코드로 자동화"하는 시장이 갈라지는 지점이며, CloakBrowser는 후자를 겨냥해 무료 오픈소스로 진입 장벽을 낮춘 뒤 Pro 구독으로 수익화하는 쪽을 택했다.
정당한 용도 — QA 엔지니어가 여러 지역·기기 조건에서 자사 서비스가 올바르게 뜨는지 검증, 광고주가 자기 광고가 실제로 노출되는지 확인(ad verification), 에이전시가 고객사의 여러 소셜/커머스 계정을 정책상 분리된 프로필로 안전하게 관리, 프라이버시를 중시하는 개인의 트래킹 회피, 그리고 이 저장소의 예제가 겨냥하는 browser-use·Crawl4AI류의 합법적 데이터 수집·리서치 에이전트.
악용 소지 — 같은 기술이 플랫폼 약관을 우회하는 다중 가짜 계정 생성(봇 팜), 광고 클릭 사기, 티켓/한정판 스니핑 봇, 리뷰 조작에도 그대로 쓰일 수 있다. CloakBrowser 자체는 "탐지를 회피하는 능력"만 제공할 뿐 용도를 강제하거나 검증하지 않으므로, 실제 사용 맥락이 서비스 약관과 관할 법률을 지키는지에 대한 책임은 전적으로 사용자에게 있다. 이 문서는 기술 학습 관점에서 다루며 특정 용도를 권장하지 않는다.
README의 "Framework Integrations" 표에 등재된 프레임워크만 봐도 이 프로젝트가 어디에 얹혀 있는지 보인다: browser-use(7만★), Crawl4AI(5.8만★), LangChain(10만★+), Scrapling(2.1만★), Stagehand(2.1만★), Crawlee, Selenium, undetected-chromedriver, agent-browser까지 — 대형 AI 에이전트·스크래핑 생태계가 CloakBrowser를 "바로 아래에 갈아끼울 수 있는 브라우저"로 인식하고 있다는 뜻이다. 이는 "에이전트가 웹을 자율적으로 돌아다녀야 하는" 흐름과 정확히 맞물린 트렌딩 요인이다.
navigator.webdriver = true, 헤드리스 UA, 빈 플러그인 목록 등)을 남긴다. 이 흔적을 지워 "사람이 직접 띄운 Chrome"처럼 보이게 만든 브라우저가 스텔스 브라우저다.저장소는 이제 명확히 "3개 공식 래퍼 + 예제 + 배포 레이어"로 나뉜다. 확장자 기준 파일 수는 .py 57개, .ts 44개, .cs 62개 — 두 달 전 "Python 래퍼 하나"였던 것과 비교하면 코드베이스 자체가 몇 배로 커졌다.
| 분류 | 패키지 | 역할 |
|---|---|---|
| 필수 | playwright>=1.40 | 브라우저 자동화 API |
| 필수 | httpx>=0.24 | 바이너리·라이선스 서버 통신용 HTTP 클라이언트 |
| 필수 (신규) | cryptography>=41.0 | 다운로드 바이너리의 Ed25519 서명 검증 (SHA256SUMS) |
옵션 [geoip] | geoip2, socksio | 프록시 IP → 시간대/로케일(132개국), SOCKS5 지원 |
옵션 [serve] | aiohttp, websockets | cloakserve CDP 멀티플렉서 서버 |
옵션 [dev] | pytest, pytest-asyncio | 테스트 |
내부적으로 크게 4개 축으로 나뉜다: 실행(browser.py, 1,495줄), 다운로드/검증(download.py, 1,161줄), 라이선스(license.py), 휴먼라이즈(human/, __init__.py만 3,050줄). 여기에 widevine.py(DRM), geoip.py가 옵션 기능으로 붙는다.
Node >=20.0.0 요구. playwright-core·puppeteer-core·mmdb-lib(GeoIP)·socks-proxy-agent가 전부 peerDependency이자 선택적(optional)이다 — 즉 사용자가 Playwright만 쓰든 Puppeteer만 쓰든, 안 쓰는 쪽의 무거운 패키지를 강제로 설치하지 않는다. 진입점은 3개로 분리돼 있다: cloakbrowser(Playwright 기본), cloakbrowser/puppeteer, cloakbrowser/human(외부에서 CDP로 붙는 프레임워크가 휴먼라이즈만 따로 가져다 쓸 때).
.NET의 Playwright는 IPage, ILocator, IMouse 등 봉인된(sealed) 인터페이스를 노출한다. Python/JS처럼 런타임에 메소드를 몽키패치할 수 없다는 뜻. 그래서 .NET 클라이언트는 Roslyn 소스 제너레이터(CloakBrowser.Generators, [GenerateInterfaceDelegation] 특성)를 만들어 컴파일 타임에 HumanizedPage 같은 래퍼 클래스를 자동 생성한다. 가로챌 멤버만 휴먼라이즈 엔진으로 보내고, 나머지는 원본 Playwright 객체로 그대로 위임(delegate)한다 — 리플렉션 없이 완전한 정적 타입 안정성을 유지하는 설계다.
| 항목 | 버전 |
|---|---|
| .NET SDK | 8.0 (net8.0 타겟) |
| Microsoft.Playwright | 1.49.0 |
| MaxMind.GeoIP2 | 5.2.0 (GeoIP 시간대/로케일) |
license.py가 cloakbrowser.dev의 3개 API(/api/license/validate, /api/download/version, /api/license/session/count)와 통신한다. 검증 결과는 24시간 TTL 로컬 캐시로 저장되고, 서버가 죽어도 stale 캐시로 계속 동작하도록 fail-open에 가깝게 설계돼 있다. Pro 바이너리가 라이선스 문제로 실행을 거부하면 76~79번 종료 코드로 사유를 인코딩해 반환하고, 래퍼가 이를 사람이 읽을 수 있는 CloakBrowserLicenseError로 번역한다.
| 채널 | 내용 |
|---|---|
| PyPI / npm / NuGet | 래퍼 코드 (MIT, 3개 언어 전부 정식 패키지) |
| GitHub Releases | 무료 바이너리(v146/v145) 아카이브 + SHA256SUMS + .sig |
| Docker Hub (신규) | cloakhq/cloakbrowser — 기본은 무료 바이너리 내장, 런타임에 라이선스 키를 주면 Pro로 전환 |
| AWS Lambda 레이어 (신규) | 공식 cloakhq/cloakbrowser 이미지를 FROM으로 삼아 30줄만 얹은 컨테이너 이미지, 원샷 스크래핑용 |
이전 분석에서는 아키텍처를 "래퍼 → Playwright → 패치된 바이너리 → 탐지 시스템"이라는 단순한 4단 파이프라인으로 설명했다. 지금은 그 파이프라인 앞뒤로 두 겹이 더 붙었다 — 실행 전에는 라이선스 해석과 서명 검증이, 실행 후에는 사람처럼 움직이게 만드는 휴먼라이즈 계층이 끼어든다.
config.py에는 binary_supports_headless_no_viewport(), binary_supports_http_proxy_inline_auth(), binary_supports_maximized_window() 같은 함수가 있다. 이들은 단순한 "버전 A 이상이면 켠다"가 아니라, 플랫폼마다 그 기능이 들어온 시점이 다르다는 현실을 그대로 반영한다:
# linux-x64/windows-x64는 146.0.7680.177.5부터 인라인 프록시 인증 지원.
# 그런데 macOS/linux-arm64 free 빌드는 그 이전 버전에 멈춰 있어서,
# Pro로 148+ 를 받아야만 같은 기능이 켜진다.
HTTP_PROXY_INLINE_AUTH_MIN_VERSION = {
"linux-x64": "146.0.7680.177.5",
"windows-x64": "146.0.7680.177.5",
"linux-arm64": "148.0.7778.215.3",
"darwin-arm64": "148.0.7778.215.3",
"darwin-x64": "148.0.7778.215.3",
}
이 "단일 임계값이 아니라 플랫폼별 임계값 맵"이라는 아이디어는 여러 빌드 라인이 서로 다른 속도로 진화하는 프로젝트(모바일 앱의 OS 버전별 기능 분기, 브라우저의 Canary/Beta/Stable 채널 분기 등)에 그대로 옮겨 쓸 수 있는 실전 패턴이다. 게다가 Python·JS·.NET 세 클라이언트가 이 게이트 로직을 동일하게 복제해 세 언어에서 동일한 판정이 나오도록 맞춰뒀다.
Pro 바이너리가 라이선스 문제로 실행을 거부하면 그냥 죽지 않고 76(세션 한도 초과) / 77(키 무효·만료) / 78(서버 연결 불가) / 79(로컬 설정 문제) 중 하나의 종료 코드를 낸다. Playwright는 이 종료를 "process did exit: exitCode=N" 형태의 텍스트로만 넘겨주는데, 래퍼가 정규식으로 그 코드를 뽑아 CloakBrowserLicenseError("session limit reached...")처럼 사람이 읽을 메시지로 바꿔준다. "바이너리는 숫자만 뱉고, 그 숫자의 의미는 래퍼 코드에 산다"는 분리 — 진단 문자열을 바이너리에 내장하면 리버스 엔지니어링 단서가 되니, 의도적으로 로직을 반대편에 둔 것이다.
bin/cloakserve는 "CDP 멀티플렉서"로 재정의됐다. 원격 서버에 브라우저 하나를 띄워 공유하는 게 아니라, 지문 시드(fingerprint seed)마다 별도 Chrome 프로세스를 spawn하고 URL 쿼리 파라미터로 어떤 프로세스에 붙을지 라우팅한다:
포트 하나 뒤에서 "각자 다른 사람인 척하는" 독립 프로세스 여러 개를 돌리는 구조라, 동시에 여러 계정/여러 지역 프로필을 흉내 내야 하는 QA·멀티 계정 워크로드에 잘 맞는다. 보안 측면에서도 SAFE_SEED_RE(시드 값 화이트리스트 정규식)와 TRUSTED_WS_ORIGINS(devtools Origin 제한)로 경로 탐색·CDP WebSocket 하이재킹을 막아둔 흔적이 보인다 — CHANGELOG에도 실제로 외부 기여자가 "cloakserve WebSocket origin guard", "path traversal" 취약점을 보고/수정한 이력이 남아 있다.
Python·JS는 "동적인 언어"라 page.click 함수 자체를 다른 함수로 바꿔치기(몽키패치)할 수 있다 — 마치 이미 조립된 가구의 손잡이를 열어서 부품만 슬쩍 바꾸는 것과 같다. 반면 .NET의 Playwright 인터페이스는 "봉인"돼 있어 이 방식이 안 통한다. 그래서 .NET 클라이언트는 컴파일 시점에 새 가구를 통째로 다시 짜는(소스 제너레이터) 방식을 택했다 — 손잡이만 바꾸는 대신, 처음부터 다른 손잡이가 달린 가구를 공장에서 찍어내는 셈이다.
① cloakbrowser/config.py(플랫폼·버전·티어 매트릭스를 먼저 이해해야 나머지가 풀린다) → ② cloakbrowser/license.py(오픈 코어 모델의 실제 구현) → ③ cloakbrowser/download.py의 _verify_signature(공급망 보안) → ④ cloakbrowser/human/config.py(휴먼라이즈 파라미터 전체를 한눈에) → ⑤ dotnet/src/CloakBrowser.Generators/(같은 기능을 정적 타입 언어에서 어떻게 복제하는지). 이 5곳만 봐도 프로젝트가 두 달 사이 무엇을 새로 지었는지 다 들어 있다.
단순히 "무료/유료를 나눈다"가 아니라, 라이선스 키 해석 우선순위(파라미터 > 환경변수 > 파일), 검증 실패 시 stale 캐시로 성능 저하 없이 폴백, 세션(좌석) 수를 절대 캐싱하지 않고 항상 실시간 조회(과금과 직결되는 값은 캐시하면 안 된다는 원칙) 등, 실무 SaaS 설계에서 그대로 재사용할 수 있는 디테일이 license.py 한 파일에 응축돼 있다.
① 배포 시 Ed25519로 SHA256SUMS에 서명 → ② 래퍼가 다운로드마다 자동으로, 우회 불가능하게 그 서명을 검증(핀 고정된 공개키, 여러 키 순환 지원) → ③ 그 다음에야 파일 체크섬을 대조 → ④ 추가로 GPG 서명 태그, GitHub attestation(Sigstore), Docker 이미지는 Cosign 서명까지 수동 검증 경로를 열어둔다. "자동 검증 하나로 끝내지 않고, 수동 재검증 경로까지 문서화해두는" 태도가 배울 점이다.
Python/JS의 human/__init__.py류 몽키패치 코드와 .NET의 Roslyn 소스 제너레이터를 나란히 읽어보면, "같은 요구사항, 다른 언어의 제약, 다른 해법"이 무엇인지 명확히 대비된다. 리플렉션 기반 프록시(느림)나 런타임 IL 조작(복잡함) 대신 컴파일 타임 코드 생성을 택한 이유까지 dotnet/README.md에 설명돼 있어, "봉인된 인터페이스 확장" 문제를 풀어야 하는 사람에게 실전 참고서가 된다.
C++ 패치는 "무엇을 보고하는가"(정적 지문)를 속이지만, humanize=True는 "어떻게 움직이는가"(행동 패턴)를 속인다. 마우스 이동을 베지어 곡선 + 오버슈트 확률로, 타이핑을 문자당 지연 + 2% 오타(자가 교정 포함)로, 스크롤을 가속-순항-감속 3단계로 만드는 구체적 수치(typing_delay=70ms, mouse_min_steps=25 등)까지 human/config.py에 다 나와 있다. "탐지 회피는 값 하나를 속이는 게 아니라 분포를 흉내 내는 것"이라는 감각을 얻기 좋다.
binary_supports_http_proxy_inline_auth 같은 함수는 세 언어에 각각 존재하지만 완전히 동일한 판정을 내야 한다 — 아니면 "Python에서는 되는데 JS에서는 안 되는" 버그가 생긴다. CHANGELOG 곳곳에 "Python, JS, and .NET" 문구가 반복되는 게 그 증거다. 다국어 SDK를 유지보수할 때 이 "3중 동기화" 부담을 어떻게 관리하는지 살펴볼 가치가 있다.
AWS Lambda 레이어는 FROM cloakhq/cloakbrowser 한 줄로 시작해 Lambda 런타임 어댑터만 추가한다. apt 목록도, Node 설치도, Chromium 다운로드도 다시 하지 않는다 — "표준 이미지를 신뢰하고 그 위에 얇게 얹는" 접근은 사내 플랫폼 이미지를 여러 배포 타겟에 맞출 때 그대로 쓸 수 있는 패턴이다.
가장 큰 변화: 이전 분석 시점엔 macOS·Windows가 "로드맵"이었는데, 지금은 Linux x64/arm64, macOS arm64/x64, Windows x64 다섯 플랫폼 전부 정식 지원(✅)이다. 다만 무료/Pro 사이에 버전·패치 수 격차가 플랫폼마다 다르다.
| 플랫폼 | 무료 | Pro |
|---|---|---|
| Linux x86_64 | Chromium 146 (58패치) | Chromium 150 (71패치) |
| Linux arm64 (RPi, Graviton) | Chromium 146 (58패치) | Chromium 150 (71패치) |
| macOS arm64 (Apple Silicon) | Chromium 145 (26패치) | Chromium 150 (71패치) |
| macOS x86_64 (Intel) | Chromium 145 (26패치) | Chromium 150 (71패치) |
| Windows x86_64 | Chromium 146 (58패치) | Chromium 150 (71패치) |
| 항목 | Python | JS/Node | .NET |
|---|---|---|---|
| 런타임 버전 | 3.9+ (3.12+ 권장) | Node >=20.0.0 | .NET SDK 8.0 |
| 핵심 의존성 | playwright, httpx, cryptography | playwright-core/puppeteer-core(옵션) | Microsoft.Playwright 1.49.0 |
| RAM | 2GB 최소, 페이지 여러 개면 4GB+ 권장 | ||
| 디스크 | 무료+Pro 바이너리 동시 캐시 시 ~1.5GB (각 ~200MB + GeoIP 70MB) | ||
| macOS 첫 실행 | ad-hoc 서명 바이너리라 Gatekeeper 차단 — 우클릭 → 열기로 1회 우회 필요 | ||
라이선스 검증(/api/license/validate)과 최신 버전 조회(/api/download/version)는 cloakbrowser.dev로 나가는 실제 HTTP 호출이다. 완전히 격리된(에어갭) 환경에서는 24시간 캐시가 만료되면 검증이 막힐 수 있다. 사내 방화벽에서 스크래핑 서버를 운영한다면 cloakbrowser.dev 아웃바운드를 허용 목록에 넣어야 한다.
| 항목 | 요구사항 |
|---|---|
| Docker 이미지 | cloakhq/cloakbrowser — 기본 무료 바이너리 내장, Pro는 런타임에 CLOAKBROWSER_LICENSE_KEY 주입 시 재다운로드 |
| 헤드드(headed) 모드 | 컨테이너 안에 Xvfb(가상 디스플레이) + openbox(창 관리자) 필요 — 공식 이미지에 포함 |
| AWS Lambda | 컨테이너 이미지 패키지 타입, linux/arm64 권장(빌드 속도), Xvfb 상시 기동 필요(헤드드 강제) |
| Widevine(선택) | CLOAKBROWSER_FETCH_WIDEVINE=1 시 컨테이너 기동 때 CDM을 구글 컴포넌트 서버에서 받아 캐시 |
Chromium 자체를 처음부터 패치·빌드하려면(이 프로젝트의 바이너리 자체를 만드는 작업) 16코어+ CPU, 32GB RAM, 100GB+ 여유 디스크, 첫 fetch에 ~30GB 다운로드가 필요하다. 이 부분은 두 달 전과 달라지지 않았다 — Pro 바이너리든 무료 바이너리든, "빌드"의 물리적 비용 자체는 그대로다.
pip install cloakbrowser 후 python -m cloakbrowser info(또는 doctor)를 실행해 현재 실행될 바이너리의 티어·버전을 확인한다. 가능하다면 Linux/Windows 환경과 macOS 환경에서 각각 실행해, README가 말하는 "macOS 무료는 26패치, 다른 플랫폼 무료는 58패치"라는 격차가 bot.sannysoft.com 결과 차이로 실제 드러나는지 캡처해 비교한다.
launch(headless=False, humanize=True)로 헤드드 모드를 띄우고 page.locator("button").click()을 실행하면서 화면 녹화를 해본다. 마우스가 목표 지점까지 일직선이 아니라 곡선 + 약간의 오버슈트로 이동하는지 관찰하고, human_config={"mouse_overshoot_chance": 1.0}처럼 파라미터를 극단으로 바꿔가며 어떤 값이 어떤 움직임을 만드는지 대응시켜 본다.
일부러 가짜 CLOAKBROWSER_LICENSE_KEY=cb_invalid를 설정하고 launch()를 호출해 CloakBrowserLicenseError가 어떤 메시지를 내는지 확인한다. license.py의 _LICENSE_EXIT_MESSAGES 딕셔너리(76~79번 코드)를 읽고, 각 코드가 실제로 어떤 상황(세션 초과·키 무효·서버 불통·설정 오류)에 대응하는지 표로 정리해본다.
pip install cloakbrowser[serve] 후 cloakserve를 실행하고, 서로 다른 ?fingerprint= 쿼리로 두 개 이상의 CDP 연결을 동시에 만들어본다. ps aux | grep chrome으로 시드마다 별도 프로세스가 뜨는지 확인하고, 각 연결에서 navigator.userAgent나 화면 해상도가 서로 다른 지문으로 보이는지 검증한다.
Google의 "Get the Code" 가이드로 Chromium 소스를 받아 third_party/blink/renderer/core/frame/navigator.cc의 webdriver() 함수를 return false로 바꾸고 빌드한다. 빌드 결과물을 CLOAKBROWSER_BINARY_PATH 환경변수로 지정해 래퍼와 함께 실행해보면, 71개 패치가 쌓여 만들어내는 결과를 "패치 1개"로 재현하는 감각을 얻을 수 있다.
두 라이브러리의 Sync/Async API를 손에 익힌다. CloakBrowser는 이 위에 얹힌 얇은 층이므로, 밑단을 모르면 무엇이 CloakBrowser의 기여이고 무엇이 Playwright 기본 동작인지 구분이 안 된다.
FingerprintJS·CreepJS 오픈소스 코어로 "어떤 신호를 모아 해시를 만드는가"(정적 지문)를 이해하고, deviceandbrowserinfo.com 같은 사이트가 검사하는 "행동 신호"(마우스 궤적의 매끄러움, 타이핑 리듬의 규칙성 등)까지 함께 공부한다. 이번 버전의 humanize=True는 정확히 이 두 번째 층을 겨냥한다.
Ed25519 서명, Sigstore/Cosign, SLSA 프레임워크를 공부한다. CloakBrowser의 _verify_signature 함수와 README "Security" 절이 좋은 실전 예제다. "왜 체크섬만으로는 부족하고 서명까지 필요한가"(체크섬은 공격자가 통째로 바꿔치기하면 무력화되지만, 서명은 개인키가 없으면 위조 불가)를 직접 코드로 확인해본다.
GitLab CE/EE, Elastic의 라이선스 변천사, MongoDB의 SSPL 전환 같은 사례와 CloakBrowser의 "래퍼 MIT + 바이너리 구독" 모델을 비교한다. 라이선스 키 검증·캐싱·세션 관리를 실제로 구현해보는 작은 토이 프로젝트(예: 자기 CLI 도구에 "Pro 기능" 게이트 달아보기)를 진행하면 감각이 확실해진다.
Python의 몽키패치, JS의 프로토타입 오버라이드, .NET의 Roslyn 소스 제너레이터(ISourceGenerator/IIncrementalGenerator)를 나란히 공부한다. 같은 "메소드 가로채기" 목표를 세 언어가 어떻게 다르게 푸는지 직접 작은 예제로 구현해보면 각 언어의 메타프로그래밍 모델이 명확해진다.
depot_tools, GN, ninja로 첫 Chromium 빌드에 성공하는 것을 목표로 한다. Blink의 Web IDL → C++ 바인딩 구조까지 이해하면, 71개 패치가 정확히 어느 계층에서 무엇을 바꾸는지 완전히 그려진다.
여기까지 오면 "지문 패치 몇 개 + 라이선스 게이트 하나 + 서명 검증 하나"로 자신만의 미니 오픈 코어 도구를 설계할 수 있다. CloakBrowser와의 차이는 규모뿐, 구조적 본질은 동일하다.
humanize=True 한 줄로 마우스·키보드·스크롤 동작을 사람처럼 바꾸는 행동 계층. 지문 위장과 별개로 "행동 탐지"에 대응한다.CloakBrowserLicenseError로 번역한다.binary_supports_* 함수군이 대표적.dotnet add package CloakBrowser(NuGet) — 3개 언어 패키지