레지덴셜 프록시는 저희가 판매하는 상품이므로, 언제 필요하지 않은지에 대해 글을 쓰는 것이 이상하게 보일 수 있습니다. 하지만 모든 작업에 프록시를 구매하는 팀은 비용을 과다 지출하게 되고, 모든 실패를 프록시 탓으로 돌리는 팀은 몇 주를 낭비하게 됩니다. 어떤 사이트에 레지덴셜 IP가 필요한지, 어떤 사이트에는 아무것도 필요하지 않은지, 어떤 사이트에는 완전히 다른 것이 필요한지를 아는 것이 웹 데이터 수집에서 가장 저렴한 최적화입니다.
이를 구체적으로 확인하기 위해 작은 테스트를 진행했습니다. 2026년 10월 9일, 데이터센터 IP 주소를 가진 클라우드 서버에서 30개의 공개 페이지를 각각 세 번씩 요청한 다음, US 출구를 사용하는 Shifter 레지덴셜 프록시를 통해 다시 요청했습니다. 두 실행 모두 동일한 간단한 Python HTTP 클라이언트를 사용했습니다. 30개 페이지 중 16개는 데이터센터 IP에서 매번 작동했습니다. 3개는 레지덴셜 출구를 통해서만 작동했습니다. 나머지 11개는 레지덴셜 IP로도 해결되지 않는 이유로 양쪽 모두에서 실패했습니다.
The test
대상은 여섯 가지 종류의 사이트를 포함했습니다: 공개 API와 오픈 데이터, 레퍼런스 및 문서 사이트, 뉴스 홈페이지, 이커머스 검색 페이지, 여행 검색 페이지, 그리고 소셜, 채용, 검색 페이지 모음입니다. 각 요청은 동일한 데스크톱 브라우저 User-Agent를 사용했으며, 단순히 상태 코드만이 아니라 실제 콘텐츠가 있는지 확인했습니다. 응답은 검색 결과 카드처럼 실제 콘텐츠에만 나타나는 마커를 포함할 때만 성공으로 집계했습니다. 상태 200을 반환하는 차단 페이지는 흔한데, 이는 실패로 집계했습니다.
마커는 최종 실행 전에 두 네트워크에서 저장한 응답을 검토하여 선택했으며, 실제 콘텐츠와 로그인 월 또는 빈 JavaScript 셸을 구분할 수 없었던 후보 페이지 5개는 제외했습니다.
| 카테고리 | 사이트 | 데이터센터 IP | 레지덴셜 출구 | 판정 |
|---|---|---|---|---|
| 공개 API 및 오픈 데이터 | en.wikipedia.org | 3/3 | 3/3 | 프록시 불필요 |
| 공개 API 및 오픈 데이터 | api.github.com | 3/3 | 3/3 | 프록시 불필요 |
| 공개 API 및 오픈 데이터 | data.sec.gov | 3/3 | 3/3 | 프록시 불필요 |
| 공개 API 및 오픈 데이터 | api.worldbank.org | 3/3 | 3/3 | 프록시 불필요 |
| 공개 API 및 오픈 데이터 | ecb.europa.eu | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | docs.python.org | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | developer.mozilla.org | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | rfc-editor.org | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | en.wikipedia.org | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | arxiv.org | 3/3 | 3/3 | 프록시 불필요 |
| 레퍼런스 및 문서 | stackoverflow.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 뉴스 | bbc.com | 3/3 | 3/3 | 프록시 불필요 |
| 뉴스 | reuters.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 뉴스 | nytimes.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 뉴스 | theguardian.com | 3/3 | 3/3 | 프록시 불필요 |
| 뉴스 | edition.cnn.com | 3/3 | 3/3 | 프록시 불필요 |
| 뉴스 | bloomberg.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 이커머스 검색 | amazon.com | 3/3 | 2/3 | 프록시 불필요 |
| 이커머스 검색 | walmart.com | 0/3 | 3/3 | 레지덴셜 IP 필요 |
| 이커머스 검색 | ebay.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 이커머스 검색 | bestbuy.com | 0/3 | 0/3 | 양쪽 모두 시간 초과 |
| 이커머스 검색 | etsy.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 여행 | booking.com | 0/3 | 2/3 | 레지덴셜 IP 필요 |
| 여행 | expedia.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 여행 | airbnb.com | 3/3 | 2/3 | 프록시 불필요 |
| 여행 | tripadvisor.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 여행 | kayak.com | 0/3 | 3/3 | 레지덴셜 IP 필요 |
| 소셜, 채용 및 검색 | linkedin.com | 3/3 | 3/3 | 프록시 불필요 |
| 소셜, 채용 및 검색 | indeed.com | 0/3 | 0/3 | 양쪽 모두 차단됨 |
| 소셜, 채용 및 검색 | google.com | 0/3 | 0/3 | 브라우저 필요 |
“양쪽 모두 차단됨”은 일반 HTTP 클라이언트가 두 네트워크 모두에서 차단되었다는 의미입니다. 브라우저 검사를 처리하는 실제 브라우저나 스크래핑 API라면 이런 사이트에서도 충분히 성공할 수 있지만, 이번 테스트에서는 시도하지 않았습니다.
What the results say
공개 API, 오픈 데이터, 문서는 프록시가 필요 없습니다. 테스트한 API 및 레퍼런스 페이지는 하나를 제외하고 모두 데이터센터 IP에서 매번 작동했습니다. 이러한 서비스는 프로그램이 사용하도록 만들어져 있습니다. 이들이 원하는 것은 설명이 담긴 User-Agent, 합리적인 요청 속도, 그리고 일부의 경우 API 키입니다. 프록시는 비용만 추가할 뿐 그 이상은 없습니다.
많은 대형 사이트는 데이터센터 IP를 전혀 차단하지 않습니다. 6개 뉴스 홈페이지 중 3개, Amazon 검색, Airbnb 검색, 그리고 LinkedIn 회사 페이지는 클라우드 서버에 3번 중 3번 모두 실제 콘텐츠를 제공했습니다. 이러한 사이트에서 소량 수집을 할 때는 사이트의 이용약관과 요청 제한을 준수하는 한, 프록시 없이 시작하는 것이 합리적입니다.
일부 사이트는 IP 평판으로 차단하며, 이 경우 레지덴셜 출구가 중요해집니다. Walmart, Kayak, Booking.com은 매번 데이터센터 IP를 거부했고, 레지덴셜 출구를 통해서는 콘텐츠를 제공했습니다. 이러한 사이트는 요청이 들어온 네트워크를 평가하는데, 클라우드 서버의 주소는 평판이 나쁘게 매겨집니다. 바로 이런 경우를 위해 레지덴셜 프록시가 존재합니다.
일부 사이트는 IP가 아니라 클라이언트를 차단합니다. eBay, Etsy, Expedia, Tripadvisor, Indeed, Stack Overflow와 뉴스 사이트 3곳은 두 네트워크 모두에서 일반 Python 클라이언트를 차단했습니다. 이들은 요청이 어디서 왔는지 보기 전에, TLS 핑거프린트, HTTP 헤더, JavaScript 실행 여부 등 클라이언트가 연결하고 동작하는 방식을 확인합니다. 레지덴셜 IP는 스스로를 스크립트라고 드러내는 클라이언트를 고쳐주지 못합니다. TLS 및 HTTP/2 핑거프린팅 가이드에서 이러한 검사가 어떻게 작동하는지 설명합니다.
어떤 네트워크를 쓰든 브라우저가 필요한 페이지도 있습니다. Google 검색은 두 네트워크 모두에 JavaScript를 요구하는 페이지를 반환했으며, HTML에는 결과가 없었습니다. 이런 페이지의 경우 헤드리스 브라우저와 데이터를 직접 반환하는 API 중에서 선택해야 합니다.
How to tell what a site needs
대부분의 대상은 무언가를 구매하기 전에 오후 한나절이면 이러한 그룹으로 분류할 수 있습니다. 아래 함수는 테스트에서 사용한 검사 방법으로, 페이지를 가져와서 실제 콘텐츠를 받았는지, 차단되었는지, 오류가 발생했는지, 아니면 빈 셸을 받았는지를 판단합니다.
import re
import requests
BLOCK = re.compile(r"captcha|access denied|are you a robot|just a moment|unusual traffic|"
r"verify you are human|request blocked|pardon our interruption|enable javascript and cookies",
re.IGNORECASE)
HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
def check(url, marker, proxies=None):
"""Did this request get the real content, or a block, an error or an empty shell?"""
try:
response = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
except requests.RequestException as error:
return {"url": url, "result": "error", "detail": type(error).__name__}
body = response.text
if response.status_code != 200:
result = "blocked" if response.status_code in (202, 401, 403, 429, 503) else "error"
elif BLOCK.search(body[:20000]) and marker.lower() not in body.lower():
result = "blocked"
elif marker.lower() not in body.lower():
result = "no content"
else:
result = "ok"
return {"url": url, "result": result, "status": response.status_code, "bytes": len(response.content)}
원하는 콘텐츠에만 나타나는 마커, 예를 들어 결과 카드의 클래스 이름이나 JSON 응답의 필드 이름을 선택하세요. 페이지 제목에 들어가는 단어는 사용하지 마세요. 차단 페이지와 로그인 월도 그 단어를 반복하는 경우가 많습니다. 그런 다음 각 대상의 몇몇 페이지에서 실행해 보세요:
from check import check
print(check("https://api.github.com/repos/python/cpython", '"full_name"'))
print(check("https://www.ebay.com/sch/i.html?_nkw=laptop", "srp-results"))
{'url': 'https://api.github.com/repos/python/cpython', 'result': 'ok', 'status': 200, 'bytes': 6617}
{'url': 'https://www.ebay.com/sch/i.html?_nkw=laptop', 'result': 'blocked', 'status': 403, 'bytes': 1832}
스크래퍼가 실제로 실행될 환경(운영 환경이 클라우드 서버라면 노트북이 아니라 그 서버)에서 하루에 몇 차례 실행해 보세요. 결과는 다음과 같은 결정으로 이어집니다:
| 클라우드 서버에서 보이는 결과 | 일반적인 의미 | 사용할 것 |
|---|---|---|
| 지속적으로 실제 콘텐츠 | 해당 사이트는 현재 요청량에서 데이터센터 트래픽을 차단하지 않음 | 프록시 불필요, 또는 규모 확장을 위한 데이터센터 IP |
| 차단 또는 챌린지가 발생하지만 가정용 연결에서는 실제 콘텐츠 | 해당 사이트는 IP 평판으로 차단함 | 레지덴셜 프록시 |
| 모든 네트워크에서 차단 | 해당 사이트는 클라이언트를 검사함 | 실제 브라우저 또는 스크래핑 API(보통 내부적으로 레지덴셜 IP 사용) |
| 데이터가 없는 빈 셸 | 콘텐츠가 JavaScript로 렌더링됨 | 헤드리스 브라우저 또는 페이지가 호출하는 API |
| 로그인 월 | 콘텐츠가 공개되어 있지 않음 | 허가 없이 수집하지 말 것 |
두 가지 보완 사항:
- 요청량에 따라 답이 달라집니다. 클라우드 서버에서의 요청 10건은 무시하는 사이트도 10,000건은 차단할 수 있습니다. 한 번만 테스트하지 말고 실제로 운영할 속도로 다시 테스트하세요.
- 위치에 따라 답이 달라집니다. 사이트는 국가별로 다른 콘텐츠를 제공하고 다른 규칙을 적용합니다. 독일에서 보이는 데이터가 필요하다면 독일에서 테스트하세요.
The middle options
선택지는 프록시를 쓰지 않는 것과 레지덴셜 프록시만 있는 것이 아닙니다.
- 데이터센터 IP는 저렴하고 빠르며, 이를 차단하지 않는 사이트에는 적합합니다. ISP 프록시와 데이터센터 프록시 비교에서 이것만으로 충분한 경우를 다룹니다.
- ISP 프록시는 소비자용 인터넷 제공업체에 등록된 고정 주소입니다. 며칠간 동일한 IP를 유지하고 싶은 장시간 세션이나 본인 계정 로그인에 적합합니다. Shifter의 ISP 프록시는 무제한 트래픽을 제공하므로, 이를 허용하는 사이트에서는 많고 꾸준한 작업량에도 적합합니다.
- 스크래핑 API는 브라우저, 재시도, IP 선택을 대신 처리해 주며, 기가바이트 단위가 아니라 성공한 페이지 단위로 과금합니다. 클라이언트를 검사하는 사이트에서는 브라우저 레이어를 직접 구축하고 유지보수할 필요가 없기 때문에 흔히 가장 저렴한 선택지입니다. JavaScript 중심 사이트 스크래핑 가이드를 참고하세요.
- 레지덴셜 프록시는 사이트가 요청이 들어온 네트워크를 판단 기준으로 삼을 때, 즉 동일한 클라이언트가 가정용 연결에서는 성공하고 클라우드 서버에서는 실패할 때 적합한 도구입니다.
FAQ
웹 스크래핑에 프록시가 필요한가요?
항상 필요한 것은 아닙니다. 테스트에서는 모든 공개 API와 대부분의 문서 사이트를 포함해 30개 공개 페이지 중 16개가 프록시 없이도 클라우드 서버에 실제 콘텐츠를 제공했습니다. 스크래퍼가 실행될 환경에서 먼저 대상을 테스트하세요.
레지덴셜 프록시는 언제 필요한가요?
사이트가 데이터센터 IP의 요청은 차단하지만 가정용 연결에서는 동일한 클라이언트에 콘텐츠를 제공하는 경우입니다. 테스트에서는 30개 사이트 중 3개(Walmart, Kayak, Booking.com)가 이렇게 동작했습니다.
레지덴셜 프록시를 사용해도 왜 여전히 차단되나요?
대개 사이트가 IP가 아니라 클라이언트를 검사하기 때문입니다. 많은 사이트가 TLS 핑거프린트, 헤더, JavaScript 미실행 여부로 스크립트임을 식별해 HTTP 클라이언트를 차단합니다. 테스트에서는 30개 페이지 중 11개가 일반 Python 클라이언트로는 두 네트워크 모두에서 실패했습니다. 해결책은 다른 IP가 아니라 실제 브라우저나 스크래핑 API입니다.
스크래핑에는 데이터센터 프록시로 충분한가요?
공개 API, 문서, 많은 뉴스 사이트, 일부 대형 소매업체의 경우, 적당한 요청량에서는 그렇습니다. IP 평판을 평가하는 사이트의 경우에는 아닙니다. 추측하지 말고 각 대상을 직접 테스트하세요.
The bottom line
레지덴셜 프록시는 한 가지 특정한 문제, 즉 요청이 들어온 네트워크를 기준으로 판단하는 사이트의 문제를 해결합니다. 클라이언트를 검사하는 사이트에는 도움이 되지 않으며, 공개 API와 클라우드 트래픽을 차단하지 않는 사이트에는 불필요합니다. 스크래퍼가 실행될 환경에서 각 대상을 테스트하고, 이러한 그룹 중 하나로 분류한 다음, 결과가 달라지는 경우에만 레지덴셜 트래픽 비용을 지불하세요. 책임감 있는 수집의 나머지 부분은 웹 스크래핑 모범 사례에서 다룹니다.