o2o-negosium-original/lps/docs/decision-openmarket-crawler.md
민헌 c81df5bd88 refactor(lps): 설정을 TOML 단일 소스로 통합 — env/.env 이중 관리 제거
설정이 .env(compose 주입)·config.toml·코드 곳곳의 os.environ 직독 3계층에
흩어져 관리가 어려웠다. TOML 하나로 통합한다(협의 결정).

- 신설 [WorkerConfig](동시성·폴백·프로필·데드라인·유예·Chrome·하트비트),
  [AlertConfig](웹훅·쿨다운·임계 10종). [WebServerConfig].api_keys(guard),
  [DecodoConfig].ip_request_budget/port_cooldown_sec 추가 — 흩어져 있던
  LPS_* env 20여 개를 섹션으로 흡수.
- server_configs 의 env override 계층(DB_*·시크릿·NAVER_KEYS 등) 삭제.
  남는 env 는 APP_ENV(부트스트랩)·PROCESS_COUNT/WORKER_CONCURRENCY(실행
  스크립트 대화형 입력 전용)·LPS_LIVE(테스트 옵트인)뿐.
- Docker: env 주입 → config.docker.toml 마운트 + APP_ENV=docker.
  이미지 무시크릿 유지, 마운트 누락 시 FileNotFoundError 즉시 실패.
  .env.example 삭제, config.docker.toml.example 신설.
- negodata 호출부: guard 키를 env 직독에서 [WebServerConfig].lps_api_key
  (+기존 관례대로 env override)로 이동.
- 실행 스크립트: 프로필·폴백·예산 프롬프트 제거(toml 소스 안내),
  동시성/프로세스 수만 임시 override 로 유지.
- docs 7종·example toml 의 env 표기를 toml 키로 일괄 갱신.
- 전체 145 passed + APP_ENV=docker 로딩·API 기동 스모크 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 21:11:31 +09:00

5.1 KiB
Raw Blame History

논의: 오픈마켓 크롤러를 계속 안고 갈까?

상태: 결정 완료(B. 게이트/OFF) · 작성 2026-07-09 · 결정 2026-07-10 · 대상: 개발팀 한 줄: G마켓·옥션·11번가 크롤러가 비용·복잡성의 ~80%인데, 실제 값어치(ROI)가 미증명이라 유지 여부를 정해야 함.


1. 배경

LPS는 상품별 최저가를 찾는다. 소스는 2계층:

  • 핵심: 네이버 쇼핑 API(무료·빠름·안정) + 쿠팡(브라우저 크롤)
  • 폴백: 네이버가 못 덮은 몰만 G마켓·옥션·11번가 크롤 → 몰별 가격

폴백 크롤러는 안티봇(쿠팡 Akamai, G마켓/옥션 Cloudflare Turnstile)을 뚫어야 해서 실제 브라우저 + residential 프록시(DECODO)가 필요하다.

2. 현재 데이터 (실측 2026-07)

항목
검색 1건 비용 ~$0.013 (1,000건 ~$13)
그 중 DECODO(프록시 대역폭) ~87% ← 대부분 오픈마켓 크롤
크롤 몰이 최종 최저가를 이긴 횟수 0 (네이버/쿠팡이 이김)
상품당 지연 ~35초 (크롤 때문)
gmarket 커버리지 IP 평판 의존, 플래키 (Turnstile)

가장 비싸고·느리고·불안정한 부분이 최종 답을 바꾼 적이 없다.

3. 크롤러가 주는 가치 (2가지)

  1. 더 싼 가격 발견 — 데이터상 거의 없음(네이버/쿠팡이 최저가)
  2. 몰별 검증·분석 — 네이버 보고가 vs 실제 크롤가 일치 확인, 몰별 투명성 → 진짜 가치는 여기. 단, 이 데이터를 실제로 소비하는 화면/의사결정이 있어야 의미가 있음.

