확장 가능한 지역별 이커머스 가격 스크레이핑 시스템 구축하기
여러 아마존 리전에서 상품 가격을 대규모로 수집하려고 할 때, 진짜 어려운 건 첫 번째 스크레이퍼를 만드는 일이 아닙니다. 진짜 어려운 건 그 스크레이퍼를 계속 살아 있게 만드는 것입니다.
간단한 스크립트라면 페이지 하나쯤은 가져올 수 있어요. 하지만 실제 운영 환경의 시스템은 다릅니다. IP 차단, 국가별 페이지 구조 차이, 세션 끊김, 들쭉날쭉한 응답, 재시도, 저장, 모니터링, 검색까지 모두 버텨야 하죠. 그래서 운영 환경의 웹 스크레이핑은 더 이상 “스크립트 작성”의 문제가 아닙니다. 시스템 설계 문제가 됩니다.
이 글에서는 Python으로 구축한 대규모 이커머스 가격 스크레이핑 아키텍처를 실무 관점에서 풀어봅니다. 핵심 시나리오는 명확합니다. 같은 상품을 여러 아마존 국가 도메인에서 조회하고, 가격을 수집하고, 결과를 저장하고, 가격 이력을 남기고, 나중에는 직접 SQL을 쓰지 않아도 자연어로 질의할 수 있게 만드는 것입니다.
한 번만 동작하는 스크레이퍼는 스크립트에 가깝고, 매일 믿고 돌릴 수 있는 스크레이퍼는 시스템에 가깝습니다.

