봇 트래픽과 사람 트래픽을 구분하는 방법

글 썸네일

사이트를 운영하다 보면 방문자 수가 갑자기 늘 때가 있다.
그런데 방문자는 증가하는데 유저의 상호작용이 없는 것 같다면, 먼저 의심해 볼 것이 있다.

늘어난 방문이 사람이 아닐 수 있다.

봇 트래픽, 즉 사람이 아니라 로봇에 의한 페이지 방문은 생각보다 흔하다.
보안 업체 Imperva는 2025년 보고서에서 2024년 웹 트래픽의 51%가 자동화 트래픽이었다고 밝혔다.


봇을 사람으로 착각하면 분석 지표를 잘못 읽게 되거나, 애드센스와 같은 광고를 붙인 사이트라면 광고 계정의 정책 리스크에도 영향을 끼칠 수 있다.

이 글에서는 GA4로 수상한 방문을 알아채고, 요청 기록을 남기고, 그 기록으로 봇을 판별하는 과정을 순서대로 정리했다.


봇 트래픽의 유형

봇이라고 다 막아야 하는 것은 아니다. 사이트에 들어오는 봇의 유형별 특징과 대응 기준은 아래 표와 같다.

유형예특징대응
검색 크롤러Googlebot, 네이버 Yeti, Bingbot이름을 밝히고 robots.txt를 지킨다허용
AI 크롤러GPTBot, ClaudeBot, PerplexityBot 등..이름을 밝히고 대량으로 읽어 간다사이트 방침에 따름
미리보기·감시 봇메신저 링크 미리보기, 업타임 감시링크가 공유되거나 정해진 주기로 들어온다허용
사람인 척하는 봇스크래퍼, 광고 사기 봇브라우저 이름을 달고 클라우드 서버에서 들어온다판별 대상

상기 3개의 유형은 대개 스스로 정직하게 봇이라고 밝힌다.
문제는 마지막 유형이다. 사람처럼 보이도록 꾸몄기 때문에, 방문 기록만으로는 사람과 구분되지 않는다.


GA4로 봇 트래픽 파악하기

GA4는 알려진 봇과 스파이더 트래픽을 자동으로 제외해주고 있다.
따라서 GA4에 남아 있는 봇 유입은 대개 사람인 척하는 봇일 가능성이 높다.

이럴 때에는 콘솔에서 국가, 기기 별로 데이터를 나눠서 유독 데이터가 튀는 그룹을 찾아보자.

1. 인구통계 세부정보 보고서 열기

왼쪽 메뉴에서 보고서 › 사용자 속성 › 인구통계 세부정보를 연다.
국가별 활성 사용자와 참여 지표가 표로 나온다.

GA4 인구통계 세부정보 메뉴
인구통계 세부정보 보고서 위치

2. 기기 카테고리 측정기준 추가

표의 국가 열 옆 + 버튼을 누르고 기기 카테고리를 고른다.
국가와 기기를 묶은 그룹별로 지표가 나뉜다.

GA4 기기 카테고리 측정기준 추가
기기 카테고리 측정기준 추가

3. 참여 지표가 유독 낮은 그룹 찾기

아래 지표가 다른 그룹보다 눈에 띄게 낮은 그룹이 의심 대상이다.

  1. 참여율: 다른 그룹보다 눈에 띄게 낮음
  2. 평균 참여 시간: 몇 초 수준
  3. 수입, 전환: 방문에 비해 거의 없음
GA4 국가·기기별 참여 지표 표
국가·기기별 참여 지표 비교

위 표의 미국·데스크톱 그룹은 참여율 56%, 평균 참여 시간 15초다.
같은 데스크톱인 한국 그룹(78%, 1분 19초)보다 확연히 낮다.

그 외 스크롤, 클릭 등 인간 유저들이 일반적으로 하는 '이벤트'를 일으키고 있는지 확인하면 좋다.
같은 표에서 이벤트 수 열 제목 아래의 "모든 이벤트"를 눌러 scroll을 고르면, 그룹별로 페이지를 끝까지 내려 본 횟수가 나온다.

GA4 국가·기기별 scroll 이벤트 표
국가·기기별 scroll 이벤트 비교

위 표에서 사용자 100명당 scroll은 미국·데스크톱이 약 2.6회, 한국·데스크톱이 약 5.0회다.
같은 데스크톱인데도 절반 수준이다.

