타이밍 공격은 브라우저에서 작업 실행 시간을 분석하여 봇을 탐지하는 방법입니다. Facebook, Google, TikTok 및 기타 플랫폼의 최신 안티프로드 시스템은 사용자가 무엇을 하는지뿐만 아니라 얼마나 빨리 하는지도 분석합니다. 너무 빠른 클릭, 즉각적인 페이지 로딩, 자연스러운 일시 정지의 부재는 모두 자동화를 드러냅니다. 이 기사에서는 Selenium, Puppeteer 및 안티탐지 브라우저와 함께 작업하는 개발자를 위한 타이밍 공격 방어 기술을 살펴보겠습니다.
타이밍 공격이란 무엇이며 어떻게 작동하는가
타이밍 공격은 사용자의 행동 간의 시간 간격을 측정하여 자동화를 탐지하는 방법입니다. 안티프로드 시스템은 텔레메트리를 수집합니다: 페이지 로딩부터 첫 클릭까지의 시간, 사용자가 스크롤하는 속도, 양식 작성 시의 일시 정지 여부. 이러한 데이터는 실제 사람의 행동 모델과 비교됩니다.
시스템이 분석하는 주요 시간 메트릭은 다음과 같습니다:
- 첫 상호작용까지의 시간 (TTFI) — 페이지 로딩부터 첫 행동(클릭, 스크롤, 텍스트 입력)까지의 시간. 봇은 일반적으로 DOM이 로드된 직후 즉시 행동을 시작하지만, 사람은 0.5-3초 후에 행동을 시작합니다.
- 클릭 타이밍 패턴 — 클릭 간의 간격. 자동화된 스크립트는 종종 동일한 빈도로 클릭합니다(예: 정확히 2초마다), 반면 사람은 무작위로 클릭합니다.
- 타이핑 속도 일관성 — 텍스트 입력 속도. 봇은 텍스트를 즉시 입력하거나 문자 간의 일정한 지연으로 입력하지만, 사람은 변동적인 속도와 일시 정지를 가집니다.
- 마우스 이동 속도 — 커서의 이동 속도. Selenium은 기본적으로 커서를 필요한 지점으로 즉시 이동시키지만, 사람은 가속과 감속으로 마우스를 이동합니다.
- 스크롤 행동 — 페이지 스크롤 패턴. 봇은 종종 고정된 픽셀 수만큼 스크롤하지만, 사람은 불규칙하게 스크롤하며 멈춤이 있습니다.
탐지 시스템은 이러한 메트릭을 분석하기 위해 머신 러닝을 사용합니다. 그들은 행동 프로필을 구축하고 사용자가 봇일 확률을 계산합니다. 시간 패턴이 너무 완벽하거나 너무 빠르면 이는 경고 신호입니다.
중요: 타이밍 공격은 대량 자동화에 특히 효과적입니다. 동일한 시간 패턴으로 100개의 브라우저를 실행하면 안티프로드 시스템은 통계적 이상으로 쉽게 탐지할 수 있습니다.
타이밍 패턴을 통한 자동화 탐지 방법
현대의 안티프로드 시스템은 시간 특성을 분석하기 위해 여러 층의 분석을 사용합니다. Facebook, Google, Cloudflare 및 기타 플랫폼에서 사용하는 구체적인 기술을 살펴보겠습니다.
1. 성능 API 분석
브라우저는 페이지 로딩에 대한 상세한 텔레메트리를 수집하는 성능 API를 제공합니다. 안티프로드 시스템은 다음을 분석합니다:
// 성능 API 데이터 예시
performance.timing = {
navigationStart: 1234567890000,
domLoading: 1234567890150, // +150ms
domInteractive: 1234567890300, // +300ms
domComplete: 1234567890500, // +500ms
loadEventEnd: 1234567890600 // +600ms
}
// 봇을 위한 의심스러운 패턴:
// - 너무 빠른 로딩 (domComplete < 200ms)
// - 이벤트 간의 완벽하게 일정한 간격
// - 외부 리소스 로딩에 지연 없음
헤드리스 브라우저(특히 구버전의 Puppeteer 및 Selenium)는 일반 브라우저와 동일한 방식으로 이미지, 글꼴 및 기타 리소스를 로드하지 않기 때문에 navigationStart 및 domLoading 값이 비정상적으로 빠르게 나타나는 경우가 많습니다.
2. 이벤트 타이밍 분석
JavaScript 추적기는 모든 이벤트(클릭, 마우스 움직임, 키 입력)의 타임스탬프를 추적하고 패턴을 분석합니다:
// 이벤트 텔레메트리 수집 예시
const events = [];
document.addEventListener('click', (e) => {
events.push({
type: 'click',
timestamp: performance.now(),
x: e.clientX,
y: e.clientY
});
});
// 의심스러운 패턴 분석:
// - 클릭이 정확히 N 밀리초마다 발생
// - 클릭 전에 마우스의 미세한 움직임이 없음
// - 첫 클릭이 페이지 로딩 직후 즉시 발생
3. 키 입력 동역학
양식을 작성할 때 안티프로드 시스템은 키 입력의 동역학을 분석합니다 — 각 사람의 독특한 생체 지표입니다:
- 유지 시간 — 키를 누르고 있는 시간 (keydown부터 keyup까지). 사람은 50-200ms의 변동을 가지며, 봇은 일정합니다.
- 비행 시간 — 한 키를 놓고 다음 키를 누르기까지의 시간. 사람은 100-500ms의 변동을 가지며, 봇은 고정된 지연을 가집니다.
- 타이핑 리듬 — 전체 타이핑 리듬. 사람은 구두점에서 일시 정지를 하고, 오류를 수정하지만, 봇은 그렇지 않습니다.
탐지 예시: Selenium에서 element.send_keys("텍스트")를 사용하면 모든 텍스트가 1-2 밀리초 안에 입력됩니다 — 이는 자동화를 즉시 드러냅니다.
코드에서 인간과 유사한 지연 시뮬레이션
타이밍 공격에 대한 첫 번째 방어 수준은 행동 간의 지연을 추가하는 것입니다. 그러나 단순히 time.sleep(2)를 삽입하는 것이 아니라 자연스러운 행동을 시뮬레이션하는 것이 중요합니다.
Python에서의 기본 지연 시뮬레이션 (Selenium)
import time
import random
from selenium import webdriver
from selenium.webdriver.common.by import By
def human_delay(min_sec=0.5, max_sec=2.0):
"""사람을 시뮬레이션하는 무작위 지연"""
delay = random.uniform(min_sec, max_sec)
time.sleep(delay)
driver = webdriver.Chrome()
driver.get("https://example.com")
# 첫 행동 전 지연 (사람이 페이지를 읽음)
human_delay(1.5, 4.0)
# 요소 클릭
button = driver.find_element(By.ID, "submit-btn")
button.click()
# 다음 행동 전 지연
human_delay(0.8, 2.5)
정규 분포를 통한 고급 시뮬레이션
균일 분포는 자연스럽지 않습니다. 인간의 지연은 이상치가 있는 정규 분포를 따릅니다:
import numpy as np
def realistic_delay(mean=1.5, std_dev=0.5, min_val=0.3, max_val=5.0):
"""
정규 분포에 따른 지연
mean: 평균 지연 시간
std_dev: 표준 편차
min_val, max_val: 경계 (극단적인 값을 피하기 위해)
"""
delay = np.random.normal(mean, std_dev)
delay = max(min_val, min(max_val, delay)) # 범위 제한
time.sleep(delay)
return delay
# 사용 예
realistic_delay(mean=2.0, std_dev=0.7) # 평균 2초, 변동 포함
맥락 지연
다양한 행동은 서로 다른 시간이 필요합니다. 다양한 시나리오에 대한 지연 프로필을 생성하세요:
class HumanBehavior:
"""다양한 유형의 행동에 대한 지연 프로필"""
@staticmethod
def page_load_delay():
"""페이지 로딩 후 지연 (콘텐츠 읽기)"""
return realistic_delay(mean=2.5, std_dev=1.0, min_val=1.0, max_val=6.0)
@staticmethod
def before_click():
"""클릭 전 지연 (눈으로 요소 찾기)"""
return realistic_delay(mean=0.8, std_dev=0.3, min_val=0.3, max_val=2.0)
@staticmethod
def before_typing():
"""텍스트 입력 시작 전 지연"""
return realistic_delay(mean=1.2, std_dev=0.5, min_val=0.5, max_val=3.0)
@staticmethod
def between_form_fields():
"""양식 필드 간 지연"""
return realistic_delay(mean=0.6, std_dev=0.2, min_val=0.2, max_val=1.5)
# 스크립트에서 사용
driver.get("https://example.com/login")
HumanBehavior.page_load_delay()
username_field = driver.find_element(By.ID, "username")
HumanBehavior.before_typing()
# ... 로그인 입력 ...
HumanBehavior.between_form_fields()
password_field = driver.find_element(By.ID, "password")
HumanBehavior.before_typing()
# ... 비밀번호 입력 ...
작업 실행 시간의 무작위화
행동 간 동일한 지연은 통계적 이상입니다. 스크립트의 100개 인스턴스를 실행하고 모두 페이지 로딩 후 정확히 2.5초 후에 클릭하면 쉽게 탐지됩니다. 여러 수준에서 무작위화가 필요합니다.
1. 행동 순서의 무작위화
행동의 순서에 변동성을 추가하세요. 예를 들어, 양식을 작성하기 전에 가끔 페이지를 스크롤하거나 가끔 스크롤하지 않을 수 있습니다:
def fill_form_naturally(driver):
# 양식 작성 전에 페이지를 스크롤할 확률 30%
if random.random() < 0.3:
driver.execute_script("window.scrollBy(0, 200)")
human_delay(0.5, 1.5)
# 무작위 위치를 클릭할 확률 20% (읽기 시뮬레이션)
if random.random() < 0.2:
body = driver.find_element(By.TAG_NAME, "body")
body.click()
human_delay(0.3, 0.8)
# 주요 행동 — 양식 작성
username_field = driver.find_element(By.ID, "username")
type_like_human(username_field, "myusername")
2. 변동적인 타이핑 속도
즉시 텍스트를 입력하는 대신, 변동적인 속도로 문자 단위로 입력을 시뮬레이션하세요:
def type_like_human(element, text):
"""인간의 타이핑 속도를 시뮬레이션하여 텍스트 입력"""
for char in text:
element.send_keys(char)
# 문자 간 기본 지연
base_delay = random.uniform(0.05, 0.15)
# 공백 및 구두점에서 추가 지연
if char in [' ', '.', ',', '!', '?']:
base_delay += random.uniform(0.1, 0.3)
# 무작위 "생각하는 시간" (5% 확률로 긴 지연)
if random.random() < 0.05:
base_delay += random.uniform(0.5, 1.5)
time.sleep(base_delay)
# 가끔 오타를 내고 수정 (10% 확률)
if random.random() < 0.1:
time.sleep(random.uniform(0.2, 0.5))
element.send_keys(Keys.BACKSPACE)
time.sleep(random.uniform(0.1, 0.3))
element.send_keys(text[-1]) # 마지막 문자를 다시 입력
3. Puppeteer: 느린 텍스트 입력
Puppeteer에는 delay 옵션이 내장되어 있지만, 이를 무작위화해야 합니다:
// 기본 사용 (권장하지 않음 — 고정 지연)
await page.type('#username', 'myusername', { delay: 100 });
// 올바른 접근 — 각 문자에 대해 무작위화
async function typeWithVariableSpeed(page, selector, text) {
await page.click(selector);
for (const char of text) {
await page.keyboard.type(char);
// 50-150ms의 무작위 지연
let delay = Math.random() * 100 + 50;
// 공백에서 추가 지연
if (char === ' ') {
delay += Math.random() * 200 + 100;
}
// 무작위 긴 지연 (5% 확률)
if (Math.random() < 0.05) {
delay += Math.random() * 1000 + 500;
}
await page.waitForTimeout(delay);
}
}
// 사용 예
await typeWithVariableSpeed(page, '#username', 'myusername');
자연스러운 마우스 움직임 및 스크롤 속도
Selenium과 Puppeteer는 기본적으로 마우스 커서를 움직이지 않고 필요할 때 즉시 원하는 지점으로 텔레포트합니다. 이는 자동화의 가장 명백한 징후 중 하나입니다. 인간의 마우스 움직임을 시뮬레이션하려면 특별한 라이브러리가 필요합니다.
부드러운 마우스 움직임을 위한 pyautogui 라이브러리
pyautogui 라이브러리를 사용하면 가속 및 감속을 통해 베지어 곡선을 따라 커서를 이동할 수 있습니다:
import pyautogui
from selenium.webdriver.common.action_chains import ActionChains
def move_mouse_naturally(driver, element):
"""사람을 시뮬레이션하여 요소로 부드럽게 마우스를 이동"""
# 요소의 좌표 가져오기
location = element.location
size = element.size
# 목표 지점 (요소의 중심 + 약간의 무작위성)
target_x = location['x'] + size['width'] / 2 + random.randint(-5, 5)
target_y = location['y'] + size['height'] / 2 + random.randint(-5, 5)
# 가변 속도로 부드럽게 이동
# duration — 이동 시간 (자연스러움을 위해 0.5-1.5초)
duration = random.uniform(0.5, 1.5)
# tweening — 가속 함수 (easeInOutQuad는 인간의 움직임을 시뮬레이션)
pyautogui.moveTo(target_x, target_y, duration=duration, tween=pyautogui.easeInOutQuad)
# 클릭 전 약간의 지연 (사람은 즉시 클릭하지 않음)
time.sleep(random.uniform(0.05, 0.15))
# 클릭
element.click()
중요: 이 방법은 Selenium이 실제 브라우저 창을 제어할 때만 작동합니다(헤드리스 모드 아님). 헤드리스 모드에서는 마우스 움직임이 무의미합니다. 안티프로드 시스템은 커서를 볼 수 없기 때문입니다.
Puppeteer: 마우스 움직임 시뮬레이션
Puppeteer에서는 ghost-cursor 라이브러리를 사용하여 커서를 자연스럽게 움직일 수 있습니다:
// 설치: npm install ghost-cursor
const { createCursor } = require("ghost-cursor");
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
const cursor = createCursor(page);
await page.goto("https://example.com");
// 요소로 부드럽게 이동하고 클릭
const button = await page.$("#submit-btn");
await cursor.click(button); // 커서가 베지어 곡선을 따라 이동합니다!
// 또는 — 좌표로 이동
await cursor.move("#username"); // 클릭 없이 커서를 이동
await page.waitForTimeout(300);
await cursor.click(); // 현재 위치에서 클릭
})();
스크롤 시뮬레이션
사람은 한 번에 정확히 500픽셀을 스크롤하지 않습니다. 스크롤은 불규칙해야 하며, 일시 정지와 가끔 뒤로 스크롤이 포함되어야 합니다:
def scroll_like_human(driver, target_position=None):
"""
인간의 스크롤 시뮬레이션
target_position: 픽셀 단위의 목표 위치 (None인 경우 페이지 끝까지 스크롤)
"""
current_position = driver.execute_script("return window.pageYOffset;")
if target_position is None:
# 페이지 끝까지 스크롤
target_position = driver.execute_script("return document.body.scrollHeight;")
while current_position < target_position:
# 무작위 스크롤 단계 (100-400픽셀)
scroll_step = random.randint(100, 400)
current_position += scroll_step
# 스크롤
driver.execute_script(f"window.scrollTo(0, {current_position});")
# 스크롤 간의 일시 정지 (사람이 콘텐츠를 읽음)
time.sleep(random.uniform(0.3, 1.2))
# 가끔 뒤로 스크롤 (10% 확률)
if random.random() < 0.1:
back_scroll = random.randint(50, 150)
current_position -= back_scroll
driver.execute_script(f"window.scrollTo(0, {current_position});")
time.sleep(random.uniform(0.2, 0.6))
# 사용 예
scroll_like_human(driver, target_position=2000) # 2000px까지 스크롤
페이지 및 AJAX 요청의 로딩 시간
안티프로드 시스템은 사용자의 행동뿐만 아니라 페이지 로딩 특성도 분석합니다. 헤드리스 브라우저는 종종 비정상적으로 빠르게 로드되며, 이미지 로딩, 일부 스크립트 실행 및 CSS 렌더링을 수행하지 않기 때문입니다.
문제: 너무 빠른 로딩
일반 브라우저와 헤드리스 브라우저의 성능 API에 대한 일반적인 값을 비교해 보세요:
| 메트릭 | 일반 브라우저 | 헤드리스 (의심스러운) |
|---|---|---|
| domContentLoaded | 800-2000 ms | 50-200 ms |
| loadEventEnd | 2000-5000 ms | 100-500 ms |
| 로드된 리소스 수 | 50-200 (이미지, CSS, JS) | 5-20 (중요한 것만) |
해결책: 로딩 지연 강제 적용
페이지 로딩 후 인위적인 지연을 추가하여 메트릭이 더 자연스럽게 보이도록 하세요:
def load_page_naturally(driver, url):
"""자연스러운 로딩 시간을 시뮬레이션하여 페이지 로드"""
start_time = time.time()
driver.get(url)
# DOM이 완전히 로드될 때까지 대기
WebDriverWait(driver, 10).until(
lambda d: d.execute_script("return document.readyState") == "complete"
)
# 실제 로딩 시간 계산
actual_load_time = time.time() - start_time
# 로딩이 너무 빠른 경우(< 1초), 지연 추가
if actual_load_time < 1.0:
additional_delay = random.uniform(1.0, 2.5) - actual_load_time
time.sleep(additional_delay)
# "페이지 읽기"를 위한 추가 지연
time.sleep(random.uniform(0.5, 2.0))
# 사용 예
load_page_naturally(driver, "https://example.com")
AJAX 요청 대기
현대 웹사이트는 AJAX를 통해 콘텐츠를 비동기적으로 로드합니다. 스크립트가 모든 AJAX 요청이 완료되기 전에 작동하기 시작하면 의심스럽습니다. 명시적 대기를 사용하세요:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def wait_for_ajax(driver, timeout=10):
"""모든 AJAX 요청 완료 대기 (jQuery)"""
WebDriverWait(driver, timeout).until(
lambda d: d.execute_script("return jQuery.active == 0")
)
# jQuery가 없는 사이트의 경우 — 특정 요소 대기
def wait_for_dynamic_content(driver, selector, timeout=10):
"""동적으로 로드된 요소의 등장 대기"""
WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((By.CSS_SELECTOR, selector))
)
# 요소가 나타난 후 추가 지연
time.sleep(random.uniform(0.3, 0.8))
안티탐지 브라우저에서 보호 설정
중재, 다중 계정 관리 또는 익명성이 중요한 기타 작업을 수행하는 경우 안티탐지 브라우저를 사용하세요: Dolphin Anty, AdsPower, Multilogin, GoLogin. 이들은 타이밍 공격에 대한 내장 보호 메커니즘을 가지고 있지만, 올바르게 설정해야 합니다.
Dolphin Anty: 인간 타이핑 설정
Dolphin Anty에는 인간의 타이핑을 자동으로 시뮬레이션하는 "인간 타이핑" 기능이 있습니다. 설정 방법:
- 브라우저 프로필 열기 → "자동화" 탭
- "인간 타이핑 에뮬레이션" 활성화
- 설정 조정:
- 평균 타이핑 속도: 150-250자/분 (자연스러운 속도)
- 변동: 30-50% (문자 간 속도 차이)
- 구두점에서의 일시 정지: 활성화 (구두점에서 일시 정지)
- 무작위 오타: 2-5% (무작위 오타 수정)
이후 Dolphin API를 통한 모든 텍스트 입력은 자동으로 인간을 시뮬레이션합니다.
AdsPower: 마우스 움직임 설정
AdsPower는 실제 사용자의 마우스 움직임 패턴을 기록하고 재생할 수 있습니다:
- 프로필 열기 → "고급 설정" → "마우스 행동"
- "실제 사용자 기록" 모드 선택:
- 일반 모드에서 브라우저 열기
- 일반적인 행동 수행 (클릭, 스크롤, 마우스 움직임)
- AdsPower가 움직임 경로를 기록합니다.
- API를 통한 자동화 시 AdsPower는 기록된 패턴을 변동과 함께 재생합니다.
Multilogin: 캔버스 노이즈 및 WebGL 타이밍
Multilogin은 캔버스 및 WebGL 지문에 노이즈를 추가하여 렌더링과 관련된 타이밍 공격을 방지합니다:
- 프로필 → "지문 설정" → "캔버스"
- "캔버스 노이즈" 활성화 (캔버스 렌더링에 미세 지연 추가)
- "WebGL 메타데이터 마스킹" 활성화 (렌더링 속도에 영향을 미치는 GPU 특성 마스킹)
이는 Canvas.toDataURL() 및 WebGL 작업의 실행 시간 분석을 통한 탐지를 방지합니다.
추천: Facebook, Instagram 또는 TikTok에서 다중 계정을 운영하는 경우, 반드시 고품질의 주거용 프록시와 함께 안티탐지 브라우저를 사용하세요 — 이는 체인 밴 및 IP 탐지 위험을 최소화합니다.
타이밍 탐지를 우회하는 고급 기술
특히 보호가 강화된 플랫폼(Google, Facebook, 은행 웹사이트)의 경우, 기본 방법만으로는 부족할 수 있습니다. 고급 기술을 살펴보겠습니다.
1. 성능 API 변조
성능 API의 메서드를 재정의하여 실제 값 대신 현실적인 값을 반환하도록 할 수 있습니다:
// performance.now() 변조를 위한 스크립트 주입
const script = `
(function() {
const originalNow = performance.now.bind(performance);
let offset = 0;
let lastValue = 0;
performance.now = function() {
const realValue = originalNow();
// 시간에 무작위 노이즈 추가
const noise = Math.random() * 2 - 1; // -1에서 +1ms까지
let fakeValue = realValue + offset + noise;
// 단조성 보장 (시간이 뒤로 가지 않도록)
if (fakeValue <= lastValue) {
fakeValue = lastValue + 0.1;
}
lastValue = fakeValue;
return fakeValue;
};
})();
`;
// Puppeteer: 페이지 생성 시 주입
await page.evaluateOnNewDocument(script);
주의: 이 방법은 기본 메서드의 무결성 검사를 통해 탐지될 수 있습니다. 강력한 보호가 없는 사이트에서만 사용하세요.
2. CPU 및 네트워크 제한
Chrome DevTools 프로토콜을 사용하여 CPU와 네트워크를 인위적으로 느리게 하여 로딩 메트릭이 더 자연스럽게 보이도록 할 수 있습니다:
// Puppeteer: CPU를 2배 느리게
const client = await page.target().createCDPSession();
await client.send('Emulation.setCPUThrottlingRate', { rate: 2 });
// 네트워크 느리게 하기 (3G 에뮬레이션)
await page.emulateNetworkConditions({
offline: false,
downloadThroughput: 1.5 * 1024 * 1024 / 8, // 1.5 Mbps
uploadThroughput: 750 * 1024 / 8, // 750 Kbps
latency: 40 // 40ms 지연
});
이는 페이지 로딩 시간과 JavaScript 실행 시간을 증가시켜 프로필이 평균 인터넷 속도를 가진 실제 사용자와 더 유사해지도록 합니다.
3. 배경 활동 시뮬레이션
실제 사용자는 한 탭에만 머무르지 않고 탭을 전환하고 창을 최소화하며 주의가 분산됩니다. 이를 시뮬레이션하세요:
async function simulateTabSwitch(page) {
// 다른 탭으로 전환 시뮬레이션 (Page Visibility API)
await page.evaluate(() => {
Object.defineProperty(document, 'hidden', {
get: () => true,
configurable: true
});
document.dispatchEvent(new Event('visibilitychange'));
});
// 일시 정지 (사용자가 다른 탭을 보고 있음)
await page.waitForTimeout(Math.random() * 3000 + 2000);
// 탭으로 돌아가기
await page.evaluate(() => {
Object.defineProperty(document, 'hidden', {
get: () => false,
configurable: true
});
document.dispatchEvent(new Event('visibilitychange'));
});
}
// 사용 예: 작업 중 무작위로 "주의를 분산"
if (Math.random() < 0.15) { // 15% 확률
await simulateTabSwitch(page);
}
4. 실제 사용자 타이밍 마크 사용
일부 웹사이트는 User Timing API를 통해 자체 타이밍 마크를 생성합니다. 현실적인 마크를 추가하세요:
// 현실적인 타이밍 마크 생성
await page.evaluate(() => {
// 행동 전 사용자의 "생각" 시뮬레이션
performance.mark('user-started-reading');
setTimeout(() => {
performance.mark('user-found-button');
performance.measure('reading-time', 'user-started-reading', 'user-found-button');
}, Math.random() * 2000 + 1000);
});
5. 통계적 상관관계 감소를 위한 프록시 회전
각 스크립트 인스턴스가 무작위화된 지연을 가지고 있더라도, 모든 요청이 동일한 IP에서 발생하면 안티프로드 시스템이 상관관계를 탐지할 수 있습니다. 프록시 회전을 사용하세요:
- 파싱 및 대량 작업의 경우: 데이터 센터 프록시를 5-10분마다 자동으로 회전
- 소셜 미디어 및 광고 작업의 경우: 주거용 프록시를 세션에 바인딩 (sticky sessions)
- 모바일 플랫폼 (Instagram, TikTok)의 경우: 모바일 프록시를 타이머 또는 요청에 따라 회전
IP 회전은 안티프로드 시스템이 타이밍 패턴에 대한 통계적 분석을 수행할 수 있는 충분한 데이터를 수집할 가능성을 줄입니다.
결론
타이밍 공격은 자동화 탐지의 복잡한 방법으로, 방어에 대한 종합적인 접근이 필요합니다. 주요 결론은 다음과 같습니다:
- 고정 지연을 사용하지 마세요 — 항상 행동 간 시간을 정규 분포를 사용하여 무작위화하세요.
- 맥락 지연을 시뮬레이션하세요 — 서로 다른 행동은 서로 다른 시간이 필요합니다 (페이지 읽기 ≠ 버튼 클릭).
- 행동 순서에 변동성을 추가하세요 — 무작위 스크롤, 클릭, 탭 전환.
- 부드러운 마우스 움직임을 사용하세요 — ghost-cursor (Puppeteer) 또는 pyautogui (Selenium) 라이브러리.
- 자연스러운 타이핑 속도를 시뮬레이션하세요 — 구두점에서의 일시 정지를 포함한 문자 단위 입력.
- 안티탐지 브라우저를 설정하세요 — Dolphin Anty, AdsPower 및 Multilogin은 타이밍 공격에 대한 내장 보호 메커니즘을 가지고 있습니다.
- 고품질 프록시와 결합하세요 — IP 회전은 통계적 분석 가능성을 줄입니다.
기억하세요: 완벽한 보호는 존재하지 않습니다. 안티프로드 시스템은 지속적으로 진화하며 새로운 탐지 방법을 추가합니다. 여러분의 임무는 스크립트의 행동을 실제 사용자에 최대한 가깝게 만들고 우회 방법을 정기적으로 업데이트하는 것입니다.
브라우저 자동화를 통해 파싱, 테스트 또는 기타 작업을 수행하는 경우, 주거용 프록시를 사용하는 것이 좋습니다 — 이는 최대한의 익명성을 보장하고 IP 주소에 의한 탐지 위험을 최소화합니다. 모바일 플랫폼에는 실제 모바일 운영자의 사용자처럼 시뮬레이션하는 모바일 프록시가 더 적합합니다.