먼저 결론부터: 운영 가능한 스크레이핑 스택에는 무엇이 필요할까?
이런 지역별 가격 인텔리전스 시스템에는 다섯 가지가 맞물려 돌아가야 합니다.
- 작업을 실행하고 결과를 확인할 수 있는 프론트엔드
- 이벤트, 재시도, 모니터링을 다루는 API 및 오케스트레이션 계층
- 차단을 피하고 요청 지역을 제어하는 프록시 계층
- 원본 데이터와 이력 데이터를 저장하는 저장소 계층
- 비개발자도 자연어로 질문할 수 있게 해주는 AI 질의 계층
이번 구현에서는 그 구성을 이렇게 가져갔습니다.
- UI: Streamlit
- 백엔드 API: FastAPI
- 이벤트 오케스트레이션 및 관측성: Inngest
- 상품 페이지 파싱: BeautifulSoup
- 지역 지정 요청 처리: Thor Data residential proxy
- 상품 데이터 및 가격 이력 저장: MongoDB
- 벡터 검색: Qdrant
- 의미 기반 검색용 임베딩: OpenAI embeddings
- AI 에이전트 구성: LangChain
- 전체 스택 실행: Docker Compose
이 조합이 주는 장점은 분명합니다. 단순히 “페이지를 긁는 코드”를 넘어서, 수집하고, 저장하고, 검색하고, 재시도하고, 설명까지 할 수 있는 운영형 시스템이 된다는 점입니다.
왜 기본적인 웹 스크레이핑은 그렇게 빨리 무너질까
대부분의 스크레이핑 튜토리얼은 여기서 멈춥니다.
“요청 보내고, HTML 파싱하고, 결과 출력하면 끝.”
프로토타입 단계에서는 충분합니다. 문제는 운영에 들어가는 순간부터 시작돼요.
보통은 이런 흐름으로 망가집니다.
- 첫 버전은 잘 동작합니다.
- 몇 번이고 반복 실행합니다.
- 사이트가 패턴을 감지하기 시작합니다.
- 요청이 차단되거나 CAPTCHA가 뜹니다.
- 국가별 페이지가 서로 다른 구조로 내려옵니다.
- 세션이 끊깁니다.
- 데이터가 비거나 어긋나기 시작합니다.
- 결국 결과를 신뢰하지 못하게 됩니다.
마지막이 특히 중요합니다. 나쁜 스크레이핑 시스템은 늘 요란하게 실패하지 않습니다. 조용히 망가져요. 부분 데이터만 가져오고, 오래된 가격을 섞어오고, 국가별로 기준이 다른 결과를 내면서도 겉으로는 “성공한 것처럼” 보일 수 있습니다.
웹 스크레이핑의 진짜 난제는 데이터를 가져오는 일이 아니라, 다음 주에도 믿을 수 있는 방식으로 계속 가져오는 일입니다.
특히 지역별 이커머스 스크레이핑이 더 어려운 이유
아마존처럼 국가별 마켓플레이스를 가진 서비스는 복잡도가 한 단계 더 올라갑니다.
- 같은 상품이 어떤 국가 사이트에는 있고, 어떤 국가 사이트에는 없을 수 있습니다.
- 가격은 지역, 통화, 현지 가격 정책에 따라 달라집니다.
- 페이지 레이아웃도 마켓플레이스마다 달라질 수 있습니다.
- 한 국가에서 유효한 ASIN이 다른 국가에서는 정상 결과를 반환하지 않을 수 있습니다.
- 같은 머신에서 반복 요청하면 금방 수상한 트래픽으로 보입니다.
실제로 단일 컴퓨터에서 직접 반복 요청을 보내는 방식은 몇 번 안 가서 막히는 경우가 많습니다. 대략 4~10회 수준의 반복 요청만으로도 블랙리스트 등록, CAPTCHA, 봇 탐지 같은 문제가 발생할 수 있습니다.
그래서 진지하게 가격 모니터링, 경쟁사 분석, 시장 추적을 하려면 처음부터 실패 대응과 확장성을 고려한 아키텍처가 필요합니다.
이 시스템은 무엇을 해결하려고 설계되었을까
이 시스템은 아주 단순한 비즈니스 질문에서 출발합니다.
“지금 이 상품은 아마존 각 국가 리전에서 얼마에 팔리고 있는가?”
전체 흐름은 이렇습니다.
- 상품 ASIN 입력
- 대상 국가 선택
- 각 아마존 도메인에서 상품 스크레이핑
- 데이터 저장
- 지역별 가격 비교
- 자연어로 후속 질문
이 구조를 잘 깔아두면 아래 같은 용도로 바로 확장할 수 있습니다.
- 경쟁사 가격 모니터링
- 지역별 이커머스 인텔리전스
- 가격 전략 분석
- 상품 재고 및 노출 여부 추적
- 내부 리포팅 자동화
실제로 어떻게 활용될 수 있을까
구체적인 예시를 보면 가치가 더 분명해집니다.
- Scrub Daddy는 프랑스, 스페인, 호주, 일본에서 스크레이핑되었고, 같은 상품이라도 국가별 가격이 다르게 나타났습니다.
- Kleenex는 여러 국가 도메인에서 확인되어 전용 가격 비교 화면에서 한눈에 비교할 수 있었습니다.
- iPad 가격은 AI 채팅 계층에서 “iPad 가격이 얼마야?” 같은 질문으로 바로 조회할 수 있었습니다.
- AXE 바디 스프레이 ASIN은 미국, 캐나다, 영국, UAE에서 테스트했는데, 실제로는 UAE에서만 유효한 결과가 나왔습니다. 이건 버그가 아니라, 국가별 상품 매핑이 실제로 다르다는 점을 보여주는 사례입니다.
이건 글로벌 스크레이핑에서 꼭 기억해야 할 포인트예요.
결과가 없다는 사실 자체가 실패가 아니라 의미 있는 데이터일 수 있습니다.
전체 아키텍처 한눈에 보기
상위 수준에서 보면 시스템 흐름은 다음과 같습니다.
- 사용자가 UI에서 스크레이핑 또는 질의를 실행합니다.
- 이벤트 오케스트레이션 계층이 요청을 받습니다.
- 백엔드 API가 실제 처리를 수행합니다.
- 스크레이퍼가 residential proxy를 통해 지역별 아마존 HTML을 가져옵니다.
- BeautifulSoup가 구조화된 상품 데이터를 추출합니다.
- 결과를 MongoDB에 저장합니다.
- 상품 텍스트를 임베딩해 Qdrant에 저장합니다.
- AI 에이전트가 두 저장소를 활용해 검색하고 답변합니다.
이제 각 계층을 나눠서 보겠습니다.
1) 애플리케이션 계층: Streamlit + FastAPI + Inngest
최상단 계층은 사용자가 시스템과 만나는 지점입니다.
사용자 인터페이스는 Streamlit으로 구성
Streamlit을 프론트엔드로 선택한 이유는 단순합니다. Python만으로 빠르게 동작하는 UI를 만들 수 있기 때문입니다. 빠르게 실험하고, 한 언어 안에서 전체 스택을 굴리고 싶을 때 특히 강합니다.
UI에서는 다음 작업을 수행할 수 있습니다.
- ASIN 입력
- 여러 대상 국가 선택
- 상품 스크레이핑 실행
- 저장된 상품 확인
- 국가별 가격 비교
- 저장된 데이터에 대해 AI 질의
내부 운영 도구, 데모 환경, 가벼운 대시보드 용도로는 이 정도만으로도 충분히 실용적입니다.
FastAPI는 백엔드 API를 담당
FastAPI는 UI와 핵심 로직 사이의 API 계층을 맡습니다.
이 선택의 장점은 크게 두 가지입니다.
- 프론트엔드와 백엔드가 깔끔하게 분리됩니다.
- 나중에 모바일 앱이나 다른 웹 앱이 생겨도 같은 백엔드를 재사용할 수 있습니다.
즉, 스크레이핑 엔진이 Streamlit UI 안에 갇히지 않습니다.
Inngest가 오케스트레이션과 모니터링을 맡는다
여기서부터 시스템이 “운영 친화적”이 됩니다.
Inngest는 UI와 API 사이에서 이벤트 오케스트레이션 계층으로 동작합니다. 스크레이핑을 단일 함수 호출로 취급하지 않고, 관찰 가능한 이벤트 기반 워크플로로 다루는 거죠.
핵심 액션은 두 가지입니다.
- scrape product
- query products
이렇게 구성하면 각 실행 단위를 추적하고, 단계별 동작을 확인하고, 실패를 명확하게 보고, 작업을 재시도하고, 진행 중인 작업을 취소하는 것까지 가능합니다.
이 차이는 꽤 큽니다.
오케스트레이션이 없으면 실패는 감에 의존하게 됩니다.
오케스트레이션이 있으면 실패는 추적 가능한 사건이 됩니다.
2) 스크레이핑 계층: 프록시 + 직접 HTTP 요청 + BeautifulSoup
이 계층은 한편으로는 단순하고, 또 한편으로는 상당히 정교합니다.
브라우저 자동화를 기본값으로 쓰지 않는다는 점에서는 단순합니다. 반면, 지역 지정이 가능한 residential proxy 인프라를 활용해 직접 요청 방식을 대규모에서도 버틸 수 있게 만들었다는 점에서는 꽤 정교합니다.
왜 직접 요청 방식이 여전히 좋은 선택일까
물론 아래 같은 도구를 사용할 수도 있습니다.
- Selenium
- Playwright
이 도구들은 버튼 클릭이 필요하거나, JavaScript 렌더링이 필수이거나, 실제 브라우저 세션을 흉내 내야 할 때 강력합니다.
하지만 필요한 데이터가 이미 HTML이나 XML 응답 안에 들어 있다면, 직접 HTTP 요청은 보통 다음 장점이 있습니다.
- 더 가볍습니다.
- 더 빠릅니다.
- 비용이 덜 듭니다.
- 확장하기 쉽습니다.
이번 시스템도 바로 이 접근을 택했습니다.
스크레이퍼는 어떻게 동작할까
흐름은 다음과 같습니다.
- 국가 코드에 맞는 Amazon 도메인을 결정합니다.
- ASIN으로 상품 URL을 만듭니다.
- residential proxy를 통해 요청을 보냅니다.
- HTML 또는 XML 형태의 페이지 원문을 받습니다.
- BeautifulSoup로 파싱합니다.
- 아래 같은 필드를 추출합니다.
- 제목
- 가격
- 브랜드
- 기타 상품 메타데이터
파싱은 비교적 안정적인 셀렉터를 기준으로 이뤄집니다.
- productTitle 식별자를 가진 span
- a-price-whole 같은 가격 관련 요소
- 브랜드 byline 관련 요소
필요한 경우 정규표현식으로 값을 정리해 최종 결과를 표준화합니다.
셀렉터를 만드는 실전형 지름길
이 구현에서 특히 실용적인 포인트가 하나 있습니다. HTML 태그를 일일이 뒤지지 않았다는 점입니다.
먼저 원시 페이지 소스를 로컬 HTML 파일로 저장한 뒤, 코드 에디터 환경에서 동작하는 로컬 LLM에게 그 파일을 읽히고, 일관된 태그와 패턴을 기반으로 스크레이핑 로직을 생성하도록 했습니다.
이건 꽤 영리한 워크플로입니다.
- 페이지 저장
- 구조 확인
- 모델에게 셀렉터 제안 요청
- 결과 검증 및 보정
즉, 사람이 일일이 HTML 고고학을 하는 시간을 줄이고, 검토 중심으로 작업 방식을 바꾼 거예요.
더 발전된 방식이라면 DOM을 채우는 JavaScript 객체에서 직접 데이터를 꺼낼 수도 있습니다. 이번 구현에서는 쓰지 않았지만, 다음 단계 최적화로는 충분히 고려할 만합니다.
스크레이핑을 빠르게 확장하는 가장 좋은 방법은 처음부터 더 복잡한 코드를 쓰는 것이 아니라, 사람이 손으로 해야 하는 불안정한 작업을 줄이는 것입니다.
3) 프록시 계층: 이 시스템을 현실로 만드는 핵심 부품
프록시 네트워크를 빼버리면, 나머지 구조는 훨씬 덜 신뢰할 만한 시스템이 됩니다.
과장이 아닙니다.
이 구성에서 사용한 프록시 제공자는 Thor Data이고, 그중에서도 residential proxy network가 핵심입니다. 이 네트워크의 역할은 단순히 “IP를 숨긴다”가 아닙니다. 세 가지를 동시에 해결합니다.
- 트래픽을 실제 사용자처럼 보이게 만든다
- 요청이 어느 국가에서 오는지 제어할 수 있게 한다
- 세션 관리를 통해 더 자연스러운 행동 패턴을 유지한다
residential proxy를 쉽게 설명하면
이렇게 생각하면 됩니다.
내 노트북에서 아마존 문을 계속 두드리는 대신, 전 세계에 흩어진 수많은 “진짜 사용자처럼 보이는 문”을 통해 대신 요청을 보내는 방식입니다.
흐름은 이렇습니다.
- 애플리케이션이 프록시 제공자에게 요청을 보냅니다.
- 제공자는 대상 국가에 맞는 노드를 고릅니다.
- 그 노드가 아마존 페이지를 요청합니다.
- 결과를 다시 애플리케이션으로 돌려줍니다.
이 구조가 있어야 지역별 스크레이핑이 가능합니다. 독일, 일본, 캐나다, UAE 사용자가 실제로 보는 페이지를 가져오려면, 요청도 그 나라에서 온 것처럼 보여야 하니까요.
규모와 지역 커버리지
이 시스템에서 사용한 프록시 네트워크는 다음 수준의 인프라를 제공합니다.
- 6천만 개 이상의 프록시 IP
- 190개국 이상 지원
이 정도 규모는 두 가지 면에서 중요합니다.
- 같은 정체성으로 반복 요청이 쌓일 가능성을 줄여줍니다.
- 국가별 스크레이핑을 위해 각 나라에 별도 인프라를 직접 세우지 않아도 됩니다.
추가 옵션으로는 다음과 같은 것들도 있습니다.
- mobile proxy
- 고대역폭 프록시
- static IP 프록시
- data center 프록시
- 웹 스크레이핑 API
설정은 생각보다 단순하다
구현 자체는 의외로 간단합니다.
- 프록시 계정 생성
- 사용자명과 비밀번호 발급
- 필요 시 내 IP 화이트리스트 등록
- 인증 문자열 생성
- 프록시 URL 생성
- HTTP 클라이언트에 주입
Python에서는 requests 세션에 http, https 프록시를 설정하는 것만으로도 충분히 구성할 수 있습니다.
이 시스템에서는 인증 문자열 안에 아래 같은 정보도 함께 넣습니다.
- 국가 코드
- 세션 ID
이렇게 하면 세션의 연속성이 필요할 때 같은 흐름처럼 유지할 수 있습니다.
비용과 사용량에 대한 감각
예시 구현에서는 대략 1GB 정도의 프록시 대역폭을 사용했고, 비용은 20달러 안팎으로 언급됩니다. 그런데 실제 테스트에서는 그 대역폭조차도 많이 소모하지 않았습니다.
이게 주는 메시지는 명확합니다.
무작정 큰 예산을 태우기보다, 요청 설계 자체를 효율적으로 만드는 것이 훨씬 중요합니다.
4) 저장소 계층: 진실은 MongoDB에, 속도는 Qdrant에
스크레이핑 시스템에서 자주 나오는 실수 하나가 있습니다.
하나의 데이터베이스에 모든 역할을 떠넘기는 것입니다.
이 시스템은 그걸 피했습니다. 역할을 분리했어요.
MongoDB는 전체 상품 기록과 이력을 저장
MongoDB는 다음과 같은 구조화된 상품 데이터를 저장합니다.
- 상품 제목
- 브랜드
- 국가
- 가격
- 통화
- 카테고리
- 스크레이핑 시각
- 이력 레코드
즉, 여기가 source of truth입니다.
정제된 상품 문서, 가격 이력, 상세 레코드를 확인하려면 MongoDB가 가장 적절합니다. 이번 구성에서는 Docker 위에서 로컬로 실행됩니다.
Qdrant는 의미 기반 검색을 담당
Qdrant는 중요한 상품 텍스트의 임베딩을 저장합니다.
그렇다면 왜 매번 MongoDB만 검색하지 않을까요?
데이터가 커지면 일반적인 레코드 조회만으로는 AI 스타일 질의에 비효율적인 경우가 많기 때문입니다. 벡터 데이터베이스를 쓰면 의미적으로 유사한 상품을 더 빠르게 찾을 수 있습니다.
그래서 아래 같은 질문을 더 자연스럽고 효율적으로 처리할 수 있습니다.
- “iPad 가격이 얼마야?”
- “이 상품과 비슷한 상품 보여줘”
- “이 상품의 국가별 엔트리를 찾아줘”
Qdrant 역시 이 구성에서는 Docker 기반 로컬 환경에서 동작합니다.
두 데이터베이스를 함께 쓰는 이유
논리는 단순합니다.
- MongoDB는 전체 진실을 보관한다
- Qdrant는 AI가 그 진실에 빨리 도달하도록 도와준다
일반적인 질의 흐름은 다음과 같습니다.
- Qdrant에서 관련 상품 후보를 찾는다
- MongoDB에서 전체 상품 스키마를 가져온다
- 그 정보를 바탕으로 답변을 생성한다
AI가 얹힌 데이터 시스템에서는 꽤 실전적인 패턴입니다.
5) AI 계층: 직접 SQL을 쓰지 않고 자연어로 묻기
이 아키텍처에서 가장 실용적인 요소 중 하나는, 스크레이핑된 데이터 위에 선택적으로 얹힌 AI 인터페이스입니다.
사용자에게 SQL을 쓰라고 요구하거나 원시 레코드를 뒤지게 하는 대신, 그냥 평범한 질문을 하도록 만드는 거죠.
에이전트 구성은 이렇게 된다
AI 계층은 다음 조합으로 구성됩니다.
- 임베딩 및 텍스트 생성: OpenAI
- 도구 연결과 에이전트 구성: LangChain
- 연결된 핵심 도구 3가지
- Amazon 스크레이퍼
- Qdrant 벡터 검색
- MongoDB 조회
이렇게 해두면 질문의 성격에 따라 에이전트가 적절한 경로를 선택할 수 있습니다.
예를 들면:
- 이미 저장된 데이터로 답할 수 있는 경우: Qdrant + MongoDB
- 최신 정보가 필요할 경우: 스크레이퍼를 도구처럼 직접 호출
왜 이게 실무에서 중요할까
비즈니스 팀 입장에서는 사용성이 크게 좋아집니다.
매번 엔지니어에게 새 쿼리를 요청할 필요 없이, 그냥 이렇게 물으면 됩니다.
- iPad 가격이 얼마인가요?
- 여러 국가 엔트리가 있는 상품은 무엇인가요?
- 이 상품의 국가별 가격 차이를 보여주세요.
진입 장벽이 확 낮아지죠.
결국 이 구조는 스크레이핑 시스템을 “개발자 전용 도구”에서 “조직 전체가 활용 가능한 데이터 자산”으로 바꿔줍니다.
6) 모니터링, 재시도, 관측성: 토이 프로젝트와 운영 시스템을 가르는 구간
많은 스크레이핑 프로젝트가 이 부분을 건너뜁니다.
그리고 대체로 그게 나중에 운영 불가능해지는 이유가 됩니다.
제대로 된 모니터링이 주는 것
Inngest를 붙이면 각 실행 단위마다 이런 정보가 보입니다.
- 어떤 ASIN이 요청됐는지
- 어떤 국가가 대상이었는지
- 어느 단계가 성공했고 실패했는지
- 단계별로 얼마나 시간이 걸렸는지
- 임베딩이 언제 생성됐는지
- 최종 결과가 언제 UI로 반환됐는지
이 정도 가시성이 생기면 운영 방식이 완전히 달라집니다.
상품이 유효하지 않거나, 비어 있거나, 특정 지역에서 존재하지 않으면 조기 종료 후 명확하게 로그를 남길 수 있습니다. 요청이 타임아웃으로 실패했는지도 바로 보입니다. 재시도가 필요하면 다시 돌릴 수 있고, 실행 중이면 취소도 가능합니다.
실제 운영 흐름은 이렇게 보인다
모니터링된 run 하나는 대략 이런 흐름을 보여줄 수 있습니다.
- scrape product 시작
- 특정 지역들에 대해 상품 요청
- 결과 수신 또는 빈 응답 감지
- 임베딩 단계 실행
- 마무리 단계 완료
- UI로 응답 반환
중요한 건, 문제가 생겨도 시스템이 그냥 “죽는” 게 아니라는 점입니다.
무슨 일이 일어났는지를 드러내 줍니다.
감으로 디버깅하는 것과, 근거를 보고 디버깅하는 것의 차이죠.
7) Docker 기반 배포: 서비스 다섯 개를 손으로 돌보지 않기 위해
이 스택에는 움직이는 조각이 많습니다.
- MongoDB
- Qdrant
- FastAPI
- Inngest
- Streamlit
이걸 매번 하나씩 수동으로 띄울 수도 있습니다.
하지만 그렇게 하면 안 됩니다.
왜 Docker Compose가 중요한가
Docker Compose를 쓰면 이 시스템이 비로소 “운영 가능한 형태”가 됩니다.
할 수 있는 일은 명확합니다.
- 명령 한 번으로 전체 스택 실행
- 깔끔한 종료
- 환경 일관성 유지
- 반복 가능한 로컬 개발
- 이후 배포 단순화
이번 구성은 총 다섯 개 컨테이너로 이뤄집니다.
- MongoDB 컨테이너
- Qdrant 컨테이너
- FastAPI 컨테이너
- Inngest 컨테이너
- Streamlit 컨테이너
README에는 다음 정보가 정리됩니다.
- 실행 명령
- 종료 명령
- 각 서비스 포트
- 필요한 환경 변수
이런 문서화는 화려하진 않지만, 시스템을 진짜 시스템답게 만드는 요소입니다.
8) 전체 워크플로: 요청부터 답변까지 어떻게 흐를까
이제 전체 흐름을 처음부터 끝까지 묶어보겠습니다.
1단계: 입력 받기
사용자는 다음을 입력합니다.
- ASIN
- 대상 국가 도메인 목록
이렇게 스크레이핑 작업의 범위가 정해집니다.
2단계: 이벤트 생성
UI가 요청을 Inngest로 보냅니다.
이제 이 작업은 추적 가능하고, 재시도 가능하고, 내부 상태를 확인할 수 있는 이벤트가 됩니다.
3단계: 지역별 요청 구성
스크레이퍼는 다음 작업을 수행합니다.
- 국가 코드를 해당 Amazon 도메인으로 매핑
- 상품 URL 생성
- 프록시 인증이 포함된 요청 생성
- 필요 시 세션 ID 설정
4단계: 페이지 원문 가져오기
요청은 residential proxy 네트워크를 거쳐 페이지 원문을 반환합니다.
실패하면 시스템은 예외를 발생시키고, 그 실패 사실을 기록합니다.
5단계: 페이지 파싱
BeautifulSoup가 아래 같은 구조화된 필드를 뽑아냅니다.
- 제목
- 가격
- 브랜드
그리고 이 값을 JSON 형태의 상품 객체에 채워 넣습니다.
6단계: 상품 데이터 저장
구조화된 결과는 MongoDB에 저장됩니다.
이렇게 해야 전체 상품 기록과 가격 이력을 나중에 다시 활용할 수 있습니다.
7단계: 임베딩 생성 및 저장
핵심 텍스트 필드를 임베딩해서 Qdrant에 저장합니다.
이 단계가 있어야 AI 질의에서 의미 기반 검색이 빨라집니다.
8단계: 결과를 UI에 반환
이제 UI는 아래 같은 내용을 보여줄 수 있습니다.
- 스크레이핑 결과
- 지역별 비교
- 상품 목록
- 가격 차트
- AI 기반 답변
9단계: 모니터링과 개선
각 run은 오케스트레이션 계층에 남아 있기 때문에 다음이 가능합니다.
- 실패 원인 확인
- 단계별 시간 측정
- 작업 재실행
- 작업 취소
- 장기적인 안정성 개선
9) 이 아키텍처가 실제로 할 수 있는 일들
조금 더 현실적인 사례로 보겠습니다.
Scrub Daddy를 프랑스, 스페인, 호주, 일본에서 비교
이 사례는 지역별 스크레이핑이 왜 필요한지를 잘 보여줍니다. 같은 상품이 여러 Amazon 국가 사이트에 있었지만, 가격은 같지 않았습니다.
심지어 유로를 쓰는 시장 안에서도 차이가 났습니다. 이건 단순 환율 차이보다 현지 가격 정책 차이를 시사합니다.
Kleenex의 다국가 비교
Kleenex는 여러 국가 도메인에서 확인되었고, 전용 비교 화면 안에서 묶어서 볼 수 있었습니다. 이런 구조가 있으면 원시 레코드를 일일이 훑지 않고도 다지역 상품을 분석하기 쉬워집니다.
iPad를 AI 채팅으로 조회
데이터베이스 쿼리를 직접 작성하는 대신, 자연어 질문으로 iPad 가격을 조회할 수 있었습니다.
이건 사용성 측면에서 꽤 큰 진전입니다.
시스템이 “엔지니어링 도구”에서 “비즈니스 팀도 쓸 수 있는 도구”로 넘어가는 지점이죠.
AXE 바디 스프레이는 UAE에서만 유효
이 사례는 특히 중요합니다. 미국, 캐나다, 영국, UAE에서 같은 ASIN을 테스트했지만, 유효한 결과는 UAE에서만 나왔습니다.
이건 특이 케이스가 아닙니다.
오히려 실제 운영 환경에서 자주 마주치는 지역별 상품 매핑 불일치를 잘 보여줍니다. 이런 미묘한 데이터 품질 이슈를 시스템이 우아하게 처리할 수 있어야 합니다.
10) 이 아키텍처가 잘한 점
이 설계에는 특히 좋은 결정이 세 가지 있습니다.
1. 스크레이핑을 스크립트가 아니라 인프라로 다뤘다
이 한 가지 관점 전환만으로도 많은 것이 달라집니다.
재시도, 관측성, 저장, 확장성 모두가 부수 기능이 아니라 핵심 기능이 됩니다.
2. 검색과 원본 저장의 역할을 분리했다
Qdrant는 관련 레코드를 빠르게 찾는 데 집중하고, MongoDB는 전체적이고 신뢰할 수 있는 기록을 보관합니다. 하나의 시스템에 모든 걸 몰아넣으려는 구조보다 훨씬 깔끔하고 확장성도 좋습니다.
3. 운영자 관점의 가시성을 최우선으로 뒀다
실행 내역을 확인하고, 실패를 보고, 단계별 시간을 측정하고, 작업을 다시 돌릴 수 있습니다. 이런 구조가 있어야 스크레이핑 시스템을 장기적으로 신뢰할 수 있습니다.
강한 스크레이핑 시스템은 실패를 가장 적게 하는 시스템이 아니라, 실패를 잘 보이게 만들고, 복구 가능하게 만들고, 결국 평범한 운영 이슈로 바꾸는 시스템입니다.
11) 한계와 실무상 주의할 점
어떤 스크레이핑 시스템도 완벽하지는 않습니다. 이 구조도 분명한 경계가 있습니다.
ASIN만으로는 글로벌 상품 식별이 부족할 수 있다
같은 상품이 항상 지역 간에 깔끔하게 대응되는 것은 아닙니다. 더 강한 매칭 로직이 필요하다면 다음 요소들을 함께 써야 할 수 있습니다.
- 제목
- 브랜드
- 용량 또는 크기
- 패키징 정보
- 카테고리
- 기타 메타데이터
정말로 “전 세계 동일 상품 비교 엔진”을 만들고 싶다면 ASIN 하나만으로는 부족할 수 있습니다.
정적 파싱에는 한계가 있다
BeautifulSoup는 필요한 데이터가 페이지 원문 안에 들어 있을 때 매우 적합합니다. 하지만 사이트가 더 동적으로 바뀌거나 DOM 구조 변경이 잦아지면 아래 접근이 필요해질 수 있습니다.
- JavaScript 객체 직접 추출
- Playwright
- Selenium
- 더 강건한 파싱 전략
AI 품질은 결국 검색 품질에 달려 있다
자연어 계층의 성능은 결국 아래 요소들에 좌우됩니다.
- 임베딩 품질
- 벡터 인덱싱 설계
- 도구 연결 방식
- 에이전트 로직
이 부분이 약하면 AI가 그럴듯하게 말하더라도 내용은 불완전할 수 있습니다.
가격 비교에는 비즈니스 맥락이 필요하다
지역별 가격 차이가 있다고 해서 곧바로 기회라는 뜻은 아닙니다. 해석할 때는 아래 요소도 함께 봐야 합니다.
- 환율
- 세금
- 배송비
- 번들 구성
- 현지 프로모션
- 지역별 카탈로그 차이
가격 차이는 신호일 뿐입니다. 그 자체로 결론은 아닙니다.
12) 앞으로 어떻게 더 발전시킬 수 있을까
이 아키텍처는 이미 꽤 강하지만, 다음 단계로 자연스럽게 확장할 여지도 많습니다.
지역 간 상품 매칭 고도화
ASIN에만 의존하지 말고, 상품 메타데이터를 함께 조합한 유사도 로직을 추가하면 지역 간 동일 상품 식별 정확도를 높일 수 있습니다.
더 견고한 파싱
필요할 때는 정적 HTML 셀렉터를 넘어, 내장된 JavaScript 데이터 추출이나 선택적 브라우저 렌더링을 도입하는 방식으로 강화할 수 있습니다.
분산 워커와 큐 도입
작업량이 커지면 단일 노드 패턴 대신, 스크레이핑 작업을 분산 워커와 큐 기반 구조로 넘기는 것이 좋습니다.
더 똑똑한 캐싱
변화 없는 상품 페이지나 이전 조회 결과를 캐시하면 대역폭과 중복 호출을 줄일 수 있습니다.
더 넓은 사이트 확장
이 아키텍처는 사실 Amazon 전용이라고 보긴 어렵습니다. 프록시 설정과 파싱 규칙만 바꾸면 다른 마켓플레이스나 일반 웹사이트에도 충분히 적용 가능합니다.
결국 핵심은 대상 사이트가 아닙니다.
지속적으로 쓸 수 있는 시스템 설계 자체가 핵심입니다.
마무리
확장 가능한 가격 스크레이핑 시스템은 스크레이핑 코드를 계속 덧붙인다고 만들어지지 않습니다.
수집, 지역 제어, 관측성, 저장, 검색, 질의 가능성을 올바르게 분리하고 연결해야 비로소 만들어집니다.
이 Python 기반 아키텍처는 바로 그 점을 잘 보여줍니다. Streamlit, FastAPI, Inngest, BeautifulSoup, residential proxy, MongoDB, Qdrant, OpenAI, LangChain, Docker를 조합해, 쉽게 깨지는 페이지 수집 코드를 운영 가능한 지역별 데이터 플랫폼으로 바꿔냈습니다.
경쟁사 모니터링, 국가 간 이커머스 인텔리전스, 상품 가격 관측 시스템을 만들고 있다면, 화려해서가 아니라 실제로 시스템을 망가뜨리는 지루한 문제들을 제대로 해결해 준다는 이유로 이런 구조를 참고할 가치가 있습니다.
FAQ: 실제로 많이 궁금해하는 질문들
1) 왜 모든 걸 Playwright나 Selenium으로 처리하지 않나요?
그렇게 할 수도 있습니다. 다만 항상 그럴 필요는 없습니다. 필요한 상품 데이터가 이미 HTML이나 XML 응답 안에 있다면, 직접 요청 + BeautifulSoup 조합이 더 빠르고, 가볍고, 확장하기 쉬운 경우가 많습니다. 브라우저 자동화는 실제 렌더링이나 상호작용이 꼭 필요한 경우에만 쓰는 편이 효율적입니다.
2) Amazon 스크레이핑에서 residential proxy가 왜 그렇게 중요하나요?
대형 이커머스 사이트는 반복적인 자동화 요청을 빠르게 감지합니다. residential proxy를 사용하면 요청이 실제 사용자 트래픽처럼 보이게 만들 수 있고, 어느 국가에서 요청이 들어오는지도 제어할 수 있습니다. 덕분에 신뢰성과 지역 정확도가 함께 올라갑니다.
3) 같은 ASIN이 모든 국가에 존재하지 않으면 어떻게 되나요?
그건 자연스러운 상황입니다. 결과가 없다는 사실이 시스템 오류가 아니라, 실제 카탈로그 차이를 반영하는 경우가 많습니다. 따라서 스크레이퍼는 이를 실패로만 처리하지 말고, 의미 있는 비즈니스 정보로 기록해야 합니다.
4) 왜 MongoDB와 Qdrant를 둘 다 쓰나요?
둘이 해결하는 문제가 다르기 때문입니다. MongoDB는 전체 상품 기록과 이력을 저장합니다. Qdrant는 빠른 의미 기반 검색을 위한 임베딩을 저장합니다. 둘을 함께 써야 AI가 관련 상품을 빨리 찾고, 그다음 정확한 상세 정보를 source of truth에서 가져올 수 있습니다.
5) 스크레이핑 시스템에 AI가 꼭 필요한가요?
반드시 그렇진 않습니다. AI 없이도 강한 스크레이핑 파이프라인은 충분히 만들 수 있습니다. 다만 비개발자가 자연어로 질문해야 하거나, 대규모 상품 데이터 위에서 더 유연한 검색 경험을 제공하고 싶다면 AI가 큰 가치를 만들어 줍니다.
6) 운영 환경에서는 스크레이핑 실패를 어떻게 처리하나요?
실패가 잘 보이도록 만들어야 합니다. 명확한 로그, 실행 이력, 재시도 지원, 단계별 모니터링이 필요합니다. 그래서 오케스트레이션 계층이 중요합니다. 조용히 실패하는 시스템이 가장 위험합니다.
7) 이런 시스템은 테스트 비용이 얼마나 드나요?
예시 구성에서는 약 1GB 정도의 프록시 대역폭을 사용했고, 비용은 20달러 안팎 수준이었습니다. 실제 테스트에서는 그것마저도 많이 쓰지 않았습니다. 규모가 커지면 비용도 늘겠지만, 요청 설계와 캐싱을 잘하면 초기 실험 단계의 비용은 생각보다 낮게 유지할 수 있습니다.
8) 이 아키텍처는 Amazon 말고 다른 사이트에도 쓸 수 있나요?
네, 가능합니다. 이벤트 기반 스크레이핑, 프록시 기반 지역 제어, 이중 저장소, AI 질의 지원이라는 핵심 패턴은 다른 이커머스 사이트는 물론 일반 웹사이트에도 적용할 수 있습니다. 필요한 건 대상 사이트에 맞춘 파서 조정입니다.
'SW > 클라우드 서비스 아키텍처' 카테고리의 다른 글
| 데이터 레이크하우스란 무엇인가요? 데이터 레이크·데이터 웨어하우스 차이까지 쉽게 정리 (0) | 2026.05.17 |
|---|---|
| 멀티클라우드 아키텍처란 무엇인가? AWS·GCP·Azure 함께 쓰는 방법 완전 정리 (0) | 2026.04.22 |
| DevOps 로드맵 정리: 초보자가 Linux부터 CI/CD까지 배우는 현실적인 순서 (0) | 2026.02.17 |
| 2025 Cloudflare 대규모 장애 원인 분석: bot mitigation config 파일 하나가 인터넷을 멈춘 이유 (0) | 2025.12.30 |
| Kafka란? LinkedIn·Netflix·Uber가 선택한 이유와 핵심 개념 완벽 정리 (0) | 2025.12.22 |