다만 GA4는 의심까지만 할 수 있다.
요청이 어느 IP에서, 어느 통신사나 데이터센터를 거쳐, 어떤 헤더를 달고 왔는지는 보여 주지 않는다.
봇인지 판정하려면 요청 하나하나의 기록이 필요하다.


요청 기록 남기기

봇인지 판정하려면 요청 하나하나의 기록에 아래 값이 남아 있어야 한다.

  1. IP 주소: 요청이 가정용·모바일 통신망에서 왔는지, 클라우드 서버에서 왔는지 알아내는 출발점이다.
  2. User-Agent: 어떤 브라우저의 몇 번째 버전으로 접속했는지 알 수 있다.
  3. 언어 헤더(Accept-Language): 실제 브라우저는 거의 항상 이 값을 보내지만, 봇은 대부분 비워 둔다.
  4. 리퍼러: 방문자가 어느 페이지를 거쳐 들어왔는지 나타낸다. 봇은 이 값을 꾸며 넣기도 한다.

기록을 어디서 얻는지는 사이트를 운영하는 방식에 따라 다르다.

운영 방식기록 위치확인할 점
서버 직접 운영(nginx, Apache)웹 서버 접속 로그기본 형식에 언어 헤더가 없어 추가해야 한다
호스팅·CDN 서비스서비스의 로그 기능위 네 값이 모두 보이는지 먼저 확인한다
로그가 없는 정적 사이트직접 기록요청을 받아 처리하는 작은 코드(엣지 함수)로 요청마다 기록한다

웹 서버 접속 로그는 기본 형식(combined)에 언어 헤더가 빠져 있다.
nginx라면 기본 형식 끝에 언어 헤더를 더한 형식을 만들어 쓴다.

nginx
# nginx.conf - 기본 형식(combined) 끝에 언어 헤더를 더한다
log_format bot '$remote_addr - $remote_user [$time_local] "$request" '
               '$status $body_bytes_sent "$http_referer" '
               '"$http_user_agent" "$http_accept_language"';
access_log /var/log/nginx/access.log bot;

Apache라면 LogFormat 끝에 \"%{Accept-Language}i\"를 더하면 된다.

필자의 사이트는 서버 없이 파일만 내주는 정적 사이트라 접속 로그가 없었다.
그래서 Cloudflare Workers로 요청마다 위 값을 기록했고, 이 글의 판정 표와 그래프는 그 기록에서 나왔다.


접속 기록으로 봇 판별

아래 명령은 앞의 nginx 형식으로 남긴 접속 로그를 기준으로 한다.
줄을 큰따옴표로 나누면 6번째 칸이 User-Agent, 8번째 칸이 언어 헤더다.

1. User-Agent별 요청 수

같은 User-Agent끼리 묶어 요청이 많은 순으로 센다.

bash
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -rn | head -30

같은 크롬이라도 버전 분포를 확인해야 한다. 실제 브라우저는 자동 업데이트 덕분에 최신 버전 몇 개에 몰려 있기 때문이다.


2. 언어 헤더가 빈 요청

언어 헤더가 없는 요청만 골라 User-Agent별로 센다. 값이 없으면 로그에는 -로 남는다.

bash
awk -F'"' '$8 == "-" {print $6}' access.log | sort | uniq -c | sort -rn | head -30

Googlebot처럼 이름을 밝힌 크롤러는 원래 언어 헤더를 보내지 않는다.
문제는 크롬·사파리 같은 브라우저 이름을 단 요청이 여기 많이 올라올 때다.


3. IP별 통신사·데이터센터

IP 주소만으로는 어디서 왔는지 알 수 없어서, IP를 통신사 이름으로 바꾸는 조회가 필요하다.
ipinfo.io 같은 IP 조회 사이트에 IP를 넣으면 통신사·데이터센터 이름(AS 이름)과 국가가 나온다.
요청이 많은 IP부터 몇 개만 찍어 봐도 그룹의 성격이 드러난다.

조회 결과에 통신사가 아니라 클라우드 회사(AWS, Google Cloud, Microsoft 같은 이름)가 많이 나오면 의심 대상이다.
결과에 나오는 국가를 GA4에서 유독 튀던 국가와 맞춰 보면, 같은 그룹인지 확인할 수 있다.


필자의 계산기 사이트 기록에서 확인한 사람인 척하는 봇의 특징은 아래와 같다.

  • 수백 개 IP가 모두 클라우드 회사의 서버 대역에서 들어옴
  • 리퍼러는 구글 검색에서 온 것처럼 꾸밈
  • 브라우저 언어 헤더가 비어 있음
  • 크롬 버전이 몇 년 전 것까지 고르게 섞여 있음
  • 디바이스는 전부 데스크톱
  • IP 하나가 한두 번씩만 들어와, IP별 요청 수로는 눈에 띄지 않았다

