o2o-negosium-original/lps
민헌 993301be8b docs(lps): README·docs 최신화 — IP 선제 회전·알림 10룰·guard·ip_session 반영
이번 기능 3종+알림 확장 이후 문서와 코드의 어긋남을 정리한다.

- README: 주요 기능 표에 선제 회전(예산 3회)·임계 알림·API guard 추가,
  차단 대응 설명을 '막히기 전 교체' 순서로 재서술, 폴더 구조에
  alerts/ip_session 반영, 데이터베이스 문서 링크를 5종으로 수정.
- api.md: /v1/lps/ops 운영 스냅샷 섹션 신설(필드 주석 포함),
  /readyz 문서화, HTTP 401(guard) 상태 코드 추가.
- architecture.md: 구성요소 표에 관측·알림/API guard 행 추가.
- database.md: 제목 '테이블 5종'으로 수정.
- operations.md: 테스트 수 96→145, 로그 읽는 법에 예산 선제 회전·
  포트 쿨다운 로그 2행 추가.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 20:46:59 +09:00
..
common feat(lps): 알림 확장 — AlertManager 쿨다운·회복, DB풀 포화·소스별 장기실패 룰 2026-07-13 16:42:12 +09:00
config fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용 2026-07-10 11:53:47 +09:00
crud feat(lps): 알림 룰 4종 추가 — 데드라인·검색원가·포트 고갈·예산 누수 2026-07-13 17:29:08 +09:00
docs docs(lps): README·docs 최신화 — IP 선제 회전·알림 10룰·guard·ip_session 반영 2026-07-13 20:46:59 +09:00
loadtest test(lps): 부하테스트 상품셋 100종 카탈로그 분리 — 실제 입력 분포 재현 2026-07-10 10:50:28 +09:00
migrations feat(lps): IP 선제 로테이션 — 요청 예산·포트 쿨다운·ip_session 관측 2026-07-13 16:35:44 +09:00
router feat(lps): API guard — LPS_API_KEY 설정 시에만 /v1 에 X-API-Key 검증 2026-07-13 16:45:31 +09:00
services feat(lps): 알림 확장 — AlertManager 쿨다운·회복, DB풀 포화·소스별 장기실패 룰 2026-07-13 16:42:12 +09:00
tests feat(lps): 알림 룰 4종 추가 — 데드라인·검색원가·포트 고갈·예산 누수 2026-07-13 17:29:08 +09:00
worker fix(lps): 워커 행(hang) 3중 방어 — 잡 데드라인·웜업 타임아웃·정리 루프 격리 2026-07-10 11:27:03 +09:00
.dockerignore fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용 2026-07-10 11:53:47 +09:00
.gitignore feat(lps): 로컬 워커·부하테스트(GUI) 실행 스크립트 추가 (대화형) 2026-07-10 08:33:11 +09:00
conftest.py feat(lps): 인터넷 최저가 검색 솔루션 프레임워크 골격 추가 2026-07-08 15:18:27 +09:00
Dockerfile fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용 2026-07-10 11:53:47 +09:00
Dockerfile.worker fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용 2026-07-10 11:53:47 +09:00
loadtest.py test(lps): 부하테스트 상품셋 100종 카탈로그 분리 — 실제 입력 분포 재현 2026-07-10 10:50:28 +09:00
pytest.ini feat(lps): 인터넷 최저가 검색 솔루션 프레임워크 골격 추가 2026-07-08 15:18:27 +09:00
README.md docs(lps): README·docs 최신화 — IP 선제 회전·알림 10룰·guard·ip_session 반영 2026-07-13 20:46:59 +09:00
requirements-api.txt fix(lps): Docker 이미지 무시크릿화 + 배포 견고화 — 리뷰 발견사항 일괄 적용 2026-07-10 11:53:47 +09:00
requirements.txt feat(lps): 실시간 관측 대시보드 추가 — 큐 추이·코어별 CPU·프로세스 그룹 사용률 2026-07-10 09:50:14 +09:00
run_loadtest_gui.sh feat(lps): 로컬 워커·부하테스트(GUI) 실행 스크립트 추가 (대화형) 2026-07-10 08:33:11 +09:00
run_local_server.sh feat(lps): 서버 실행 스크립트에 멀티코어 대화형 선택 추가 2026-07-10 09:09:55 +09:00
run_local_worker.sh feat(lps): 오픈마켓 폴백 기본 비활성(LPS_FALLBACKS 토글) — 협의 결정 B안 적용 2026-07-10 10:14:39 +09:00
run_monitor.sh feat(lps): 실시간 관측 대시보드 추가 — 큐 추이·코어별 CPU·프로세스 그룹 사용률 2026-07-10 09:50:14 +09:00
web_main.py feat(lps): process_count 기반 커넥션 풀 자동 산정 — 멀티코어 풀 오버서브스크립션 방지 2026-07-09 23:59:05 +09:00
worker_main.py feat(lps): 알림 룰 4종 추가 — 데드라인·검색원가·포트 고갈·예산 누수 2026-07-13 17:29:08 +09:00

