스크래핑 프로젝트마다 사용하는 안티봇 탐지 체크리스트

발행: (2026년 6월 8일 PM 03:36 GMT+9)
6 분 소요
원문: Dev.to

소스: Dev.to

매 스크래핑 프로젝트 전에 사용하는 안티봇 탐지 체크리스트

제가 맡는 모든 스크래핑 프로젝트는 이 체크리스트부터 시작합니다. 제가 편집증이 있어서가 아니라, 실제로 운영 중인 스크래퍼가 조용히 실패한다는 것을 뼈저리게 배웠기 때문입니다. 200 OK를 반환하면서 쓰레기 데이터를 내보내거나, 점진적으로 레이트 제한에 걸려 며칠 동안 문제를 눈치채지 못합니다.
이것은 50개가 넘는 스크래핑 프로젝트를 통해 다듬은 체계적인 접근법입니다.

코드를 한 줄이라도 작성하기 전에, 마주하고 있는 상황을 확인하세요:

CDN 및 헤더 확인

curl -I https://target-site.com

다음과 같은 일반적인 보호 헤더를 찾아보세요:

# X-Engine: akamai-html-protection
# X-Served-By: DataDome
# cf-ray: Cloudflare
# X-Bot-Status: blocked

일반적인 보호 플랫폼:

  • Cloudflare → cf-ray 및 __cfduid 쿠키를 찾아보세요
  • DataDome → 헤더나 스크립트에 datadome이 있는지 확인
  • PerimeterX → _pxff 쿠키를 찾아보세요
  • Akamai → akamai-html-protection 헤더를 찾아보세요
curl https://target-site.com/robots.txt | grep -v "^#"

절대 절대적인 규칙으로 여기지는 마세요—하지만 좋은 신호가 됩니다. 만약 그들이 여러분의 사용 사례를 명시적으로 금지한다면, 이는 위험 신호입니다.

일부 사이트는 완전 정적(빠르고 간단)이며, 다른 사이트는 모든 것을 JavaScript로 렌더링합니다(Playwright/Puppeteer 필요). 확인해 보세요:

// 빠른 확인 - 원시 HTML과 렌더링된 콘텐츠가 크게 다른지 확인
// 차이가 크다면 JS 렌더링이 필요합니다
const https = require('https');
const html = await fetch('https://target.com').then(r => r.text());
const hasAngularVueReact = /ng-app|vue|react|__NEXT_DATA__/i.test(html);
console.log('Needs JS rendering:', hasAngularVueReact);
const USER_AGENTS = [
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120 Safari',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Edge/120',
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120 Firefox/120',
  // 실제와 같은 User‑Agent 10~15개 더 추가
];
// 실제와 같은 User‑Agent를 10~15개 정도 추가하세요

절대 단일 UA 문자열만 사용하지 마세요. 10개 이상의 현실적인 UA를 순환시켜 사용하세요.

async function scrapeWithRetry(url, maxRetries = 3) {
  for (let i = 0; i  !data[f]);

  if (missing.length > 0) {
    console.warn('Missing fields:', missing.join(', '));
    return false;
  }

  if (data.price && typeof data.price !== 'number') {
    console.warn('Invalid price type');
    return false;
  }

  return true;
}

스크래퍼가 쓰레기 데이터를 반환하기 시작하면 알림을 보내는 자동 건강 체크를 설정하세요:

// 매시간 실행
async function healthCheck() {
  const testUrl = 'https://target-site.com/product-page';
  const result = await scrape(testUrl);

  const blockType = detectBlock(result);
  if (blockType) {
    sendAlert(`Scraper blocked by ${blockType}!`);
    return false;
  }

  if (!validateData(result.parsed)) {
    sendAlert('Scraper returning invalid data!');
    return false;
  }

  return true;
}

가장 간과되기 쉬운 단계입니다. 파싱하기 전에 모든 응답을 원시 HTML로 저장하세요:

async function scrapeAndStore(url) {
  const response = await fetch(url);
  const raw = await response.text();

  // 디버깅을 위해 원시 데이터를 저장
  await db.rawResponses.insert({
    url,
    raw_html: raw,
    timestamp: new Date(),
    status: response.status
  });

  // 그 다음 파싱
  const parsed = parseHTML(raw);
  return parsed;
}

파서가 깨지면(분명 깨질 겁니다) 원시 데이터를 가지고 있으면 큰 도움이 됩니다.

프로덕션 수준의 스크래퍼는 단순히 코드가 아니라 시스템입니다:

  • 모니터링 → 알림 → 건강 체크 → 데이터 검증 → 백업 파서
    ↑ ↑ ↑ ↑
  • 주거용 프록시 ──────── 고정 세션 ──── 오류 처리

이 목록 중 세 가지만 구현한다면:

  • 주거용 프록시 (가장 큰 효과)
  • 차단 탐지 (조용한 실패 방지)
  • 원시 HTML 저장 (디버깅 가능)

나머지는 모두 점진적인 개선에 불과합니다.

특정 안티봇 시스템에 대한 질문이 있나요? 저는 모든 시스템을 다뤄봤습니다—댓글로 알려 주세요.

0 조회
Back to Blog

관련 글

더 보기 »