헤드리스 브라우저 탐지: Playwright, Puppeteer 그리고 그 너머
Bot Detection 엔진은 신호 불일치, 누락된 API, 봇이 흉내 낼 수 없는 행동 패턴을 통해 15개 이상의 자동화 프레임워크를 식별합니다.
헤드리스 브라우저는 정교한 웹 스크래핑, credential stuffing, 그리고 사기 작업에서 선호되는 도구입니다. 단순한 HTTP 클라이언트와 달리 헤드리스 브라우저는 JavaScript를 실행하고, 페이지를 렌더링하며, 최신 웹 API를 지원합니다 — 그만큼 탐지하기가 훨씬 더 어렵습니다. Bot Detection 엔진은 여러 독립적인 탐지 방법을 사용해 15개 이상의 자동화 프레임워크를 거의 0에 가까운 오탐률로 식별합니다.
브라우저 자동화의 진화
브라우저 자동화는 단순한 curl 스크립트에서 크게 발전해 왔습니다. Playwright, Puppeteer, Selenium WebDriver 같은 최신 도구는 실제 브라우저 엔진 — Chromium, Firefox, WebKit — 을 헤드리스 모드로 제어합니다. 이들은 헤드 브라우저와 똑같이 JavaScript를 실행하고, CSS를 처리하며, canvas 요소를 렌더링하고, WebGL 쿼리를 처리합니다. 그래서 JavaScript 실행 능력만 단순히 확인하는 탐지 방법에는 보이지 않습니다.
최신 세대의 도구는 여기서 더 나아갔습니다. Playwright의 stealth 모드는 전통적인 bot detection이 의존하는 신호 상당수를 패치합니다. puppeteer-extra-plugin-stealth는 navigator 속성을 수정하고, WebGL 벤더 문자열을 재정의하며, 사용자 상호작용 이벤트를 위조합니다. 이러한 탐지 회피 조치는 봇 운영자와 탐지 시스템 사이의 군비 경쟁을 만들어냈습니다.
탐지 방법 1: WebDriver 플래그 분석
navigator.webdriver 속성은 브라우저가 자동화에 의해 제어될 때 true로 설정됩니다. 초기 탐지는 이 속성을 확인하는 것만큼이나 단순했습니다. 그러나 최신 stealth 도구는 이 속성을 삭제하거나 재정의합니다. 우리의 탐지는 더 깊이 들어갑니다 — 속성 값뿐 아니라 그 property descriptor, prototype chain 내 존재 여부, 그리고 재정의 시도가 있었는지까지 확인합니다. 또한 WebDriver 재정의에 수반되는 navigator.plugins 길이 이상 같은 관련 속성도 확인합니다.
탐지 방법 2: Chrome DevTools Protocol 아티팩트
Playwright와 Puppeteer는 Chrome DevTools Protocol(CDP)을 통해 브라우저를 제어합니다. stealth 모드가 활성화되어 있어도 CDP는 런타임에 아티팩트를 남깁니다: 특정 전역 변수, 수정된 getter 함수, 그리고 Window 및 Navigator 객체의 변경된 property descriptor 등입니다. 우리는 단순한 덮어쓰기에 견디는 기법으로 이러한 아티팩트를 탐침합니다.
탐지 방법 3: 헤드리스 브라우저 fingerprinting
헤드리스 Chrome은 헤드 Chrome과 다른 기능 집합을 가집니다. 특정 브라우저 플러그인이 없고, 일부 CSS 속성의 렌더링 특성이 다르며, 일부 MediaQuery 결과에 대해 다른 값을 보고합니다. 우리는 알려진 헤드리스 브라우저 특성의 데이터베이스를 유지하고, 들어오는 fingerprint를 이에 대조해 확인합니다.
주요 헤드리스 지표로는 다음이 있습니다: chrome.runtime 누락(헤드 Chrome에는 존재하지만 헤드리스에는 없음), 길이가 0인 navigator.plugins 배열, 이전 버전에서 헤드리스 모드와 연관된 특정 user agent 패턴, 그리고 헤드리스 Chrome이 iframe 보안 컨텍스트를 처리하는 방식의 차이 등입니다.
탐지 방법 4: Eval 길이 분석
JavaScript 엔진마다 내장 함수의 구현이 다르며, 이 구현들은 서로 다른 문자열 표현을 가집니다. Function.prototype.toString.call(eval)의 길이를 확인하고 이를 각 브라우저 엔진의 알려진 값과 비교함으로써, 환경 위장 — 예를 들어 헤드리스 Chrome 인스턴스가 Firefox인 척하는 경우 — 을 탐지할 수 있습니다.
탐지 방법 5: TLS 교차 검증
TLS fingerprinting 관련 글에서 논의했듯이, TLS Client Hello 메시지는 연결을 맺는 실제 브라우저 또는 HTTP 라이브러리를 드러냅니다. Playwright 스크립트가 Chrome을 제어할 때는 TLS fingerprint가 Chrome과 일치합니다 — 이는 예상되는 결과입니다. 그러나 커스텀 봇이 Python requests 라이브러리나 Go의 net/http를 사용할 경우, 어떤 user agent 문자열을 보내든 TLS fingerprint가 그 위장을 드러냅니다.
탐지 방법 6: 타이밍 및 행동 분석
실제 사용자는 상호작용 타이밍에서 자연스러운 변동을 보입니다. 마우스를 직선이 아닌 곡선으로 움직입니다. 클릭하기 전에 멈칫합니다. 가변적인 속도로 스크롤합니다. 자동화 도구는 사람의 행동을 시뮬레이션하는 것조차도 통계적으로 구별 가능한 패턴을 만들어냅니다 — 지나치게 일정한 타이밍, 완벽하게 직선인 마우스 경로, 부자연스러운 스크롤 속도 등입니다.
우리는 fingerprinting 과정 자체에서 최소한의 행동 신호를 수집합니다 — API 호출의 타이밍, 신호 수집의 순서, 특정 브라우저 API의 응답성 등입니다. 이러한 미세 행동 신호는 재정의 가능한 속성이 아니라 실제 실행 환경에 의존하기 때문에 자동화 도구가 위조하기 어렵습니다.
탐지 방법 7: 권한 및 API 불일치
실제 브라우저는 일관된 권한 상태와 API 가용성을 가집니다. 알림을 지원한다고 주장하면서 Notification 생성자가 없는 브라우저, 또는 특정 화면 해상도를 보고하면서 window.screen과 CSS media query에서 다른 값을 반환하는 브라우저는 변조 또는 에뮬레이션을 나타내는 불일치를 드러내고 있는 것입니다.
우리는 이러한 교차 검증 지점을 수십 개 확인하며, 자동화 도구가 관련된 모든 API에 걸친 일관성을 유지하지 않고 일부 신호만 선택적으로 재정의할 때 발생하는 모순을 찾아냅니다.
탐지 방법 8: VM 및 에뮬레이션 탐지
많은 봇 작업은 가상 머신이나 클라우드 인스턴스 안에서 실행됩니다. 이것만으로 자동화의 증거가 되지는 않지만, 다른 지표와 결합되면 강력한 신호가 됩니다. 우리는 VM과 연관된 키워드("llvmpipe" 또는 "SwiftShader" 등)를 포함하는 WebGL 렌더러 문자열, 소비자 기기와 맞지 않는 하드웨어 특성(정확히 CPU 코어 2개와 메모리 2GB — 흔한 VM 기본값), 그리고 알려진 클라우드 제공업체 IP 대역을 통해 VM을 탐지합니다.
다중 방법의 이점
각 탐지 방법은 개별적으로는 한계가 있습니다 — 정교한 봇 운영자는 어떤 단일 방법이든 우회할 수 있습니다. 그러나 모든 방법을 동시에 우회하면서 그 모두에 걸쳐 교차 검증의 일관성을 유지하는 것은 감당하기 어려울 정도로 비쌉니다. 모든 검사를 통과하는 봇을 개발하고 유지하는 비용은 대부분의 봇 작업이 지니는 경제적 가치를 초과합니다.
거의 0에 가까운 오탐
우리의 탐지는 reverse DNS로 검증된 검색 엔진 봇(Googlebot, Bingbot 등)에 대해서는 화이트리스트 모델로, 그 외 트래픽에 대해서는 다중 신호 모델로 작동합니다. 트래픽을 자동화된 것으로 분류하기 전에 여러 개의 상호 확증 신호를 요구합니다. 이러한 보수적인 접근은 오탐률을 0.1% 미만으로 유지하도록 보장하며 — 수십억 건의 프로덕션 이벤트에서 검증되었습니다.