LPS — 인터넷 최저가 검색 솔루션

상품 정보를 넣으면 네이버·쿠팡을 뒤져 "같은 상품"의 최저가를 찾아 돌려주고, 그 가격을 시간에 따라 기록해 그래프로 볼 수 있는 시스템입니다.


🧭 이게 뭔가요? (비개발자용 3줄 요약)

  1. "맥심 커피 (1박스, 160개입)" 같은 상품 정보를 보내면,
  2. 시스템이 네이버·쿠팡을 실제로 검색하고, AI가 "진짜 같은 상품"만 골라 최저가를 알려줍니다. (빨대·커버 같은 엉뚱한 액세서리는 걸러냅니다)
  3. 같은 상품을 여러 번 조회하면 가격 변화가 쌓여서, 네이버/쿠팡/최종 최저가를 그래프로 볼 수 있습니다.

왜 유용한가? 사람이 일일이 검색·비교하지 않아도, 필요한 상품만(조회할 때만) 자동으로 최저가를 찾고 가격 추이를 남깁니다.


⚙️ 어떻게 동작하나요? (워크플로우)

 [1] 검색 요청           [2] 대기줄(큐)         [3] 일꾼(워커)가 처리
  상품 정보 전송   ─────▶  순서대로 쌓임   ─────▶  네이버 + 쿠팡 동시 검색
 (POST /search)          (즉시 접수번호 반환)         │
                                                     ▼
                                        [4] 걸러내기 + AI 판정
                                        가격 이상치 제거 → "같은 상품"만 선별
                                                     │
                                                     ▼
                                        [4-1] 오픈마켓 폴백 (옵션 · 기본 꺼짐)
                                        네이버가 못 덮은 몰(G마켓·옥션·11번가)만 크롤
                                                     │
                                                     ▼
                                        [5] 최저가 확정 + 기록
                                        네이버/쿠팡/최종 + 몰별 최저가 저장 → 이력 적재
                                                     │
                                                     ▼
                                        [6] 완료(결과 + 검색 원가 조회 가능)

핵심 포인트

  • 즉시 응답 + 나중 처리: 요청하면 바로 "접수번호(job_id)"를 주고, 실제 검색은 뒤에서 진행됩니다. (검색은 몇 초~수십 초 걸림)
  • 못 찾으면 검색어를 바꿔 재시도: "맥심 커피"로 안 나오면 "맥심 모카골드 커피믹스"처럼 AI가 검색어를 다듬어 다시 시도하고, 그래도 없으면 "없음"으로 정리합니다. (무한 재시도 안 함)
  • 차단 대응: IP당 요청 예산(기본 3회)에 닿으면 차단당하기 전에 IP를 선제 교체하고(평판 보존 — 그 IP는 로테이션 복귀 시 재사용), 그래도 감지되면 그 포트를 쿨다운 격리 후 다른 IP로 재시도합니다. 시작 시 챌린지를 미리 풀어(웜업) 실 작업을 빠르게 합니다.
  • 원가 투명: 검색 1건이 쓴 AI 비용·프록시 대역폭·시간을 함께 기록합니다.

주요 기능

