파서가 실행되고, 코드가 중단되지 않으며, 데이터가 수신되지만 — 가격이 루블이 아닌 달러로 표시되고, 텍스트는 영어로 되어 있으며, 상품은 러시아의 실제 사용자가 보는 것과 다릅니다. 이는 파싱에서 가장 흔하고 불쾌한 문제 중 하나입니다: 기술적으로 모든 것이 작동하지만 콘텐츠가 "다릅니다". 이러한 문제가 발생하는 이유와 필요한 페이지 버전을 얻기 위해 요청을 어떻게 구성할 수 있는지 분석합니다.
증상: 파서가 잘못된 버전을 보고 있다는 것을 어떻게 알 수 있나요
문제를 수정하기 전에 올바르게 진단하는 것이 중요합니다. 파서가 일반 브라우저 사용자와 다른 데이터를 받는 세 가지 전형적인 시나리오가 있습니다:
- 콘텐츠 언어가 일치하지 않음 — 러시아어 텍스트를 기대했지만 영어 또는 우크라이나어 버전이 나타납니다.
- 통화 및 가격이 다름 — 사이트가 USD 또는 EUR로 가격을 표시하지만 러시아 브라우저에서는 루블이 보이거나 숫자가 다릅니다 (지역 가격 책정).
- 상품/콘텐츠 카탈로그가 다름 — 상품의 가용성, 프로모션, 전체 진열대는 사이트가 "보는" 지역에 따라 달라집니다.
원인은 거의 항상 세 가지 중 하나(또는 그 조합)입니다: Accept-Language 헤더,
누락되거나 잘못된 쿠키, 또는 요청이 이루어진 IP 주소의 지리적 위치입니다. 각 항목을 차례로 살펴보겠습니다.
Accept-Language: 서버가 응답 언어를 선택하는 방법
브라우저는 각 요청 시 Accept-Language 헤더를 보내며,
사용자가 선호하는 언어와 가중치(q-값)가 나열됩니다. 러시아 로케일을 가진 Chrome이 실제로 보내는 예는 다음과 같습니다:
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
파싱 라이브러리(requests, httpx, scrapy)는 기본적으로 이 헤더를 전혀 보내지 않거나 */*와 같은 것을 보냅니다.
이 경우 서버는 기본 언어(대개 영어)를 제공하거나 IP에 따라 언어를 결정합니다 — 여기서 지리적 부분이 작용합니다.
중요한 점: 많은 사이트가 "Accept-Language + IP 지리 위치" 조합을 사용하며, 단독으로 사용하지 않습니다. 즉, 올바른 언어 헤더를 보냈더라도 요청이 다른 국가의 IP에서 이루어지면 사이트는 여전히 영어 또는 해당 지역의 로컬 버전으로 전환할 수 있습니다.
통화 및 로케일: 사이트가 가격을 가져오는 방법
통화는 거의 항상 Accept-Language 헤더에 의해 직접적으로 결정되지 않습니다. 보통 세 가지 메커니즘 중 하나(또는 그 조합)가 사용됩니다:
- GeoIP 데이터베이스 — 서버는 IP가 어느 나라에서 왔는지 확인하고 첫 방문 시 자동으로 해당 통화 및 로케일을 적용합니다.
- 이전에 선택된 지역의 쿠키 — 사용자가 한 번 수동으로 국가와 통화를 선택하면, 사이트는 이를 쿠키에 저장하고 더 이상 IP를 확인하지 않습니다.
- URL 매개변수 또는 서브도메인 — 일부 사이트는
?country=ru또는ru.example.com와 같은 명시적인 마커를 사용합니다.
실제로 인터넷 쇼핑몰을 파싱하고 달러로 가격이 표시되는 경우, 80%의 경우는 헤더가 아니라 요청의 IP 주소 때문입니다. 사이트는 단순히 비러시아 IP를 "보았"고 기본 국제 진열대를 표시했습니다.
지리 쿠키: 사이트가 선택한 지역을 기억하는 방법
사이트가 한 번 지역을 결정한 후 (IP 또는 "당신의 도시를 선택하세요" 배너에서 수동 선택) 이를 쿠키에 저장합니다 — 일반적으로
region,
geo_city,
currency 또는
locale와 같은 이름을 사용합니다.
이후 모든 요청은 이 쿠키에 저장된 지역에 따라 처리됩니다 — IP가 갑자기 변경되더라도 말입니다.
이는 파서에게 함정을 만듭니다: 만약 한 번 "잘못된" 버전을 받고 세션 쿠키를 저장했다면, 이후 모든 요청은 동일한 오류를 재현하게 됩니다. 따라서 헤더나 프록시를 수정하더라도 문제가 발생합니다. 따라서 진단 시 항상 이전 실행에서 저장된 쿠키 없이 깨끗한 세션으로 파싱을 확인해야 합니다.
동일한 메커니즘의 반대 측면은 유용합니다: 필요한 쿠키의 이름과 해당 지역에 대한 올바른 값을 알고 있다면 (예: 필요한 위치에서 DevTools 브라우저에서 확인한 경우), IP를 변경하지 않고도 요청에서 이 값을 강제로 설정할 수 있습니다. 이는 지역이 쿠키 플래그를 통해서만 결정되는 사이트에서 작동하지만, 서버가 매 요청마다 IP를 GeoIP 데이터베이스와 다시 확인하는 경우에는 작동하지 않습니다.
지역 결정에서 IP 주소와 프록시의 역할
GeoIP 결정은 사이트가 요청이 실제로 어디서 왔는지 이해하는 가장 신뢰할 수 있는 방법입니다. 왜냐하면 헤더와 쿠키는 위조할 수 있지만, IP 주소는 위조할 수 없기 때문입니다 (다른 실제 주소로만 교체할 수 있습니다). 따라서 "올바른" 지역 버전을 안정적으로 얻기 위해서는 HTTP 헤더만으로는 충분하지 않으며, 실제로 필요한 국가에 속한 IP가 필요합니다.
여기에는 IP 주소 유형 간의 중요한 차이가 있습니다:
- 데이터 센터 IP — GeoIP 데이터베이스는 종종 국가에 따라 이를 정확하게 식별하지만, 많은 대형 사이트 (특히 마켓플레이스 및 봇 방지 서비스)는 데이터 센터 범위를 의심스러운 것으로 표시하고 지리적 위치와 관계없이 축소된 또는 기본 콘텐츠 버전을 표시할 수 있습니다.
- 레지던스 IP — 실제 제공업체 및 물리적 주소에 속하므로 GeoIP가 지역을 더 정확하게 식별하고, 사이트는 요청을 해당 국가/도시의 일반 사용자로 인식합니다.
- 모바일 IP — 특정 국가의 모바일 운영자에 연결되어 있어, 이는 특정 국가의 모바일 트래픽과 데스크톱 트래픽을 다르게 처리하는 사이트 및 애플리케이션에 특히 중요합니다.
Wildberries, Ozon 또는 Avito와 같은 특정 도시에서 가격 모니터링과 같은 작업에는 레지던스 프록시가 가장 적합합니다 — 이들은 실제 지역에 연결된 IP를 제공하며, 사이트의 GeoIP 데이터베이스는 국가와 도시를 정확하게 식별하여 기본 국제 진열대로 대체되지 않습니다.
실습: Python에서 올바른 요청 구성하기
세 가지 문제를 동시에 해결하는 요청을 구성해 보겠습니다: 올바른 Accept-Language를 보내고, 필요한 쿠키로 깨끗한 세션을 사용하며, 필요한 지역의 IP를 통해 요청을 보냅니다.
import requests
proxies = {
"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080",
}
headers = {
"Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36",
}
cookies = {
"region": "ru",
"currency": "RUB",
}
session = requests.Session()
response = session.get(
"https://example.com/catalog",
headers=headers,
cookies=cookies,
proxies=proxies,
timeout=15,
)
print(response.status_code)
print(response.text[:500])
이 코드에서 몇 가지 중요한 사항:
requests.Session()를 사용하고, 단일requests.get()를 사용하지 않음으로써, 필요할 경우 서버가 추가 쿠키를 설정할 수 있도록 하여, 동일한 파싱 세션 내에서 요청 간에 쿠키가 저장됩니다.- 쿠키의 값
region과currency는 조건부이며, 실제 이름과 값은 필요한 위치의 대상 사이트에서 DevTools 브라우저 (Application → Cookies 탭)에서 확인해야 합니다. - 프록시는 실제로 필요한 국가에 있어야 합니다 — 그렇지 않으면 올바른 헤더와 쿠키도 서버에 의해 지리적 위치 재확인 시 덮어씌워질 수 있습니다.
JS 사이트: Playwright 및 헤더/쿠키 관리
사이트가 JavaScript를 통해 콘텐츠를 렌더링하는 경우 (가격이 페이지 로드 후 별도의 요청으로 로드됨), 단순한 requests 요청으로는 부족하며, 헤드리스 브라우저가 필요합니다. Playwright에서는 로케일, 언어 및 프록시가 브라우저 컨텍스트 수준에서 설정됩니다:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(
locale="ru-RU",
timezone_id="Europe/Moscow",
proxy={
"server": "http://gate.proxycove.com:8080",
"username": "user",
"password": "pass",
},
)
context.add_cookies([
{"name": "region", "value": "ru", "domain": "example.com", "path": "/"},
{"name": "currency", "value": "RUB", "domain": "example.com", "path": "/"},
])
page = context.new_page()
page.goto("https://example.com/catalog")
page.wait_for_selector(".price")
print(page.content()[:500])
browser.close()
timezone_id 매개변수에 주의하세요 —
많은 사이트가 브라우저의 시간대와 지역에 대한 예상 시간대를 추가로 확인하며, 불일치
(예: IP는 러시아에서 오지만 브라우저의 시간대는 미국)는 언어와 통화가 형식적으로 올바르더라도
요청이 의심스럽다고 판단할 수 있는 신호가 될 수 있습니다.
일반적인 실수 및 실행 전 체크리스트
파서를 프로덕션에서 실행하기 전에 짧은 체크리스트를 확인하세요 — 이는 디버깅 시간을 절약합니다:
- ✅ Accept-Language 헤더가 설정되어 있으며 예상 지역과 일치합니다.
- ✅ 세션이 깨끗합니다 — 쿠키가 이전의 실패한 요청에서 상속되지 않았습니다.
- ✅ 프록시의 IP가 실제로 필요한 국가에 있습니다 (파싱 전에 어떤 geo-IP 체크기로 확인하세요).
- ✅ User-Agent가 실제 브라우저와 일치하며 헤드리스 모드의 징후가 없습니다.
- ✅ 브라우저의 시간대와 로케일 (Playwright/Selenium의 경우)이 IP 국가와 일치합니다.
- ✅ 사이트가 배너에서 지역을 수동으로 선택하는 경우 — 이 선택의 쿠키가 수동으로 전달됩니다.
프록시 회전과 관련하여 별도로 언급할 점이 있습니다: 각 요청마다 IP를 변경하고 세션 쿠키는 동일하게 유지하면, 사이트는 "A 지역의 쿠키, 그러나 B 지역의 IP"의 불일치를 감지하고 세션을 초기화할 수 있습니다. 가격 모니터링 작업에는 특정 지역의 데이터 수집 중 전체 파싱 세션에 하나의 IP를 고정하는 것이 좋습니다.
작업에 적합한 프록시 유형 선택하기
프록시 유형 선택은 사이트가 귀하의 지역을 얼마나 정확하게 식별하고 자동화를 의심하지 않을지에 직접적인 영향을 미칩니다. 다음은 지역 사이트 버전 파싱의 일반적인 작업에 대한 비교입니다:
| 프록시 유형 | 지리적 위치 정확도 | 언제 사용해야 하는지 |
|---|---|---|
| 데이터 센터 프록시 | 평균, 국가가 정확하지만 IP가 "비거주"로 표시될 수 있음 | 엄격한 봇 방지 보호가 없는 사이트 파싱, 높은 속도 및 요청량 |
| 레지던스 프록시 | 높음, 도시까지 정확하게 | 마켓플레이스 가격 모니터링, 지역 콘텐츠, GeoIP 검증 우회 |
| 모바일 프록시 | 높음, 모바일 운영자 태그 추가 | 특정 국가의 모바일 트래픽과 다르게 작동하는 사이트 및 애플리케이션 |
특정 도시에서 마켓플레이스의 카탈로그 및 가격 모니터링 작업이 필요한 경우, 레지던스 프록시가 일반적으로 가장 예측 가능한 결과를 제공합니다: GeoIP 데이터베이스는 실제 거주 주소를 보고하며, 데이터 센터 범위가 아닌 별도의 로직으로 처리되는 경우가 있습니다.
결론
"파서가 잘못된 페이지 버전을 보고 있다"는 문제는 거의 항상 세 가지 요인으로 구성됩니다: 선호하는 응답 언어를 결정하는 Accept-Language 헤더; 이전에 선택된 지역과 통화를 기억하는 쿠키; 그리고 서버가 첫 방문 시 요청 국가를 결정하는 IP 주소의 지리적 위치입니다. 실제 사용자가 보는 사이트 버전을 얻으려면 이 세 가지 매개변수를 동시에 동기화해야 하며, 개별적으로 수정해서는 안 됩니다.
지역 사이트 버전을 정기적으로 파싱하거나 마켓플레이스에서 경쟁자의 가격을 모니터링하거나 여러 국가의 데이터를 수집하는 경우, 적절한 IP 선택부터 시작하는 것이 좋습니다 — 나머지 설정(헤더, 쿠키, 시간대)은 이를 중심으로 구성됩니다. 필요한 지역에 정확하게 도달하기 위해 레지던스 프록시를 시도해 보시기 바랍니다, 이는 예측 가능한 지리적 위치를 제공하고 기본 국제 사이트 버전 대신 로컬 버전을 받을 위험을 최소화합니다.