같은 글을 서른한 번 가져가는 크롤러

같은 글을 서른한 번 가져가는 크롤러

며칠 전 서버 한 대의 하루 전송량이 평소의 두 배로 뛰었습니다. 로그를 따라가 보니 수집 봇 세 개가 게시판 이미지를 통째로 받아 가고 있었습니다. 무거운 이미지 요청만 거절하도록 설정을 하나 넣었고, 그걸로 끝난 줄 알았습니다. 닷새 뒤에 다시 로그를 열어 보고서야 실제로 무슨 일이 벌어지고 있었는지 알았습니다. 이미지는 막혔는데 전송량은 거의 그대로였습니다. 가장 많이 받아 간 봇은 글을 읽고 있었는데, 같은 글을 서른 번씩 다시 읽고 있었습니다.

같은 9,542개를 295,042개로 세는 봇

하루치 접속 기록을 봇별로 갈라 보았습니다. 요청 수만 보면 어느 봇이 많이 다녀갔는지만 알 수 있어서, 요청한 주소를 두 가지로 나눠 세었습니다. 물음표 뒤까지 포함한 주소 전체가 몇 가지였는지, 그리고 물음표를 떼어 낸 경로만 세면 몇 가지였는지입니다. 둘을 나누면 봇이 같은 문서를 몇 개의 주소로 간주했는지가 나옵니다.

수집 봇 요청 주소 종류 경로 종류 경로당 주소
GPTBot 295,616 295,042 9,542 30.9
Amazonbot 134,681 114,042 18,009 6.3
Googlebot 59,487 30,102 15,795 1.9
Bingbot 7,837 5,700 3,603 1.6
AhrefsBot 12,886 7,211 7,211 1.0
ClaudeBot 6,460 4,624 4,055 1.1
수집 봇별로 문서 하나에 매겨진 주소 수 막대그래프. GPTBot 30.9배, Amazonbot 6.3배, Googlebot 1.9배, Bingbot 1.6배, ClaudeBot 1.1배, AhrefsBot 1배
같은 사이트를 다녀갔는데 GPTBot은 문서 하나를 서른한 개로, AhrefsBot은 하나로 셌습니다.

맨 윗줄이 문제였습니다. 실제 문서는 9,542개인데 주소는 295,042개였습니다. 문서 하나에 주소를 평균 서른한 개 매겨 놓고 그걸 다 따로 받아 갔습니다. 요청 수로는 하루 전체 요청 261만 건 중 11.3퍼센트, 전송량으로는 3.43기가바이트였습니다. 응답 하나는 평균 12킬로바이트에 불과한데 건수가 29만이라 그만큼 쌓였습니다.

한 대가 몰아서 긁어 간 것도 아니었습니다. 요청을 보낸 주소는 231개로 나뉘어 있었습니다. 특정 주소 하나를 막는 식으로는 대응이 안 되는 모양새입니다. 이름을 밝힌 봇 여섯 개를 합치면 하루 요청의 19.8퍼센트였고, 그 대부분이 맨 윗줄 하나였습니다.

같은 날 같은 사이트를 다녀간 ClaudeBot은 4,055개 문서를 4,624개 주소로 봤습니다. 경로당 1.1입니다. AhrefsBot은 정확히 1.0이었습니다. 같은 링크를 보고 돌아다녔는데 한쪽은 1이고 한쪽은 31입니다. 사이트가 보내 준 것이 같다면, 차이는 받는 쪽이 주소를 어떻게 해석하는지에서 나온 것입니다.

정렬 링크가 주소를 불린다

원인은 목록 페이지의 정렬 링크였습니다. 게시판 목록에는 보통 “최신순”과 “조회순” 같은 정렬 버튼이 있습니다. 이 버튼이 걸고 있는 주소를 들여다보니 정렬 기준만 들어 있지 않았습니다. 지금 보고 있는 페이지 번호, 게시판 이름, 검색 조건이 전부 함께 붙어 있었습니다.

세 번째 페이지에서 정렬 버튼을 누르면 “세 번째 페이지를 조회순으로”라는 주소가 됩니다. 페이지가 백 개 있으면 정렬 주소도 백 개 생깁니다. 그 주소에서 또 정렬 버튼이 보이고, 그 버튼에는 다시 현재 상태가 붙습니다. 링크를 따라가는 입장에서는 가도 가도 새 주소가 나옵니다.

정렬 파라미터가 붙은 요청의 비율을 보면 봇별 차이가 그대로 드러납니다.

수집 봇 정렬 조건이 붙은 요청
GPTBot 97.7%
Amazonbot 79.2%
Googlebot 54.1%
Bingbot 17.6%
ClaudeBot 2.0%
AhrefsBot 0.0%

GPTBot 요청 열 건 중 아홉 건 넘게 정렬 조건이 붙어 있었습니다. 반대쪽 끝에서 AhrefsBot은 한 건도 없었습니다. 정렬 링크를 아예 따라가지 않은 것입니다.

비어 있는 조건도 주소를 가른다

주소를 하나 꺼내서 뜯어보니 더 알 것이 있었습니다. 검색어 자리와 분류 자리가 비어 있는 채로 주소에 들어 있었습니다. 검색을 하지 않았으니 결과는 같은데, 글자로는 다른 주소입니다.

사람 눈에는 같은 화면입니다. 주소를 글자로 비교하는 쪽에는 다른 문서입니다. 빈 조건이 여섯 개 붙어 있으면 그 조합마다 주소가 갈라질 수 있습니다. 정렬 두 가지에 페이지 백 개를 곱하고 여기에 빈 조건까지 곱하면 서른한 배라는 숫자가 나옵니다.

