지금까지 last_bytes=page.content()(렌더된 DOM 크기)라 실제 네트워크 전송량이 아니었다
— 리소스 차단 효과가 안 보이고 ESM DOM(~5MB) 과대계상 → DECODO 비용이 부정확했다.
- browser_base: CDP 세션(new_cdp_session) 부착, Network.loadingFinished 의 encodedDataLength
누적 → last_bytes=실제 전송 바이트. 컨텍스트당 1회 부착, 검색마다 리셋. 미지원 시 DOM 폴백.
- 실측(gmarket): 콜드(차단해제) 3.44MB → 웜(차단활성) 1.07MB(~3x↓) — 동적 차단 효과가 이제 숫자로 보임.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
프록시(DECODO) 포트/IP 사망(407/ERR_TUNNEL/ERR_HTTP_RESPONSE_CODE_FAILURE)이
봇차단과 구분 없이 예외로 튕겨 같은 죽은 포트로 재시도만 하다 DEAD 되던 문제를 고친다.
- browser_base: is_proxy_error(순수함수) + search 루프에서 프록시 전송오류 시 IP 회전 재시도
(max_proxy_retries=2). 봇감지 회전과 통합. uses_proxy 프로퍼티.
- 쿠팡 어댑터를 BrowserSearchAdapter 로 통합 — 중복 machinery 제거, 회전 로직 한 곳에서 공유
(detect_block 순수함수는 유지, 테스트 호환).
- proxy.healthcheck(): 시작 프리플라이트 — 살아있는 포트 선점 + egress IP 로그(빠른 실패·가시성).
worker_main 기동 시 호출.
- 비용: DecodoConfig.cost_per_gb 추가. metrics 에 proxy_bytes(네이버 직접 제외) + 컴포넌트별
cost{ai_usd, proxy_usd, total_usd}. FE 원가 타일에 AI/DECODO 분해·프록시 바이트.
- 테스트: is_proxy_error 8종 + 비용 분해 1종.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
검색이 소모하는 리소스/비용/시간을 잡 단위로 집계해 result.metrics 로 적재(API/FE 노출).
지금까진 타임스탬프만 있고 실제 비용 동인(AI 토큰·대역폭)은 버려지고 있었다.
- services/metrics.SearchMetrics: duration_ms + ai(calls/tokens/est_cost_usd, gpt-4o-mini 단가)
+ crawl(fetches/html_bytes/malls_crawled) + source_ms
- AI 클라이언트: resp.usage 를 last_usage 로 노출(그동안 폐기하던 토큰)
- 어댑터: last_bytes(처리 HTML 바이트) 노출 — naver/coupang/browser_base 공통
- handler: 각 fetch 타이밍+바이트, AI 호출 토큰을 metrics 로 누적 → 결과에 스냅샷
- FE: 작업 카드에 원가 4타일(소요/AI비용/토큰/크롤 트래픽)
- 테스트 2종. ⚠️ html_bytes 는 대역폭 근사(오픈마켓 리소스 미차단분 제외=하한), CDP 정확화는 백로그
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>