Agent-Reach 프로덕션 배포 시 프록시 비용과 토큰을 줄이는 인프라 설계
19 जून 2026
0
컴퓨터/소프트웨어Comments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
로컬 CLI에서 잘 돌아가던 Agent-Reach 기반 에이전트도 운영 서버에 올리는 순간 사방에서 벽에 부딪힌다. 수만 건의 스크랩 요청이 몰리면 Cloudflare 같은 CDN 보안망에 걸려 IP가 줄줄이 차단된다. 그렇다고 유료 주거용 프록시만 고집하면 대역폭 비용 감당이 안 된다. 원시 HTML을 그대로 LLM에 밀어 넣다가 문맥이 터지고 토큰 요금 폭탄을 맞기도 한다. 이 문제를 해결하려면 동적 라우팅 아키텍처와 전처리 파이프라인이 필요하다.
Agent-Reach를 무방비하게 운영하면 유료 주거용 프록시 비용으로만 수천 달러를 쓰게 된다. 하루 100,000건의 요청을 처리하고 페이지당 평균 크기가 150KB인 시스템에서 실패율이 50%까지 올라가면 월간 데이터 전송량은 675GB에 달한다. Bright Data나 Oxylabs 같은 프리미엄 주거용 프록시는 GB당 4달러에서 8달러 선이다. 모든 트래픽을 여기로 태우면 월 비용이 5,400달러까지 치솟는다.
오픈소스 프록시 애그리게이터인 Scrapoxy를 Docker 컨테이너 기반의 슈퍼 프록시로 배포하면 단일 엔드포인트를 유지하면서 인프라 비용을 제어할 수 있다. 먼저 프로젝트 루트에 docker-compose.yml 파일을 생성하고 valkey/valkey:7.2-alpine 이미지와 fabienvauchelles/scrapoxy:latest 이미지를 정의한다. Valkey 컨테이너에 --appendonly yes --requirepass [비밀번호] 명령을 지정해 크레덴셜 캐싱의 지속성을 확보한다. Scrapoxy 환경변수에 유저네임과 패스워드를 설정한 후 docker compose up -d 명령으로 컨테이너를 구동한다. 이 구성을 통해 유료 서비스 구독 비용을 월 200달러 이상 아낄 수 있다.
타깃 플랫폼의 보안 정책에 따라 IP 교체 주기는 이원화해야 세션이 깨지지 않는다. 인증이 필요 없는 공개 Read-Only 요청은 30초에서 3분 사이의 공격적인 TTL을 설정해 라운드 로빈 방식으로 매번 신규 IP를 강제 할당한다. 임계치 기반 차단을 회피하기 위한 조치다. 반면 X나 Reddit처럼 세션 쿠키 유지가 필수인 인증 기반 플랫폼은 Scrapoxy의 쿠키 인젝션 기능을 활성화해 5분에서 10분 동안 동일한 주거용 IP 노드를 고정한다. 지리적 IP가 갑자기 바뀌어 인증 세션이 만료되는 현상을 막기 위함이다.
비용을 더 깎으려면 NGINX API 게이트웨이 레이어에서 트래픽 라우팅을 최적화해야 한다. NGINX 구성 파일(/etc/nginx/nginx.conf)의 upstream 블록에 GB당 1달러 수준인 DataImpulse 등의 저비용 데이터센터 프록시 풀과 Scrapoxy 주거용 프록시 풀을 각각 정의한다. server 블록 내에 /fetch/generic/ 로케이션을 생성해 RSS 피드나 GitHub 검색 등 보안 강도가 낮은 공개 HTML 트래픽을 데이터센터 프록시로 포워딩한다. 이어서 /fetch/social/ 로케이션을 만들어 고마찰 소셜 엔드포인트 요청만 Scrapoxy 백엔드로 라우팅하고 헤더를 주입한다. 이 2트랙 라우팅을 적용하면 값비싼 주거용 프록시의 대역폭 낭비를 막고 전체 프록시 비용을 최대 90%까지 감축한다.
원시 HTML 데이터는 중복 DOM 요소, 스타일시트, 인라인 스크립트 덩어리다. 이걸 LLM에 그대로 입력하면 불필요한 토큰을 소비하고 추론 결과도 흐려진다. 웹페이지 원본을 정제되지 않은 상태로 컨텍스트 윈도우에 주입하는 대신 마크다운으로 변환하면 데이터 크기가 75%에서 90%까지 줄어든다. 파이프라인 전처리 단계에서 정규식 기반 정제와 마크다운 직렬화를 수행하면 LLM API 토큰 소모량을 40% 이상 절감하면서 윈도우 초과 에러를 방지할 수 있다.
파서 컴포넌트인 Trafilatura와 html2text를 조합해 입력 데이터를 전처리하는 Python 함수를 구현한다. trafilatura.extract() 함수를 호출할 때 favor_recall=False 옵션을 지정해 사이드바나 광고를 배제하고 본문 텍스트만 추출한다. 메인 콘텐츠 블록 추출에 실패할 때를 대비해 html2text.HTML2Text() 객체를 생성하고 ignore_images=True 및 body_width=0을 설정하는 Fallback 코드를 삽입한다. 추출된 마크다운 텍스트에서 <script>, <style> 등 잔여 태그를 제거하는 정규식(re.sub)과 연속된 공백 라인을 축소하는 정제 루틴을 실행하면 에이전트의 응답 지연 시간이 줄어든다.
긴 문서를 분할할 때는 단순 글자 수 기준의 청킹 대신 의미론적 유사도를 기준으로 문맥을 유지하는 세분화 알고리즘을 도입해야 한다. 문장 단위로 분할된 텍스트의 임베딩 벡터 간 코사인 유사도를 계산해 의미적 단절이 발생하는 지점을 포착한다.
인접한 문장 간의 거리를 연산한 뒤, 거리 차이가 전체 문서의 95백분위수를 초과하는 경계면을 세맨틱 분할점으로 확정해 청크 리스트를 생성한다. 고정 길이 청킹 방식보다 의미론적 청킹을 적용하는 편이 관련 정보가 서로 다른 청크로 쪼개져 소실되는 현상을 막고 LLM의 정보 검색 정확도를 개선한다.
X나 LinkedIn 같은 플랫폼은 속도 제한이 엄격하다. HTTP 429나 403 에러가 빈번하게 터진다. 이런 일시적인 장애 상황에서 동기식 애플리케이션 프로세스가 즉시 재시도를 반복하면 서버 리소스가 고갈되고 IP 차단 수위만 높아진다. 시스템 복원력을 확보하려면 발생한 예외의 성격을 규명하고 타깃 서버에 가해지는 부하를 동적으로 조절하는 비동기식 예외 처리 미들웨어가 필요하다.
에러 핸들러 클래스를 설계할 때 일시적 오류와 영구적 오류를 정확히 분기해야 한다. HTTP 상태 코드가 429, 502, 503, 504이거나 에러 메시지에 'timeout', 'connection refused'가 포함된 경우는 일시적 오류로 분류해 재시도 대상으로 지정한다. 반면 401이나 400 등은 영구적 오류로 판정해 즉시 Dead Letter Queue(DLQ)로 격리한다. 일시적 오류인 경우, 동일한 타이밍에 요청이 몰려 발생하는 Thundering Herd 문제를 방지하기 위해 임의의 밀리초 무작위 지터를 포함한 지수 백오프 알고리즘을 적용한다. 대기 시간 산출 공식은 다음과 같다.
초기 기저 지연 시간()을 30초로 설정하고 최대 한도()를 600초로 제한하면, 3회차 재시도 시 약 240초 내외의 분산된 대기 시간이 보장되어 타깃 플랫폼의 차단 정책을 우회한다.
특정 플랫폼의 장애나 보안 강화가 전체 워크플로우를 마비시키는 연쇄 장애를 차단하기 위해 Redis 기반의 차단벽 패턴을 미들웨어 레이어에 구현한다. 단일 글로벌 큐 대신 목적지 도메인별로 분리된 독립 Redis 리스트(queue:bulkhead:twitter, queue:bulkhead:reddit, queue:bulkhead:general)를 생성한다. 각 큐를 소비하는 워커 풀의 최대 컨커런시 한도를 Twitter는 3, General Web은 25와 같이 차등 할당한다. 실패한 태스크의 재시도 스케줄을 관리하기 위해 Redis의 Sorted Set을 활용해 복귀 타임스탬프를 스코어로 등록하는 지연 처리 루틴을 작성한다. 이 차단벽 구조를 적용하면 특정 소셜 미디어의 API 차단 사태가 발생하더라도 해당 워커만 대기 상태에 빠질 뿐, 전체 에이전트의 리서치 작업 완료 성공률을 95% 이상으로 방어한다.
다양한 웹 소스에서 무작위로 긁어온 원시 데이터에는 날짜 불일치나 허위 사실이 포함되어 있어 LLM이 왜곡된 추론을 하기 쉽다. 생성형 AI 모델에 컨텍스트를 제공하기 전에 마크다운 파일 내용의 신뢰성을 연산하고 수치적 정합성을 검증하는 불연속적인 검증 레이어를 파이프라인 종단에 결합해야 환각 현상을 차단할 수 있다.
수집된 메타데이터의 시간적 유효성과 플랫폼 출처별 가중치를 연산하는 결정론적 필터 클래스를 설계한다. 시스템 시간 기준으로 미래의 타임스탬프를 가졌거나 타당하지 않은 ISO 포맷의 날짜를 담고 있는 문서는 데이터 세트에서 즉시 제외한다. 또한 플랫폼 소스별 신뢰도 가중치를 매핑하는 딕셔너리를 선언해 GitHub에는 0.95, Wikipedia에는 0.90을 부여하고 Reddit(0.50)이나 Twitter(0.40) 같은 소셜 미디어 정보에는 낮은 기본 점수를 배정한다. 문서 내 저자명과 타이틀이 온전하게 보존되어 있는 경우에만 0.05의 메타데이터 가중치 보너스를 추가하는 로직을 거쳐 최종 신뢰도 점수를 생성한다. 점수가 기준에 미달하는 정보 자산은 LLM 프롬프트 조립 단계에서 원천 배제된다.
출력 데이터의 품질을 최종 보증하기 위해, 생성된 답변 후보군을 원본 콘텍스트와 대조하는 채점 스크립트를 가동한다.
\b\d+(?:\.\d+)?%?\b)을 활용해 원본 데이터셋에 존재하는 숫자 기호 세트와 생성 문장 내 숫자 세트를 교집합 연산한다. 소스에 없는 임의의 수치나 화폐 단위가 검출되면 수치 불일치 플래그를 발생시키고 즉시 라우팅 미들웨어를 통해 재수행을 요청한다.이러한 다층 검증 레이어를 연동함으로써 크롤링 기반 에이전트가 저지르는 수치 조작 및 허위 인용 문제를 아키처 레벨에서 차단하고 완전히 검증된 리서치 결과만을 최종 사용자에게 인도한다.