이건 봇의 잘못이라고만 하기 어렵습니다. 주소가 다르면 다른 문서일 수도 있다는 전제는 틀린 전제가 아닙니다. 다만 그 전제를 끝까지 믿고 따라가면 끝이 없는 사이트가 세상에 있고, 제 사이트가 그중 하나였습니다.

54,377번 요청된 비밀번호 화면

경로별로 전송량을 세워 보니 1위가 뜻밖이었습니다. 게시글이 아니라 비밀번호를 묻는 화면이었습니다. 하루 54,377건, 275메가바이트입니다. GPTBot이 받아 간 전송량의 8퍼센트를 여기에 썼습니다.

보호된 글을 고치려고 할 때 뜨는 화면입니다. 비밀번호를 모르면 아무것도 나오지 않습니다. 봇이 비밀번호를 알 리 없으니 54,377번 모두 같은 입력 상자만 받아 갔습니다. 여기에도 정렬 조건과 페이지 번호가 붙어 있었습니다. 그래서 글마다, 페이지마다, 정렬 방식마다 주소가 따로 생겼습니다.

얻을 것이 없는 쪽에 가장 많이 들어왔다는 점이 중요합니다. 봇은 그 화면이 비밀번호 요구인지 모릅니다. 응답 코드가 정상이고 내용이 들어 있으면 받아 간 것입니다. 링크를 거는 쪽과 받는 쪽이 보는 것이 다르다는 이야기를 전에 썼는데, 같은 일이 봇과 서버 사이에서도 벌어집니다.

이미지를 막은 것은 효과가 있었습니다. 다만

처음 넣은 이미지 차단은 제대로 작동했습니다. 설정에 적어 둔 세 봇의 게시판 이미지 요청은 전부 거절되고 있었습니다. 받아 간 양은 봇마다 1메가바이트 수준으로 떨어졌습니다.

그런데 전체 전송량은 22.7기가바이트로, 문제가 생기기 전 평소치보다 여전히 높았습니다. 이미지로 나가던 몫이 다른 데로 옮겨 간 셈입니다. 게시판 이미지를 가장 많이 받아 간 쪽도 바뀌었습니다. 차단 목록에 넣지 않은 검색 봇이 1.3기가바이트로 1위였습니다. 검색 노출에 필요하다고 보고 일부러 열어 둔 쪽입니다.

옮겨 간 자리가 하나 더 있었습니다. 두 번째로 요청이 많던 봇은 요청 중 39,570건이 주소 이동 안내를 받고, 983건은 없는 문서를 찾고 있었습니다. 예전 주소로 들어오는 것입니다. 사이트 구조를 바꾼 뒤 남은 흔적을 봇이 계속 두드리고 있는 셈이라, 이쪽은 차단이 아니라 주소 정리로 풀 문제입니다.

차단 목록에 없던 다른 수집 봇도 이미지 폴더에 들어오고 있었습니다. 양은 3메가바이트로 적었지만, 목록 방식의 한계를 보여 줍니다. 이름을 적어서 막는 방법은 적어 둔 이름에만 듣습니다. 새 봇이 생기면 그때 또 추가해야 합니다.

막는 것보다 안 만드는 것

닷새를 두고 두 번 들여다본 결론은 방향을 바꿔야 한다는 것이었습니다. 요청을 거절하는 일은 들어온 다음에 하는 일입니다. 요청 자체가 왜 29만 건이나 생기는지는 그대로입니다.

접근 효과 한계
이름으로 거절 전송량이 바로 준다 적어 둔 이름에만 듣는다
수집 거부 문서에 명시 요청 수가 준다 지키는 쪽에만 듣는다
대표 주소 지정 중복을 한 주소로 모은다 따라오지 않는 봇도 있다
정렬 링크에 수집 거부 표시 조합이 안 생긴다 링크를 손봐야 한다
빈 조건을 주소에서 빼기 주소 가짓수가 줄어든다 목록 코드를 고쳐야 한다

위의 둘은 밖에서 거는 조치고 아래 셋은 사이트가 주소를 덜 만드는 조치입니다. 효과를 재 보면 아래쪽이 확실합니다. 봇이 어떤 규칙을 지키는지에 기대지 않기 때문입니다.

작업 순서로는 빈 조건부터 빼는 것이 가장 쌉니다. 정렬 링크를 만들 때 값이 없는 조건은 붙이지 않게 하면 그걸로 조합 하나가 사라집니다. 사람이 자동화를 멈춰 세우는 지점을 세어 봤을 때도 비슷했는데, 뒤에서 막는 장치보다 애초에 일이 생기지 않게 하는 쪽이 손이 덜 갔습니다.

이 숫자를 그대로 믿지는 마십시오

하루치 기록 하나로 센 숫자입니다. 봇은 날마다 다르게 움직이므로 다음 날 비율이 바뀔 수 있습니다. 같은 봇이 여러 날에 걸쳐 같은 양을 유지한다고 말하려면 며칠을 더 봐야 합니다.

봇 구분은 요청 헤더에 적힌 이름으로 했습니다. 이 값은 보내는 쪽에서 아무렇게나 적을 수 있습니다. 이름을 밝히지 않고 브라우저인 척 들어오는 수집기는 이 집계에 들어 있지 않습니다. 그러니 표의 숫자는 이름을 밝힌 봇에 한정된 이야기입니다.

그리고 경로당 주소 수가 1에 가깝다는 것이 꼭 좋은 봇이라는 뜻은 아닙니다. 정렬 링크를 안 따라갔다는 뜻일 뿐이고, 그 과정에서 가져가야 할 페이지를 빠뜨렸을 수도 있습니다. 서버 입장에서 가볍다는 것과 사이트를 잘 읽었다는 것은 다른 이야기입니다. 이번에 센 것은 앞쪽뿐입니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다