대부분의 스크래핑 가이드는 한 가지에 초점을 맞춘다. 차단당하지 않고 데이터를 얻는 것이다. 타당한 목표이긴 하지만, 파이프라인이 첫 달을 넘겨 살아남을지를 결정하는 부분은 빠뜨린다. 최대한 빠르게 대상을 두드리는 스크래퍼는 무례할 뿐만 아니라 취약하기도 하다. 사이트의 부하를 급증시키고, 모든 속도 제한과 안티봇 규칙을 건드리며, 조용히 읽고 싶었던 소스를 적극적으로 자신을 차단하려는 대상으로 바꿔버린다.
역설적인 부분은, 책임감 있게 스크래핑하는 방식과 지속 가능하게 스크래핑하는 방식이 사실 같은 것이라는 점이다. 제한을 존중하고, 부하를 분산시키고, 필요한 것만 요청하는 배려심 있는 클라이언트처럼 행동하는 것이야말로 탐지 임계값 아래에 머물며 계속 작동하는 프로필이다. 이는 차단을 피하는 방법과 같은 동전의 예절 쪽 면이다. 그 글이 봇처럼 보이지 않는 것에 관한 것이라면, 이 글은 해로운 봇처럼 행동하지 않는 것에 관한 것이다. 후자를 실천하면 전자는 대체로 저절로 해결된다.
책임감 있고 지속 가능한 스크래핑이 실제로 어떤 모습인지 살펴보자.
robots.txt를 읽고, 진지하게 받아들여라
제대로 운영되는 모든 사이트는 루트에 robots.txt를 게시하여 자동화된 클라이언트가 건드리면 안 되는 경로를 명시하고, 때로는 Crawl-delay도 함께 명시한다. 이는 법적 계약도 아니고 기술적 장벽도 아니다. 사이트가 그 목적을 위해 만들어진 유일한 장소에서 자신의 선호를 알려주는 것이다. 이를 완전히 무시하는 것은 당신이 선의의 방문자가 아니라는 가장 명확한 신호다.
실용적인 입장은 이렇다. 실행을 시작할 때 robots.txt를 한 번 가져와 캐시하고, 제시하는 user-agent에 대해 금지된 경로를 존중하라. crawl delay가 명시되어 있다면 그것을 최소 기준으로 취급하고, 제안 정도로 여기지 마라. 일부 프로젝트가 이를 부분적으로 벗어나는 정당한 이유가 있을 수는 있지만, “그냥 안 봤다”는 그런 이유가 될 수 없다. robots.txt를 읽으면 사이트가 sitemap을 어디에 두는지도 알 수 있는데, 이는 링크를 하나씩 따라가며 크롤링하는 것보다 훨씬 깔끔하게 URL을 발견하는 방법일 때가 많다.
사이트가 강제하기 전에 스스로 속도를 제한하라
스크래퍼가 저지르는 가장 해로운 행위는 네트워크가 허용하는 만큼 빠르게 요청을 보내는 것이다. 사람 트래픽에 맞춰진 규모의 대상은 공격적인 클라이언트 하나로 인해 응답 시간이 저하되거나 그 이상으로 밀려날 수 있다. 이는 실제 사용자에게 피해를 주며, IP 대역 전체가 차단당하는 가장 빠른 지름길이기도 하다.
의도적인 요청 속도를 설정하고 그 아래를 유지하라. 대부분의 작업에는 호스트당 초당 몇 건의 요청이면 충분하며, 작은 사이트일수록 더 느린 쪽이 안전하다. 요청 사이에 일정한 메트로놈 간격을 두는 대신 작은 무작위 지터를 추가해 트래픽이 기계적으로 균일하게 보이지 않도록 하라. 목표는 누군가의 모니터링 대시보드에 튀는 스파이크가 아니라, 많은 방문자 중 하나로 눈에 띄지 않는 소박한 방문자가 되는 것이다. 전체 처리량을 더 늘려야 한다면, 단일 호스트에 대한 압력을 높이기보다는 시간과 로테이팅 풀에 걸쳐 분산시켜라.
사이트가 거절하면 물러서라
429 Too Many Requests나 503은 서버가 명시적으로 속도를 줄이라고 말하는 것이다. 잘못된 대응은 즉시 재시도하는 것인데, 이는 과부하된 서버가 가장 감당할 수 없는 방식이다. 올바른 대응은 지수 백오프다. 기다렸다가 재시도하고, 다시 실패하면 더 오래 기다리되, 매번 지연 시간을 두 배로 늘려가며 상한선까지 올린다. 서버가 Retry-After 헤더를 보낼 때는 이를 존중하라. 정확히 얼마나 기다려야 하는지 알려주는 것이다.
이는 진짜로 실패한 요청을 재시도하는 것과는 다르다. 연결 끊김이나 타임아웃은 깨진 시도이므로 즉시 재시도할 가치가 있지만, 429는 작동 중인 서버가 여유를 요청하는 것이다. 이 둘을 다르게 취급하라. 429를 촘촘한 루프에서 맹목적으로 재시도하는 것은 스크래퍼가 완화된 속도 제한을 완전한 차단으로 바꾸는 방법이다.
적극적으로 캐시하고 같은 것을 두 번 가져오지 마라
가장 저렴한 요청은 보내지 않는 요청이다. 규모를 확장하기 전에, 얼마나 많은 것을 다시 가져오고 있는지 면밀히 살펴보라. 응답을 캐시하고, 조건부 요청으로 ETag와 Last-Modified를 존중하며, URL 프론티어를 중복 제거하면 실제 요청량을 크게 줄일 수 있다. 피한 요청 하나하나가 대상에 가하지 않은 부하이자, 쓰지 않은 대역폭이며, 발생하지 않은 차단 위험 이벤트다.
이는 비용과 직접적으로 겹치는 부분이다. 당신을 더 가벼운 손님으로 만드는 바로 그 절제가 프록시 대역폭 비용도 절감해준다. 필요한 페이지만 요청하고, 사용할 필드만 가져오며, HTML만 필요할 때는 이미지나 폰트 같은 자산은 건너뛰어라. 예절과 효율성은 같은 습관의 집합이다.
한산한 시간대에 스크래핑하라
작업 실행 시점을 제어할 수 있다면, 대상이 조용할 때 실행하라. 한낮이라면 눈에 띌 배치 작업도 사이트 현지 시간대의 야간 저트래픽 시간대에서는 눈에 띄지 않는다. 이는 서버가 가장 감당하기 힘든 시점에 부하를 더하는 것과, 그렇지 않으면 유휴 상태로 남아있을 용량을 빌리는 것의 차이다. 대규모 반복 작업의 경우, 당신의 시간대가 아니라 대상의 한산한 시간대에 맞춰 스케줄링하라.
가능하다면 정직하게 자신을 밝혀라
여기에는 실질적인 긴장이 존재하며, 솔직히 짚어볼 가치가 있다. 좋은 스크래핑 예절은 전통적으로 봇을 명시하고 연락 수단을 알려주는 설명적인 User-Agent를 보내는 것을 의미한다. 그래야 트래픽을 알아챈 관리자가 차단 대신 연락을 취할 수 있다. 많은 진지하고 정당한 크롤러들이 실제로 이렇게 한다.
동시에, 사이트들은 행동과 무관하게 자동화된 것으로 자신을 밝히는 모든 것을 점점 더 차단하는 추세이며, 이는 스크래퍼들을 일반 브라우저처럼 보이도록 밀어붙인다. 두 입장 모두 사용 사례에 따라 정당화될 수 있다. 정당화될 수 없는 것은 실제로 아닌 특정 서비스인 척하거나 다른 회사의 크롤러를 스푸핑하는 것이다. 자신의 상황에 맞는 정직한 표현 방식을 선택하고 일관되게 유지하라. 비즈니스를 위해 데이터를 수집하는 경우, 크롤러가 무엇을 하는지와 연락 방법을 설명하는 공개 페이지를 두는 데는 비용이 들지 않으며 많은 갈등을 해소해준다.
공개 데이터만 가져가고, 그 안에 무엇이 있는지 유의하라
책임감 있는 스크래핑이란 인증 장벽을 뚫거나 동의한 후 무시하는 약관 없이 도달할 수 있는 공개 페이지를 의미한다. 로그인 뒤에 있는 데이터는 다른 법적, 윤리적 범주에 속하며, 스크래핑 자체가 합법인지 여부는 그 경계에 크게 좌우된다. 공개된 쪽에 머물러라.
데이터가 어디서 왔는지만큼이나 그 안에 무엇이 담겨 있는지에도 신중해야 한다. 페이지에 개인정보가 포함되어 있다면, 저장하는 순간 프라이버시 의무를 물려받게 되며, 대규모로 개인 데이터를 수집하면 GDPR 및 유사 규제가 개입된다. 가장 깔끔한 태도는 특정한 합법적 이유가 없는 한 개인 데이터를 수집 범위에서 제외하고, 필요하지 않은 것은 보관하지 않는 것이다.
프록시가 어디에 맞는지, 그리고 좋은 프록시가 왜 당신을 더 온건하게 만드는지
위의 내용 중 어느 것도 프록시 사용에 반대하는 논거가 아니다. 오히려 올바른 방식으로 프록시를 사용해야 한다는 논거다. 양질의 레지덴셜 풀은 하나의 주소에서 대상에 압력을 집중시키는 대신, 합리적인 요청 속도를 여러 IP와 지역에 걸쳐 분산시킬 수 있게 해준다. 잘 사용하면 이는 사이트를 더 세게 때리는 방법이 아니라 부하 분산 및 지역화 도구다.
풀의 품질은 애초에 얼마나 자주 재시도하게 될지도 결정한다. 좋은 평판을 가진 깨끗한 IP는 문제없이 통과하지만, 플래그가 찍힌 IP는 도전을 받는다. 따라서 더 나은 풀은 동일한 데이터를 위해 더 적은 실패 시도, 더 적은 재시도, 더 적은 총 부하를 의미한다. 세션 도중 새 IP로 바꾸는 대신 논리적 작업 단위당 하나의 아이덴티티를 사용하는 합리적인 로테이션(고정 방식과 로테이팅 방식 비교)은 발자국을 일관되고 가볍게 유지해준다. 그리고 지연 시간을 낮게 유지하면 각 요청이 쌓이지 않고 빠르게 완료되고 해제된다.
간단한 체크리스트
robots.txt를 가져와 존중하라. 그것이 가리키는 sitemap을 사용하라.- 호스트별로 무작위 지터를 둔 의도적인 속도를 설정하라. 대개 초당 몇 건이면 충분하다.
429/503에는 지수적으로 물러서라.Retry-After를 존중하라. 이를 깨진 요청 재시도와 혼동하지 마라.- 캐시하고, 조건부 요청을 사용하고, 중복을 제거하라. 가장 저렴한 요청은 건너뛴 요청이다.
- 필요한 페이지와 필드만 가져오라. 사용하지 않을 자산은 건너뛰어라.
- 대규모 작업에는 대상의 시간대에서 한산한 시간을 선호하라.
- 정직하고 일관된 아이덴티티를 선택하라. 절대 다른 회사의 크롤러를 사칭하지 마라.
- 공개 데이터만 다루라. 보관할 합법적 이유가 없는 개인 데이터는 범위에서 제외하라.
- 부하를 강화하는 것이 아니라 분산시키기 위해 깨끗한 레지덴셜 풀을 사용하라.
결론
수년간 계속 작동하는 스크래퍼는 가장 공격적인 것이 아니라, 대상이 거의 알아채지 못하는 것이다. 여기서 다룬 모든 관행, 즉 속도 제한, 백오프, 캐싱, 한산한 시간대 스케줄링, 정직한 신원 표시는 모두 같은 방향을 가리킨다. 필요한 것만 가져가고, 사이트를 건강하게 남겨두며, 실제로 당신이 그러한 배려심 있는 클라이언트처럼 보이는 것이다. 이것이 윤리적인 스크래핑 방식이며, 동시에 차단당하지 않는 방식이기도 하다.
부하를 집중시키기보다 분산시키도록 설계된 인프라를 원한다면, 저희 레지덴셜 프록시는 깨끗한 로테이팅 풀에서 운영되며, 가격 페이지에는 GB당 요금제가 있어 더 가볍고 스마트한 스크래핑이 실제로 비용을 낮춰줍니다.