4. 핵심 질문 (팀 논의)

  • by_mall(몰별 가격) 데이터를 지금 또는 로드맵에서 실제로 쓰는 화면/기능이 있는가?
    • 있다 → 유지 가치 있음 (아래 A)
    • 없다 / 막연히 쌓는 중 → 투기적. 소비자 생길 때 켜도 됨 (아래 B)
  • 몰별 검증이 필요하다면 얼마나 신선해야 하나? (실시간? 1시간? 하루?)
  • 비용 $13/1,000건 × 예상 검색량 = 월 얼마인가? 감당 범위인가?

5. 옵션

옵션 내용 비용/복잡성 언제
A. 유지 + TTL 캐시 같은 상품 몰별 가격을 창(예 1h)당 1회만 크롤·재사용 비용 대폭↓(재크롤 회피율만큼), 구현 소(小) by_mall 소비자가 있고, 분석 가치를 저렴히 유지하고 싶을 때 ← 추천
B. 게이트/OFF 크롤 기본 끔. 네이버 몰별분해(추가요청 0)만 사용. 필요 시 플래그로 켬 비용 ~87%↓, 복잡성↓ 아직 소비자가 없을 때
C. gmarket만 드롭 가장 플래키·비싼 gmarket 제거, 옥션·11번가 유지 부분 절감 gmarket 부담만 클 때
D. 현행 유지 매 검색 전 몰 크롤 비용·불안정 그대로 분석 가치가 풀 비용을 정당화할 때

왜 curl_cffi(브라우저 없이 쿠키 재사용)로 싸게 못 하나? 스파이크 결과 쿠팡(Akamai)은 되지만 G마켓/옥션(Cloudflare)은 cf_clearance가 브라우저 지문에 고정돼 실패. 즉 비싼 소스는 "크롤을 싸게"가 불가 → 남은 레버는 "크롤을 덜 하기"(TTL 캐시).

6. 참고: 안 바뀌는 것 (크롤러와 무관하게 견고)

큐(PG 원자적 claim·lease·dead-letter), 어댑터 패턴, AI 같은상품 매칭, 비용 계측(CDP 실측), 다중 병렬, 네이버+쿠팡 핵심 경로(싸고 빠르고 안정) — 여기는 유지. 이번 결정은 오픈마켓 크롤러 서브시스템에 한정된다.


결론 (2026-07-10 개발자 협의로 확정)

  • 결정: B. 게이트/OFF — 검색은 네이버+쿠팡만. 오픈마켓 폴백 3종은 코드·테스트 유지, 로직에서 제외(기본 비활성).
    • 근거: 크롤 몰의 최종 최저가 기여 0회 + 검색당 최대 15s(폴백 데드라인) + 비용의 ~87%(DECODO)가 이 경로.
  • 구현: 주석처리가 아닌 설정 토글[WorkerConfig].fallbacks(기본 []=OFF, 예: ["gmarket","auction","st11"], 일부만도 가능. 구현 당시 env LPS_FALLBACKS, 2026-07-13 toml 단일화로 이관).
    • worker_main.py 가 이 값으로만 폴백 어댑터를 생성. 핸들러는 빈 폴백을 원래 정상 처리(worker/handlers.py)라 로직 변경 없음.
    • 폴백 로직·파서 테스트는 fake 주입이라 비활성 상태에서도 계속 돈다(코드 부패 방지).
    • by_mall 은 네이버 노출 몰 + 쿠팡으로만 채워짐 → 소비처(프론트) 연동 시 공유할 것.
  • 재개 트리거: by_mall 소비 화면이 생기거나, 특정 몰이 네이버 커버리지에서 빠져 가격 검증이 필요해질 때.
    • 재가동 절차: ① 라이브 스모크로 셀렉터 드리프트 점검(LPS_LIVE=1 pytest tests/test_browser_base.py::test_live_smoke + 대상 몰 1회 검색) → ② [WorkerConfig].fallbacks 설정(로컬은 config.local.toml, 배포는 config.docker.toml) → ③ 웜업/차단 로그 확인. 미사용 기간 동안 셀렉터는 낡는다고 가정할 것.