Selenium으로 실행한 브라우저는 디버깅 포트, 페이지에서 읽을 수 있는 속성, 시작 방식에서 차이가 나타날 수 있습니다. 일부는 일관성을 위해 합리적으로 설정할 수 있지만, 자동화 자체를 숨기려는 시도는 불필요하고 취약하며 효과도 오래가지 않습니다.
Selenium으로 자동화를 실행할 때 스크립트 로직이 맞는데도 원하는 결과를 얻지 못하는 경우가 있습니다. 많은 사람은 먼저 한두 개의 파라미터를 바꾸려 하지만, 실제로 환경을 눈에 띄게 만드는 원인은 단일 스위치가 아닌 경우가 많습니다. 여러 층에서 나타나는 차이가 함께 작용합니다. 이 층들을 나눠 보면 무엇을 설정할 가치가 있고 무엇은 해도 큰 도움이 되지 않는지 구분하기 쉬워집니다.
디버깅 포트와 런타임 흔적
Selenium이 브라우저를 제어하는 방식은 두 종류의 흔적을 남길 수 있습니다. 첫째, 브라우저가 시작될 때 디버깅 포트가 열릴 수 있고, 외부 소프트웨어가 이를 통해 페이지를 제어할 수 있습니다. 둘째, 런타임 환경에 추가 요소가 생길 수 있습니다. 예를 들어 드라이버가 주입한 cdc_ 접두사의 전역 변수, window에 추가된 드라이버 객체, 일부 객체 프로토타입의 변경된 부분 등이 있습니다.
이러한 요소는 웹페이지가 아니라 드라이버 자체에서 생깁니다. 표준 방식으로 브라우저를 시작하면 스크립트가 얼마나 잘 작성되었는지와 관계없이 존재합니다.
페이지에서 읽을 수 있는 속성
또 다른 종류의 흔적은 드라이버가 아니라 페이지가 읽을 수 있는 JavaScript 환경에 있습니다. 가장 자주 언급되는 예가 navigator.webdriver입니다.
이 속성에는 세 가지 값이 있을 수 있습니다. true는 브라우저가 자동화 도구에 의해 제어되고 있음을 뜻하고, false는 그렇지 않음을 뜻합니다. undefined는 관련 정보를 가져올 수 없다는 뜻으로, 보통 브라우저가 이 속성을 노출하지 않거나 어떤 처리가 이루어진 경우입니다. 일반적인 사람의 브라우징에서는 false 또는 undefined이고, Selenium을 기본 설정으로 시작하면 true입니다.
이 주변에는 더 많은 파라미터가 있습니다. User-Agent, 운영체제와 브라우저 버전, 화면 해상도, 시간대, 언어, Canvas, WebGL, AudioContext, 글꼴 목록, GPU 모델, CPU 코어 수 등입니다. 이 정보를 합치면 흔히 브라우저 지문이라고 부르는 것이 됩니다. 실제 사용자의 기기는 시스템, 소프트웨어, 사용 습관이 다르기 때문에 지문도 자연스럽게 다양합니다. 반면 기본 자동화 설정으로 실행되는 브라우저는 매우 비슷한 조합을 만들기 쉬워 알려진 패턴으로 묶이기 쉽습니다.
시작 방식과 렌더링 타이밍에서 생기는 차이
세 번째 종류는 어느 한 속성에 있는 것이 아니라 브라우저를 시작하고 렌더링하는 전체 방식에서 생깁니다.
자동화 플래그를 붙여 시작하거나 headless 모드로 실행하는 것, 창 크기와 화면 파라미터가 맞지 않는 것, 글꼴 렌더링과 그래픽 드라이버 조합이 어색한 것, 페이지 로드부터 상호작용 가능 상태까지의 시간이 지나치게 일정한 것 등은 하나씩 보면 증거가 아닙니다. 하지만 여러 요소가 겹치면 실제 사람이 사용한 환경처럼 보이지 않을 수 있습니다.
Headless가 대표적인 예입니다. 최신 Chrome의 headless 모드는 몇 년 전보다 일반 브라우저에 훨씬 가까워졌지만, 일반 모드와 비교하면 여전히 자동화 특징이 더 쉽게 드러날 수 있으며, 특히 위험 관리가 엄격한 사이트에서 그렇습니다.
합리적으로 설정할 수 있는 범위
시간대, 언어, 화면 해상도, 글꼴 목록은 자동화에만 있는 요소가 아닙니다. 실제 기기도 원래 서로 다릅니다. 이런 파라미터에서 중요한 것은 내부 일관성입니다. 시간대는 네트워크 출구 지역과 맞아야 하고, 언어는 일반적인 사용 지역과 맞아야 하며, 해상도는 하드웨어 프로필과 충돌하지 않아야 합니다.
쉽게 말하면 환경을 특별하게 보이게 만드는 것이 아니라 내부적으로 말이 되게 만드는 것이 목표입니다. 독일에서 접속하는 기기로 보이는데 브라우저는 미국 서부 시간대를 보고하고, 시스템 언어는 영어뿐이며, 화면 해상도는 전형적인 가상 디스플레이 값이라면 이 조합만으로도 충분히 눈에 띕니다.
이 때문에 환경 설정은 장기간 유지할 수 있는 형태로 저장하는 편이 좋습니다. 오늘 시간대를 바꾸고 내일 언어 설정을 잊으면 아무것도 바꾸지 않는 것보다 더 큰 불일치가 생길 수 있습니다.
자동화 자체를 숨기려는 방법과 권장하기 어려운 이유
또 다른 방식은 흔적 자체를 직접 없애려는 것입니다. navigator.webdriver를 제거하고, 드라이버가 주입한 변수를 지우고, 드라이버 객체를 숨기거나, 탐지 측이 자동화 상태를 읽지 못하게 만드는 방법입니다.
문제는 이런 방식이 본질이 아니라 표면만 바꾼다는 데 있습니다. 탐지는 이미 오래전부터 단일 속성만 보지 않으며, 속성을 읽는 것은 가장 표면적인 단계일 뿐입니다. 드라이버가 업데이트되거나 탐지 스크립트의 실행 순서가 바뀌거나, JavaScript를 건너뛰고 저수준 렌더링 결과와 기기 특성의 조합을 직접 보는 방식이 사용되면 이전의 수정은 쉽게 무효가 됩니다. 유지보수 비용은 적지 않은데 효과는 계속 줄어듭니다.
실무적으로는 이런 작업이 플랫폼 이용약관에서 기술적 보호 조치의 우회로 규정하는 영역에 들어가는 경우가 많다는 점도 중요합니다. 몇 가지 속성을 수정했다고 해서 행위의 성격이 달라지는 것은 아닙니다.
네트워크 계층은 스크립트로 해결할 수 없다
브라우저 환경에서 문제가 보이지 않더라도 네트워크 계층에서 세션이 식별될 수 있습니다. IP가 데이터센터, 클라우드 서버, 프록시 네트워크 중 어디에 속하는지, 해당 IP 대역의 과거 평판과 ASN, 지리적 위치, 같은 IP의 요청 밀도, 짧은 시간에 여러 계정이나 페이지에 접근하는지 등이 고려될 수 있습니다. 요청에 포함된 Cookie, Session, 로그인 상태도 서로 연관 지어 볼 수 있습니다.
이 문제는 스크립트 내부에서 해결할 수 없고 환경 계층에서 처리해야 합니다. 각 작업마다 별도의 네트워크 출구를 두고, 출구 지역과 환경 지역을 맞추며, 요청 속도를 통제할 수 있어야 합니다. 여러 작업을 분리할 때 PurpleMark 같은 기능은 보통 이 계층에서 각 작업에 독립적인 브라우저 환경과 네트워크 출구를 제공하고 지리 관련 파라미터의 일관성을 유지합니다.
실제로 차단됐을 때의 점검 순서

대략적인 순서는 다음과 같습니다. 먼저 네트워크 계층에서 IP 유형, 안정성, 지역 일관성을 확인합니다. 다음으로 환경 내부에서 시간대, 언어, 해상도, 글꼴이 서로 모순되지 않는지 봅니다. 그다음 대기 시간이 항상 고정인지, 입력이 즉시 끝나는지 같은 행동 타이밍을 확인합니다. 마지막으로 드라이버 계층의 자동화 속성을 봅니다.
이유는 간단합니다. 드라이버 계층의 흔적은 이미 탐지의 중심이 아닙니다. 이를 문제 해결의 첫 단계에 두는 것은 대체로 시간을 낭비하게 됩니다.
경계
기술적 조치로 식별될 가능성을 낮출 수는 있지만 넘어서는 안 되는 선이 있습니다. 대상 사이트의 robots 규칙과 이용약관을 준수하고, 개인정보를 수집하지 않으며, 기술적 보호 조치를 우회하지 말아야 합니다. 또한 요청 빈도를 통제하고 상대 서비스의 정상적인 운영에 영향을 주지 않아야 합니다.


