비개발자/기획자/개발자 누구나 이해하도록 일목요연하게 정리. 길이 분산 위해 분할. - README.md: 3줄 요약 + 워크플로우 다이어그램 + 주요기능 + 빠른시작 + 문서 목차 - docs/architecture.md: 구성요소·처리 파이프라인·재시도/프록시/봇감지/이력 원리 - docs/database.md: 테이블 4종(job/price_history/search_negative/bot_detection) + 코드값 - docs/api.md: 엔드포인트 요청/응답 예시(curl/Postman), 상태·코드 요약 - docs/operations.md: 실행·로그·DB조회·테스트·문제해결·배포유의 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
110 lines
4.4 KiB
Markdown
110 lines
4.4 KiB
Markdown
# 운영 가이드 — 실행 · 로그 · DB · 문제 해결
|
|
|
|
[← README로](../README.md)
|
|
|
|
## 1. 사전 준비
|
|
|
|
**필요한 것**: Python 3.12+ (로컬은 3.14), PostgreSQL, Google Chrome(쿠팡 크롤링용)
|
|
|
|
**설정 파일** (`config/config.local.toml`, git 미커밋)
|
|
```bash
|
|
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` 생성 후 최초 실행 시 테이블 자동 생성.
|
|
```bash
|
|
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 서버** (요청 접수)
|
|
```bash
|
|
./run_local_server.sh # → http://localhost:9600/docs
|
|
```
|
|
|
|
**워커** (실제 검색 수행) — 별도 터미널
|
|
```bash
|
|
python worker_main.py
|
|
# 로그를 실시간으로 보려면:
|
|
PYTHONUNBUFFERED=1 python worker_main.py
|
|
```
|
|
> 워커 실행 시 쿠팡 크롤링용 **Chrome 창이 뜹니다**(정상). 기동 로그에 `DECODO 프록시: ON/OFF`, `AI: ON/OFF`가 표시됩니다.
|
|
|
|
## 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 조회 (유용한 쿼리)
|
|
|
|
```bash
|
|
psql -h 127.0.0.1 -U postgres -d lps_db
|
|
```
|
|
```sql
|
|
-- 큐 상태 요약 (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. 테스트
|
|
|
|
```bash
|
|
python -m pytest
|
|
```
|
|
> ⚠️ **워커가 실행 중이면 테스트가 깨집니다** — 워커가 같은 `lps_db`의 테스트 작업을 가로채기 때문. 테스트 전 워커를 멈추세요:
|
|
> ```bash
|
|
> 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)은 이미지에 굽지 말고 **마운트** 권장
|