어떤 AI 봇이 당신을 방문하는지 알아내는 방법
요약
User-agent 헤더만으로는 AI 크롤러의 신원을 정확히 식별할 수 없으며, 사칭으로 인한 데이터 왜곡과 차단 우회 문제가 발생합니다. 이를 해결하기 위해 역방향 DNS 방식 외에도 OpenAI, Anthropic 등이 사용하는 공개된 IP 주소 범위(CIDR) 검증 방식을 병행해야 합니다.
핵심 포인트
- User-agent는 위조가 가능하여 트래픽 보고서 왜곡 및 차단 우회를 초래함
- Google/Bing과 달리 OpenAI, Anthropic 등은 IP 주소 범위 검증 방식을 사용함
- 역방향 DNS만 의존할 경우 실제 AI 크롤러를 사칭으로 오판할 위험이 있음
- 운영자는 각 크롤러 제공자의 최신 IP 범위 파일을 직접 확인하여 검증해야 함
User-agent 헤더는 클라이언트가 선택한 문자열입니다. 누구나 GPTBot을 보낼 수 있으며, 실제로 많은 이들이 속도 제한(rate limits)을 우회하거나, 타인의 robots.txt 처리 방식을 테스트하거나, 스크래핑(scraping)을 공식적인 것처럼 보이게 하기 위해 그렇게 합니다. 실제로 누가 당신을 방문했는지 알기 위해서는 검증이 필요하며, 역방향 DNS(reverse DNS)를 사용하라는 표준적인 조언은 Google과 Bing에는 맞지만, 이 클러스터에 속한 대부분의 크롤러(crawlers)에게는 틀린 방법입니다.
User agent만으로는 답이 되지 않는 이유
robots.txt 페이지에 있는 것을 포함하여 공개된 모든 AI 크롤러(AI crawler) user agent 표는 모범적인 클라이언트가 보내는 문자열 목록입니다. 그것은 신원(identity)이 아닙니다. 이로 인해 발생하는 세 가지 구체적인 결과는 다음과 같습니다:
- 사칭꾼들에 의해 트래픽 보고서가 부풀려집니다. 실제로는 누군가의 스크래퍼(scraper)인 자가 스스로
ClaudeBot이라고 선언하면, 당신의 사이트에 대한 AI의 관심에 대한 증거로 집계되며, 그 수치로부터 도출된 모든 결론은 잘못된 것이 됩니다. - 차단 목록(block list)이 너무나 쉽게 우회됩니다. 특정 토큰에 대한 robots.txt 규칙은 정직하게 자신을 밝히는 클라이언트만을 차단하며, 이들은 어차피 규칙을 준수했을 집단입니다.
- 실제 부하가 잘못 할당됩니다. 검증되지 않은 사칭꾼이 당신을 공격하고 있다면, 지목된 운영자에게 책임을 돌리는 것은 잘못된 해결책으로 인도합니다. 즉, 속도 제한(rate limit)을 설정하는 대신 불만을 제기하게 만듭니다.
하나가 아닌, 두 가지 검증 체계
이 부분이 표준적인 설명들이 틀리는 지점입니다. 운영자들이 요청이 진짜인지 확인할 수 있도록 제공하는 메커니즘은 두 가지가 있으며, 이들은 서로 대체될 수 없습니다.
| 체제 (Regime) | 설명 |
|---|---|
| Forward-confirmed reverse DNS | 운영자가 자신이 제어하는 도메인 아래에 역방향 DNS (reverse-DNS) 레코드를 등록합니다. IP에 대해 역방향 조회 (reverse-look-up)를 수행하여 호스트 이름이 해당 도메인으로 끝나는지 확인한 다음, 호스트 이름을 정방향 조회 (forward-resolve)하여 원래의 IP가 응답에 포함되어 있는지 확인합니다. Google과 Bing은 수년 동안 이 방식을 문서화해 왔습니다. |
| Published address ranges | 운영자가 크롤러 (crawler)에 사용하는 CIDR 블록을 기계 판독 가능한 파일로 공개합니다. 해당 파일을 가져와 캐싱한 뒤 멤버십을 테스트합니다. OpenAI, Anthropic, Perplexity, Apple이 크롤러를 위해 사용하는 방식입니다. |
잘못된 방식을 사용하면 확신에 찬 오답을 내놓게 됩니다. OpenAI 크롤러 주소에 대해 역방향 조회 (reverse lookup)를 수행하면 일반적으로 일반적인 클라우드 호스트 이름이 반환되거나 아무것도 반환되지 않으며, "역방향 DNS가 일치하지 않음"을 "사칭"으로 취급하는 스크립트는 모든 실제 요청을 가짜로 표시할 것입니다. 따라서 아래의 파서 (parser)는 하나의 전역적인 방식 대신 운영자별 검증 방법을 사용합니다.
각 운영자의 범위 파일 (range file)에 대한 정확한 URL은 이 글을 포함한 그 어떤 기사에서 읽기보다는 해당 운영자의 최신 크롤러 문서에서 직접 읽어야 합니다. 경로가 변경되었을 수 있으며, 오래된 URL에서 가져온 범위 파일은 아무런 검증도 수행하지 못한 채 조용히 통과될 뿐입니다. 아래의 스크립트가 이를 설정값으로 받는 이유도 바로 이 때문입니다.
질문에 답할 수 있는 로그 확보하기
이 작업이 가능한지 여부는 두 가지 필드, 즉 클라이언트 주소 (client address)와 사용자 에이전트 문자열 (user-agent string)에 의해 결정됩니다. 많은 기본 설정들이 이 중 하나 또는 둘 모두를 누락하며, 오리진 (origin) 앞의 CDN은 전달된 헤더 (forwarded header)를 읽지 않는 한 클라이언트 주소를 자신의 주소로 대체합니다.
# nginx: combined 형식은 이미 두 가지를 모두 포함합니다.
log_format combined '$remote_addr - $remote_user [$time_local] '
"$request" $status $body_bytes_sent '
...
Caddy는 기본적으로 JSON lines 형식을 작성하며, 이는 파싱(parse)하기 더 쉽고 아래 스크립트가 두 가지 입력 형식 중 하나로 가정하는 방식입니다. 어떤 형식을 사용하든 보관 주기(retention)를 확인하세요. 크롤링 속도(crawl-rate)에 대한 질문에 답할 수 있는 최소 기간은 30일이며, 90일이 더 좋습니다. 왜냐하면 흥미로운 비교 대상은 대개 지난 분기의 동일한 주(week)이기 때문입니다.
파서 (The parser)
의존성(dependencies)이 없는 Node.js 환경에서 동작합니다. 토큰(token)별로 분류한 다음, 운영자가 사용하는 체계에 따라 각 고유 주소를 한 번씩 검증하고, 결과를 캐싱(cache)하며, 에이전트(agent)별로 검증된 항목과 검증되지 않은 항목을 보고합니다.
#!/usr/bin/env node
// crawler-audit.mjs — 실제로 누가 우리를 가져갔으며, 그들은 진짜였는가?
// node crawler-audit.mjs access.log
...
unknown 컬럼은 이 스크립트의 정직한 부분이며, 더 단순한 스크립트를 복사하는 대신 이 스크립트를 실행할 가치가 있는 이유입니다. 확인할 수 없는 주소는 가짜(fake)가 아니라 확인되지 않음(unchecked)으로 보고됩니다. 이 두 상태를 하나로 합쳐버리는 도구는 당신의 AI 트래픽 대부분이 사기(fraudulent)라고 말하겠지만, 이는 근거 없는 주장입니다.
순방향 확인 역방향 DNS (Forward-confirmed reverse DNS), 상세 설명
역방향 DNS(Reverse DNS) 자체만으로는 아무것도 증명할 수 없습니다. 주소 블록의 소유자는 PTR 레코드(PTR records)를 제어할 수 있으며 그곳에 어떤 호스트 이름(hostname)이든 넣을 수 있기 때문입니다. 순방향 확인(forward-confirmation) 단계가 바로 이를 증거로 만드는 핵심입니다.
- 주소를 역방향 조회(Reverse-look-up)합니다.
dig -x 66.249.66.1 +short는crawl-66-249-66-1.googlebot.com과 같은 호스트 이름을 반환합니다. - 호스트 이름이 운영자가 문서화한 도메인으로 끝나는지 확인합니다.
.googlebot.com으로 끝나는지가 확인 기준입니다. 단순히
# 전체 확인 과정을 쉘 원라이너(one-liner)로 작성
ip=66.249.66.1
host=$(dig -x "$ip" +short | sed 's/\.$//')
...
공개된 주소 범위(address ranges) 매칭하기
범위(ranges)를 공개하는 운영자들의 경우, 검증은 집합 멤버십 테스트(set membership test)로 이루어지며, 이는 DNS보다 빠르고 신뢰할 수 있습니다. 여기에는 두 가지 운영 규칙이 있습니다.
캐싱하되, 영원히 두지는 마십시오. 로그 라인이 발생할 때마다 범위 파일(range file)을 가져오는 것은 비효율적이며, 일 년에 한 번 가져오는 것은 더 나쁩니다. 범위는 계속 추가되기 때문입니다. 하루에 한 번이 합리적인 주기이며, 가져오기에 실패하더라도 소프트 실패(fail soft) 처리를 해야 합니다. 즉, 파일에 접근할 수 없다면 주소를 '가짜(fake)'로 분류하는 대신 '알 수 없음(unknown)'으로 처리해야 합니다.
IPv6를 처리하십시오. 위의 스크립트는 IPv4 산술 연산을 완벽하게 수행하지만 IPv6는 건너뜁니다. 이는 실제적인 한계이며, 숨기기보다는 명시적으로 밝히고 있습니다. 크롤러 트래픽의 상당 부분이 IPv6를 통해 들어오므로, 만약 로그에 IPv6가 포함되어 있다면 검증된 주소와 알 수 없는 주소의 비율에 대해 결론을 내리기 전에 128비트 형식에서 작동하도록 비교 범위를 확장하십시오.
만약 단순히 감사(auditing)하는 것이 아니라 강제 적용(enforcing)하는 단계라면, 동일한 범위 파일이 방화벽이나 CDN 규칙에 직접 입력되며, 실제 결정이 내려지는 계층은 바로 그곳입니다. robots.txt는 요청(request)이지만, 주소 규칙은 제어(control)입니다.
결과 읽기
보고서에는 살펴볼 가치가 있는 네 가지 항목이 있으며, 순서는 다음과 같습니다.
- 에이전트별 상태 코드(status-code) 라인. 주로 404 오류를 받는 크롤러는 이미 삭제된 URL을 크롤링하고 있는 것이며, 429 또는 5xx 오류를 받는 크롤러는 속도 제한(rate-limited)으로 인해 사이트의 불완전한 모습만을 수집하고 있는 것입니다. 이는 나중에 콘텐츠 누락이나 오류 미표시 문제로 나타나게 됩니다.
- 최상위 경로(top path). 만약 이 경로가 필터 조합(filter permutation), 검색 결과 페이지 또는 달력이라면, 이는 크롤 트랩(crawl trap)에 빠진 것입니다. 해결책은 에이전트를 차단하는 것이 아니라, robots.txt에 좁은 범위의
Disallow패턴을 설정하는 것입니다. - 가짜(fake) 컬럼. 공개된 검증 메커니즘이 있는 에이전트에 대해 이 값이 0이 아니라면, 누군가 해당 토큰을 스푸핑(spoofing)하여 당신을 속이고 있다는 의미입니다. 행동 기반으로 속도 제한(rate-limit)을 적용하되, 운영자에게 문제를 제기하지 마세요. 그들의 잘못이 아니기 때문입니다.
- 대량 에이전트(bulk agents)에 대한 사용자 에이전트(User agents).
ChatGPT-User,Claude-User또는Perplexity-User로부터의 요청은 누군가가 지금 당장 질문을 던지고 있다는 뜻이며, 이들이 가져가는 경로는 검색 단계(retrieval stage)에서 당신의 페이지 중 어떤 것을 선택했는지를 보여주는 직접적인 지표입니다. 이는 어시스턴트가 인용 대상을 선택하는 방법에서 설명된 관찰 가능한 창(observable window)과 같습니다.
정직한 크롤러도 당신의 사이트를 다운시킬 수 있습니다
이 클러스터가 당신이 피하기를 가장 원하는 실패 사례는 통제 불능의 스크래퍼(rogue scraper)가 아닙니다. 그것은 문서화가 완벽히 되어 있고, 올바르게 식별되었으며, robots.txt를 준수하는 크롤러가 당신이 인지했던 것보다 훨씬 더 큰 URL 공간을 탐색하는 상황입니다.
그 양상은 항상 동일합니다. URL을 통해 어떤 페이지 필터가 적용됩니다. 예를 들어 속성(facets)이 있는 카탈로그, 달력, 또는 링크 가능한 결과를 생성하는 검색 양식 등이 있습니다. 모든 조합은 별개의 URL이 되며, 각각은 캐싱되지 않아 렌더링 비용이 많이 듭니다. 또한 그 숫자는 실제 페이지의 개수가 아니라 속성들의 곱(product)으로 늘어납니다. 해야 할 일을 정확히 수행하는 크롤러가 이 곱해진 경로들을 따라 걷게 되면, 렌더링 큐(queue)가 뒤섞이게 되고, 결국 크롤러를 포함한 모든 사용자에게 사이트가 느려지게 됩니다.
진단 결과는 위 보고서의 상단 경로(top-path) 열에 나타나며, 만약 당신이 이 글을 읽고 있다면 장애(outage)가 발생하기 전에 이미 도달해 있을 것입니다. 해결책은 에이전트(agent)를 차단하는 것이 아니라, 쿼리 스트링(query-string) 패턴에 대해 좁은 범위의 Disallow를 적용하는 것입니다. 왜냐하면 문제는 에이전트가 아니라, 경계가 없는 URL 공간(unbounded URL space)이기 때문입니다. 이것이 robots.txt 레시피에 표시된 Disallow: /models? 규칙의 근거이며, 무언가(크롤러)가 당신의 사이트를 찾아내기 전에 당신의 사이트도 동일한 형태를 띠고 있는지 확인해 볼 가치가 있습니다.
관련 항목
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기