사람과 사람인 척하는 봇의 판별 신호를 정리하면 아래 표와 같다.

신호사람사람인 척하는 봇
통신사·데이터센터통신사클라우드·호스팅
언어 헤더지역 언어없음
리퍼러검색·메신저없음·위조
브라우저 버전최신 몇 개에 몰림옛 버전까지 고르게
기기PC·휴대폰 섞임데스크톱 한 종류

로봇 판정표

판정 기준은 하나다. 아래 판정표의 세 신호 가운데 두 개 이상이 겹치면 봇으로 판정한다.
하나만 해당하는 요청은 사람일 수도 있으니 판정을 보류한다.

신호를 하나만 보면 사람도 봇으로 오판하기 쉽다. 평범한 방문자도 신호 하나쯤은 얼마든지 걸리기 때문이다.

  1. 한 페이지만 보고 나간 방문자: 검색으로 들어와 답만 확인하고 나가면, IP당 요청 1건과 몇 초의 체류 시간만 남는다.
  2. 회사 VPN 사용자: 회사 VPN을 거치면 가정용 통신망이 아니라 데이터센터 IP로 들어온다.

한 페이지만 보고 나간 방문자를 봇으로 보는 짤
너의 정체를 밝혀라

필자의 기록 일부에 이 기준을 적용한 결과는 아래 판정표와 같다.

요청 신호별 봇 판정표
요청 신호별 봇 판정표
  1. 봇: 클라우드 대역이나 언어 헤더 없음에 옛 버전이 겹친 요청
  2. 보류: 호스팅 대역이지만 최신 브라우저로 들어온 요청. VPN을 쓰는 사람일 수 있다
  3. 인간: 통신사 대역에서 최신 브라우저로 들어온 요청

계산기 사이트에 하루 동안 미국에서 들어온 요청 30,446건을 이 기준으로 나눠 보면, 사람으로 보이는 요청은 1% 남짓에 그쳤다.
대부분은 이름을 밝힌 검색·AI·광고 봇이었고, 사람인 척하는 봇이 4%, 판정을 미룬 요청이 3%였다.

미국에서 들어온 요청 구성 그래프
미국에서 들어온 요청 중 사람은 1%

이 사이트는 이미 Cloudflare 확인 화면으로 일부 봇을 먼저 거르고 있어서, 사람인 척하는 봇이 거르기 전보다 적게 잡혔다.

이름을 밝힌 봇도 진짜인지 확인

User-Agent는 누구나 꾸밀 수 있다.
그래서 구글은 Googlebot 확인 문서에서 역방향 DNS로 진짜인지 확인하라고 안내한다.

IP 주소로 호스트 이름을 찾고, 그 이름이 다시 같은 IP를 가리키는지 두 번 확인한다.

bash
# 1) IP 로 호스트 이름을 찾는다 - googlebot.com 이나 google.com 으로 끝나야 한다
host 66.249.66.1
# 2) 그 호스트 이름이 다시 같은 IP 를 가리키는지 확인한다
host crawl-66-249-66-1.googlebot.com

봇 트래픽 점검 순서

방문이 늘었는데 성과가 따라오지 않는다면 아래 순서대로 확인하면 된다.

  1. GA4 이상 그룹: 참여율·평균 참여 시간이 유독 낮은 국가·기기 조합 찾기
  2. 요청 기록 확보: 접속 로그에 IP·User-Agent·언어 헤더·리퍼러 기록
  3. 통신사 조회: IP를 통신사 이름으로 바꿔 클라우드·호스팅 대역의 비율 확인
  4. 요청 모양: 언어 헤더·리퍼러·브라우저 버전 분포
  5. 이름 밝힌 봇 검증: 역방향 DNS 확인
  6. 판정: 두세 신호가 겹친 그룹만 봇으로 분류

마무리

봇으로 판정한 그룹은 방화벽 규칙이나, 사람인지 확인하는 검사 화면으로 거를 수 있다.
Cloudflare를 쓴다면 매니지드 챌린지로 거르는 방법을 다음 글에서 따로 다룬다.

방문이 늘었는데 성과가 그대로라면, 그 방문이 사람인지부터 따져 봐야 한다.

최신 글 전체 보기 →