문제점
버티컬 AI 스타트업은 모두 2개월 차쯤에 같은 장벽에 부딪힙니다. 이들은 지원 코파일럿, 법률 조사 어시스턴트, 컴플라이언스 봇을 배포합니다. 첫 번째 데모로 고객을 확보합니다. 그 후 데이터가 노후화되고 답변은 현실에서 벗어나기 시작합니다.
우리는 여러 팀이 AI 측면은 깔끔하게 구축하면서 데이터 측면은 나중에 생각하는 것을 보았습니다. 수집 파이프라인은 누군가의 노트북에서 실행되는 Python 스크립트 하나입니다. 이 스크립트는 200개의 소스 URL을 한 번 스크랩하고 정리된 Markdown을 벡터 저장소에 덤프하며 모두가 이를 축하합니다. 6주 후, 답변의 절반은 삭제된 페이지, 지원 중단된 API, 또는 3월에 출시되었다가 5월에 다시 출시된 제품 기능을 인용합니다.
해결책은 간단해 보입니다. 매주 모든 소스를 재크롤링하는 것입니다. 현실은 더 참혹합니다. 2026년까지 신뢰할 수 있는 사이트의 약 60%가 AI 크롤러를 차단하며(2023년 말 23%에서 증가), 이러한 보호 조치는 더 이상 단순한 User-Agent 검사가 아닙니다. 이들은 세션 동작, request 리듬, 핸드셰이크 수준의 신호를 분석합니다. 1월에 작동했던 단순한 스크립트는 3월에 말없이 빈 페이지를 반환합니다.
더 나쁜 것은 일부 사이트가 임베딩을 오염시킬 때까지 타르핏 콘텐츠(실제 산문처럼 읽히는 Markov 생성 헛소리)를 제공한다는 것입니다. 따라서 엔지니어들은 제품을 배포하는 대신 일주일의 절반을 스크래퍼 패치에 소비합니다. 검색 품질이 떨어지고 고객이 이를 알아차리며 AI 구축을 위해 고용한 팀은 스크래퍼 유지보수 담당으로 전락합니다.
접근 방식
재크롤링 문제는 모든 request에서 발생해야 하는 세 가지 구체적인 결정으로 나뉩니다.
- 렌더링 여부. 대부분의 문서 포털은 깔끔한 HTML을 제공합니다. 하지만 점점 더 많은 비율(Next.js로 구축된 모든 항목, 클라이언트 측 렌더링이 있는 모든 항목)이 유용한 콘텐츠를 반환하기 위해 전체 브라우저 렌더링을 필요로 합니다.
- 어떤 proxy를 사용할 것인가? 주거용, 데이터센터, 모바일, 지역 지정, 특정 ISP. 올바른 선택은 타겟에 따라 달라집니다.
- 실제로 작동했는가? 본문이 비어 있는 200이나 CAPTCHA HTML 페이지는 성공적인 HTTP request이지만 실패한 크롤링입니다.
FourA와 같은 플랫폼은 이러한 각각의 문제를 1급 관심사로 처리합니다.
렌더링 결정의 경우, 저렴하고 빠른 케이스에는 Single을 호출하고 JS가 많은 타겟에는 Browser를 호출합니다. 호출 본문은 동일한 형태이므로, 수집 코드는 수백 개의 사이트별 특성을 가지는 대신 소스별 플래그를 기준으로 한 번만 분기합니다.
proxy 선택을 위해 Proxy Finder는 모든 Single, Browser, Auto 호출의 일부로 실행됩니다. 플랫폼은 request당 작동하는 출구를 선택하고 response에 불투명한 id를 반환하며(Single/Browser의 경우 r.proxy 최상위, Auto의 경우 r.session.proxy), 동일한 출구를 유지해야 하는 후속 호출에서 해당 id를 재사용합니다. 크롤러는 자체 proxy 순위 알고리즘을 가지지 않습니다. (풀 크기가 더 이상 차별화 요소가 아닌 이유에 대해서는 2026년에 Proxy 풀 크기가 중요하지 않게 된 이유에서 작성했습니다.)
그리고 "실제로 작동했는가"라는 질문에 대해 모든 request는 validate 블록을 지원합니다. 허용되는 상태 코드, 필수 header 값, 반드시 나타나야 하거나 나타나지 말아야 하는 본문 문자열 등 성공으로 간주되는 항목을 선언합니다. FourA는 7가지 결과 중 하나를 반환하며 success만 청구 대상입니다. 콘텐츠 규칙에 실패한 200은 application_fail로 표시되며 데이터 세트에 입력되지 않습니다.
JS 렌더링이 필요한 문서 포털에 대한 재크롤링 호출은 다음과 같습니다. Auto가 오케스트레이션하도록 합니다. 이는 올바른 제품(Single, Proxy, Browser)을 선택하고 봇 방어를 처리하며 다음 재크롤링이 동일한 출구를 유지할 수 있도록 세션 3종 세트를 반환합니다.
import requests
r = requests.post(
"https://api.foura.ai/api/auto",
headers={"Authorization": "Bearer pk_live_..."},
json={
"url": "https://docs.example.com/changelog",
"validate": {
"status": {"accept": [200]},
"data": {"accept": ["<article"], "fail": ["captcha", "Just a moment"]},
},
},
).json()
# r["data"] or r["body"] — rendered content (Auto runs the right sub-product per host;
# Single populates "data", Browser populates "body")
# r["session"] — { "proxy": "<base36 id>", "cookies": [...], "userAgent": "..." }
# On the next recrawl, pass r["session"]["proxy"] back as `ignoreProxies: [<id>]` to avoid
# the same exit, or via /api/single with `proxy: <id>` to stick to it.
타겟이 Cloudflare 전면 광고를 던지면 validate.data.fail 규칙이 이를 포착합니다. 사용량에 찍히는 결과는 application_fail입니다. 요금이 청구되지 않으며, 수집 코드는 "잠시만 기다려주세요..." 페이지를 임베딩에 공급하는 대신 다른 proxy로 재시도해야 한다는 것을 알게 됩니다.
더 넓은 말뭉치의 경우 동일한 패턴을 기존 작업 대기열에 래핑합니다. 우리가 대화한 팀들은 이전 크롤링과 비교하여 야간 diff를 실행하고 실제로 변경된 문서만 다시 임베딩하며 몇 시간의 실제 소요 시간 내에 500개 소스 말뭉치를 새로 고칩니다. 작업 대기열은 귀하의 소관입니다. proxy 교체, 렌더링 결정, 성공 판정은 우리의 몫입니다.
결과
인프라가 더 이상 병목 현상이 되지 않을 때 최신 상태 루프가 어떻게 보이는지 보여줍니다(버티컬 AI 팀에서 관찰된 패턴에 기반한 설명 시나리오).
- 출시 시점의 200개 URL 단발성 크롤링 대신 매주 500개의 소스 URL 재크롤링
- 1-2일에서 단축된 주당 2시간 미만의 스크래퍼 엔지니어링 시간
- 무제한에서 단축된 5-7일의 검색 노후화 기간
- Cloudflare 전면 광고 및 타르핏 페이지가 임베딩 모델에 도달하기 전에
validate계층에서 거부되므로 벡터 저장소의 가비지 비율이 거의 0에 수렴 - 실패한 크롤링은 청구서에 표시되지 않으므로 소스당 예측 가능한 비용
요점은 이것들이 마법이 아니라는 것입니다. 요점은 지루하다는 것입니다. 그리고 지루함이야말로 프로덕션 AI에 필요한 것입니다. (호스팅된 LLM 추출에서 수학이 작동하지 않는 위치에 대한 자세한 내용은 LLM 추출이 더 이상 비용을 감당하지 못하는 시기를 참조하세요.)
핵심 요약
버티컬 AI를 구축하는 대부분의 팀은 해자가 프롬프트, 모델 선택 또는 검색 알고리즘이라고 생각합니다. 그렇지 않습니다. 해자는 최신 상태 루프입니다. 매주 지식 기반을 정직하게 유지하는 매력적이지 않은 인프라입니다.
2026년까지 버티컬 AI에서 승리하는 팀은 가장 영리한 프롬프트를 가진 팀이 아닐 것입니다. 데이터가 항상 최신이므로 사용자가 데이터의 최신 여부를 전혀 의식하지 못하게 만드는 팀일 것입니다.