가이드

가입 페이지에서 헤드리스 브라우저와 자동화를 탐지하는 방법

Puppeteer, Playwright, Selenium 가입을 드러내는 브라우저 신호, 각 신호를 단독으로는 위조할 수 있는 이유, 실제 사람을 막지 않고 조합하는 방법.

9분 분량 · 2026-10-31 업데이트 · Attrelix

봇이 이제 진짜 브라우저를 쓰는 이유

몇 년 전만 해도 대부분의 가입 봇은 양식을 직접 전송하는 단순한 HTTP 스크립트였습니다. 이런 봇은 막기 쉽습니다. JavaScript를 실행하지 않으니 페이지가 브라우저에서 계산한 것이 아무것도 도착하지 않습니다. 오늘날 진지한 봇 대부분은 Puppeteer, Playwright, Selenium으로 진짜 브라우저를 조종하며, 흔히 헤드리스이고 때로는 핑거프린트를 위장하는 안티디텍트 브라우저를 거칩니다. 이들은 JavaScript를 실행하고, 페이지를 렌더링하고, 사람처럼 양식을 채웁니다.

이들을 탐지한다는 것은 자동화된 브라우저가 사람이 쓰는 브라우저와 다른 지점을 찾는 것입니다. 아래 신호는 어느 것도 혼자서는 증거가 아닙니다—마음먹은 운영자는 하나씩 감출 수 있습니다—하지만 수집 비용이 낮고 서로 쌓입니다.

신호 1: WebDriver 플래그

WebDriver 방식의 자동화 아래 있는 브라우저는 navigator.webdriver를 true로 설정합니다. 이는 WebDriver 표준의 의도된 일부이며, Selenium, Puppeteer, Playwright의 기본 설정은 이를 노출합니다.

const automated = navigator.webdriver === true;

“stealth” 플러그인은 이를 지우거나 덮어쓰므로, 없다고 해서 아무것도 증명되지 않습니다. 하지만 있다면 거의 결정적입니다. 실제 사용자에게는 사실상 없기 때문입니다.

신호 2: 헤드리스 사용자 에이전트

헤드리스 Chrome은 운영자가 덮어쓰지 않는 한 사용자 에이전트에서 HeadlessChrome이라고 밝힙니다. JavaScript에서 보고되는 사용자 에이전트와 실제로 보내는 것이 다를 수 있으니 서버에서도 요청 헤더로 확인하세요.

신호 3: DevTools 프로토콜 클라이언트 연결

Puppeteer와 Playwright는 DevTools 프로토콜로 Chrome을 조종합니다. 프로토콜 클라이언트가 콘솔 이벤트를 듣고 있으면, 객체를 로그로 남기는 것만으로 브라우저가 이를 직렬화하며 일반 페이지라면 절대 건드리지 않을 속성까지 읽습니다. 읽혔는지를 기록하는 getter는 이를 알아채는 잘 알려진 방법입니다.

function devtoolsProtocolAttached() {
  let read = false;
  const e = new Error();
  Object.defineProperty(e, "stack", { get() { read = true; return ""; } });
  console.debug(e);
  return read;
}

개발자가 DevTools를 열어 둔 경우에도 반응하므로, 판정이 아니라 중간 정도의 가중치로 다루세요.

신호 4: 소프트웨어 렌더링과 이상한 창

서버의 헤드리스 브라우저에는 GPU가 없어서 WebGL이 SwiftShader나 llvmpipe 같은 소프트웨어 렌더러로 대체됩니다. 브라우저가 WEBGL_debug_renderer_info 확장을 제공하면 렌더러 이름을 읽을 수 있습니다. 일부 헤드리스 설정은 너비나 높이가 0인 창을 보고하기도 합니다. 가상 머신과 원격 데스크톱도 같은 특징을 가지므로 단독으로는 약한 신호입니다.

신호 5: 스스로 모순되는 핑거프린트

안티디텍트 브라우저는 서로 다른 수많은 진짜 브라우저처럼 보이려고 존재합니다. 그러기 위해 속성을 덮어쓰는데, 덮어쓰기가 완벽하게 일관된 경우는 드뭅니다. 비교해 볼 만한 것은 다음과 같습니다.

  • 사용자 에이전트의 운영체제와 navigator.platform, User-Agent Client Hints.
  • 사용자 에이전트의 브라우저 계열과 그 엔진에만 있는 기능.
  • 설치된 글꼴과 그 운영체제에 기본 포함된 글꼴.
  • 연달아 두 번 그린 canvas가 서로 다른 두 이미지가 되는 경우—주입된 노이즈의 징후.
  • Notification.permission은 “denied”인데 Permissions API는 “prompt”라고 답하는 경우.

