o2o-negosium-original/lps/docs/operations.md
민헌 ba67275cd8 docs(lps): 운영 가이드 — WORKER_CONCURRENCY 병렬 실행 + loadtest.py 안내
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 16:28:51 +09:00

5.0 KiB
Raw Blame History

운영 가이드 — 실행 · 로그 · DB · 문제 해결

← README로

1. 사전 준비

필요한 것: Python 3.12+ (로컬은 3.14), PostgreSQL, Google Chrome(쿠팡 크롤링용)

설정 파일 (config/config.local.toml, git 미커밋)

cp config/config.local.toml.example config/config.local.toml

채워야 할 값:

섹션 값
[MainDBConfig] DB 접속(host/port/id/pw, name=lps_db)
[NaverConfig].keys 네이버 쇼핑 API 키(id/secret). 여러 개면 자동 로테이션
[OpenAIConfig] api_key (AI 판정·검색어 생성용)
[DecodoConfig] 프록시 정보(비워두면 프록시 미사용)

한 파일에 설정+시크릿 통합 관리. 배포 시엔 이 파일을 마운트하거나, 환경별로 바뀌는 값(DB_HOST 등)만 환경변수로 덮어씁니다.

DB 준비: lps_db 생성 후 최초 실행 시 테이블 자동 생성.

createdb -h 127.0.0.1 -U postgres lps_db
psql -h 127.0.0.1 -U postgres -d lps_db -c "CREATE EXTENSION IF NOT EXISTS pgcrypto;"

2. 실행

API 서버 (요청 접수)

./run_local_server.sh            # → http://localhost:9600/docs

워커 (실제 검색 수행) — 별도 터미널

python worker_main.py
# 로그를 실시간으로 보려면:
PYTHONUNBUFFERED=1 python worker_main.py
# 상품 여러 개를 동시에 검색(워커별 브라우저 세트 · 다른 IP):
WORKER_CONCURRENCY=3 python worker_main.py   # 권장 2~3(로컬). Chrome 최대 4×N개

워커 실행 시 쿠팡 크롤링용 Chrome 창이 뜹니다(정상). 기동 로그에 DECODO 프리플라이트 OK — egress IP ..., AI: ON/OFF가 표시됩니다. 동시성 N이면 상품 N개가 진짜 병렬 처리됩니다(각 워커가 자기 프로필·프록시 IP 사용).

부하 테스트 (여러 상품 동시 검색 측정)

N=8 python loadtest.py    # 상품 8개 제출→처리량·지연(p50/p95)·AI/DECODO/총비용 집계

워커 동시성만큼 병렬 처리됩니다(동시성 낮으면 큐에서 순차 대기 — 그게 부하 관측 포인트).

3. 로그 보는 법 (워커 터미널)

로그 의미
[naver] query='...' → N건 네이버 검색 결과 수
[coupang] query='...' → N건 (ip_req#K) 쿠팡 결과 수 / 이 IP로 K번째 요청
[ai] 판정 N건 중 매칭 M건 AI 같은상품 선별 결과
[ai] 검색어 생성 precise=... broad=... 0건이라 검색어 재생성
[coupang][BOT-DETECTED] ... 쿠팡 봇 감지 → IP 회전
[worker-0] done <id> / fail ... → DEAD 작업 완료 / 실패
[reaper] reclaimed N 죽은 워커 작업 회수

디버그 로그가 안 보이면 config.local.toml의 [LogConfig] log_level = "debug" 확인.

4. DB 조회 (유용한 쿼리)

psql -h 127.0.0.1 -U postgres -d lps_db
-- 큐 상태 요약 (1=대기 2=처리중 3=완료 4=실패)
SELECT status, count(*) FROM job GROUP BY status;

-- 최근 작업 결과
SELECT job_id, status, result->>'outcome' AS outcome,
       result->'lowest'->>'price' AS lowest, result->'sources' AS sources
FROM job ORDER BY created_at DESC LIMIT 5;

-- 특정 상품의 최저가 이력(그래프 원본)
SELECT triggered_at, naver_lowest, coupang_lowest, final_lowest, final_source, outcome
FROM price_history WHERE product_code='T1' ORDER BY triggered_at;

-- 봇 감지 패턴 (IP당 평균 몇 요청 만에 감지?)
SELECT avg(ip_request_no), count(*) FROM bot_detection;

-- 네거티브 캐시(없음으로 기록된 상품)
SELECT key, until, reason FROM search_negative ORDER BY created_at DESC;

5. 테스트

python -m pytest

⚠️ 워커가 실행 중이면 테스트가 깨집니다 — 워커가 같은 lps_db의 테스트 작업을 가로채기 때문. 테스트 전 워커를 멈추세요:

pkill -f worker_main.py

6. 문제 해결

증상 원인 / 해결
포트 9600 사용 중 lsof -ti:9600 | xargs kill 후 재실행
백그라운드 실행 시 로그 안 보임 print 버퍼링 → PYTHONUNBUFFERED=1 붙여 실행
ProcessSingleton ... profile is already in use Chrome 프로필 중복 — 워커를 하나만 실행(또는 워커별 프로필 분리 필요)
쿠팡 결과 0건 + blocked=True 봇 차단 → 프록시(DECODO) 설정 확인. 감지 이력은 bot_detection 참고
AI 매칭이 0건 자주 발생 검색어가 모호하거나 스펙이 실제와 다름 → product_name/specification을 더 정확히
result.desc = LPS_JOB_NOT_FOUND 존재하지 않거나 잘못된 job_id

7. 배포 시 유의 (예정)

  • Chrome을 headless로(서버엔 화면 없음) — 튜닝 필요
  • Docker 이미지에 chromium 설치 필요
  • 프록시(residential) 사실상 필수 — 클라우드 IP는 쉽게 차단됨
  • 워커 여러 개 띄우면 워커별 Chrome 프로필 분리 필요
  • 시크릿(config.local.toml)은 이미지에 굽지 말고 마운트 권장