기능 설명
멀티 소스 검색 네이버 쇼핑 API + 쿠팡(Akamai 우회) 동시 검색·병합
오픈마켓 폴백 크롤 네이버가 못 덮은 몰만 G마켓·옥션(Cloudflare Turnstile 우회)·11번가 크롤 → 몰별 가격. 기본 비활성(LPS_FALLBACKS, 배경)
AI 같은 상품 판정 "진짜 그 상품"만 선별 (액세서리·다른 규격 제외)
검색어 자동 정제 0건이면 정밀/광역 검색어로 재시도
최저가 이력 그래프 조회 시점마다 네이버/쿠팡/최종 + 몰별(by_mall) 최저가를 시계열로 기록
검색 원가 계측 검색 1건의 AI 토큰·비용 + DECODO 대역폭(실측 CDP) + 시간을 집계
다중 상품 병렬 워커별 브라우저 세트로 여러 상품 동시 검색(WORKER_CONCURRENCY)
안정적 큐 처리 작업 유실 없이 순서대로, 실패 시 자동 재시도
프록시 IP 선제 회전 요청 예산(기본 3회) 도달 시 차단 전 선제 교체 + 불탄 포트 쿨다운 + 봇 감지·전송오류 즉시 순환 + 시작 웜업(DECODO). 예산 튜닝용 ip_session 관측 로그
임계 알림 큐·차단·DB풀·소스별 장기실패·비용 등 10룰 — 쿨다운(스팸 방지)·해소 알림, Slack 웹훅(룰 표)
API guard LPS_API_KEY 설정 시 /v1 전체 X-API-Key 검증(개발은 미설정=개방 모드)

🚀 빠른 시작

cd lps

# 1) 설정 파일 준비 (DB·API 키 등)
cp config/config.local.toml.example config/config.local.toml   # 값 채우기

# 2) API 서버 실행 (요청 접수)
./run_local_server.sh              # → http://localhost:9600/docs

# 3) 워커 실행 (실제 검색 수행) — 별도 터미널
./run_local_worker.sh              # 대화형: 동시성·프로필 선택 (또는 python worker_main.py)

# (선택) 부하 테스트 GUI — Locust 웹 UI(:8089)
./run_loadtest_gui.sh              # 브라우저에서 users/spawn 조절하며 RPS/지연 관측

간단 테스트:

curl -X POST localhost:9600/v1/lps/search -H 'Content-Type: application/json' \
  -d '{"data":[{"product_code":"T1","product_name":"맥심 커피","specification":"1박스, 160개입"}]}'

자세한 실행/설정은 운영 가이드 참고.


📚 문서

문서 대상 내용
아키텍처 개발자/기획자 구성요소·파이프라인·안티봇(Akamai/Turnstile)·비용계측·동시성
데이터베이스 개발자/기획자 테이블 5종 구조와 코드값(+by_mall·ip_session)
API 사용법 연동 개발자 엔드포인트·요청/응답·metrics 예시
운영 가이드 운영자/개발자 실행·병렬·관측(readyz/ops/알림)·Docker 배포·문제 해결
크롤러 논의 오픈마켓 크롤러 유지 여부(ROI) 의사결정 메모

📁 폴더 구조

lps/
├── web_main.py            # API 서버 진입점 (요청 접수)
├── worker_main.py         # 워커 진입점 (검색+웜업+유휴정리+ops모니터)
├── Dockerfile             # API 이미지(lean) · Dockerfile.worker  # 워커(Chromium+Xvfb)
├── run_local_server.sh    # 로컬 API 실행 (대화형)
├── run_local_worker.sh    # 로컬 워커 실행 (대화형: 동시성·프로필)
├── run_loadtest_gui.sh    # 부하 테스트 Locust 웹 UI(:8089) 실행 (대화형)
├── config/                # 설정(config.local.toml — 포트/DB/API키, 미커밋; 배포는 env 주입)
├── common/                # 공통(enums, DB 세션, 모델, 로거, alerts=임계 알림 관리자)
│   └── database/model/models.py   # DB 테이블 정의
├── loadtest.py            # 부하 테스트 (N개 상품 → 처리량·지연·비용 집계)
├── crud/                  # DB 접근 (job_crud, price_history, negative_cache, bot_detection, ip_session)
├── services/
│   ├── search/            # 소스 어댑터 (coupang, naver, esm=G마켓·옥션, st11=11번가)
│   │   ├── browser_base.py    # patchright 공통(수명·프록시회전·차단감지·CDP 바이트계측)
│   │   ├── proxy.py           # DECODO(IP 회전·포트 쿨다운·프리플라이트)
│   │   └── card_parser.py     # 오픈마켓 공용 카드 파서
│   ├── pipeline/          # 필터·이상치·최저가 정렬(+몰별 분해)
│   ├── ai/                # AI 유사도 판정·검색어 생성 (OpenAI)
│   └── metrics.py         # 검색 원가 계측(AI/DECODO 비용·시간)
├── worker/                # 워커 루프·핸들러(폴백·데드라인)·알림(NOTIFY)
├── router/v1/lps/         # API 라우터
└── tests/                 # 테스트

포트

backend 9300 / negodata 9400 / agent 9500 과 겹치지 않게 LPS는 9600.