개인정보 보호 확장 프로그램이나 흔치 않은 설정도 일부를 만들어 내므로, 모순 하나하나는 약합니다. 두세 개가 함께 나타나면 강한 패턴입니다.

신호 6: 돌아오지 않은 토큰

간단하고 견고한 기법입니다. 가입 페이지 스크립트가 수명이 짧은 일회용 토큰을 요청하게 하고, 양식의 숨은 필드에 넣은 뒤 서버에서 검증하세요. JavaScript를 건너뛴 봇은 유효한 토큰 없이 오고, 예전 토큰을 재사용하는 봇은 이미 쓴 토큰을 들고 옵니다. 봇이 어떻게 동작하는지 몰라도 페이지를 제대로 실행하지 않았다는 것은 알 수 있습니다. 토큰은 일회용으로, 여러분 사이트에 묶고, 몇 분 안에 만료되게 하세요.

신호 7: 지문이 아니라 행동

지문은 위조할 수 있지만 행동은 훨씬 어렵습니다. 사람은 양식을 읽고 포인터를 움직이며 입력합니다. 스크립트는 페이지 로딩 후 수백 밀리초 만에 필드를 채워 전송하며, 신뢰할 수 있는 입력 이벤트를 하나도 만들지 않습니다.

정확한 측정에 추가 소프트웨어는 필요 없습니다. 에이전트가 페이지 로딩 시 방문자 토큰을 발급하고, 서버가 그 시각과 검사 시점을 비교합니다. 로딩에서 가입까지 약 1초 미만이면 스크립트입니다. 에이전트가 신뢰할 수 있는 입력 이벤트도 보고할 수 있다면, 포인터·키·터치 이벤트가 전혀 없는 즉시 전송은 두 번째 독립적 확인이 됩니다.

신호 3에 대한 주의: 현재 Chrome에서 DevTools 기법은 자동화 클라이언트가 콘솔 이벤트를 구독할 때만 작동하므로, 주된 탐지 수단이 아니라 보너스로 다루세요.

조합하세요. 신호 하나로 차단하지 마세요

각 신호를 점수의 점수로 다루고 합계로 결정하세요. 강한 것부터 약한 것까지, 출발점으로 삼을 만한 가중치입니다.

신호가중치이유
navigator.webdriver가 true높음실제 사용자는 거의 true가 아님
HeadlessChrome 사용자 에이전트높음헤드리스 빌드만 보냄
토큰 없음 또는 재사용높음페이지 스크립트가 실행되지 않았거나, 한 번 실행으로 여러 가입
DevTools 프로토콜 연결중간DevTools를 연 개발자도 해당
OS 또는 브라우저 모순중간안티디텍트 덮어쓰기지만 일부 확장 프로그램도 원인
소프트웨어 렌더러, 크기 0인 창낮음VM과 원격 데스크톱에도 있음

브라우저 신호를 서버 측 신호—클라우드 IP 대역에서 온 가입, 한 서브넷에서 몰린 가입, 같은 기기에 연결된 계정—와 결합하면, 모든 면에서 동시에 깨끗해 보이는 봇은 극히 드뭅니다.

하지 말아야 할 것

  • 플러그인이나 언어가 없다는 이유만으로 차단하지 마세요. 개인정보 보호를 강화한 브라우저는 이를 제거합니다.
  • 탐지 로직을 이름이 뻔한 검사로 배포하지 마세요. 운영자가 검색해서 한 번에 우회할 수 있습니다. 브라우저에서는 원시 데이터를 모으고 판단은 서버에서 하세요.
  • 브라우저가 보고하는 것을 맹신하지 마세요. 클라이언트는 봇의 통제 아래 있습니다. 검증은 여러분의 서버에서, 여러분의 비밀 키로 이뤄집니다.

Attrelix의 방식

Attrelix 에이전트는 가입 페이지에서 이런 브라우저 정보와 일회용 방문자 토큰을 수집하고, 서버는 이를 네트워크, 메일함, 연결된 계정 신호와 합쳐 하나의 점수를 만듭니다. 모든 가중치는 문서에 공개되어 있으며, 약한 신호 하나만으로 가입이 검토로 가지는 않습니다.

요약

  • 현대의 봇은 진짜 브라우저를 씁니다. 자동화가 사람과 다른 지점을 찾으세요.
  • WebDriver, 헤드리스 사용자 에이전트, 토큰 누락은 강한 신호이고, 나머지는 약하지만 쌓입니다.
  • 판단은 서버에서 점수로 하세요. 브라우저 플래그 하나로 정하지 마세요.

다른 가이드