o2o-negosium-original/lps/config/config.local.toml.example
민헌 8fa77af866 [chore] lps: 배포 설정 문서화 + 죽은 env 제거 + 알림 문구 정정
배포서버 쿠팡 크롤 조사(2026-07-28)에서 드러난 '설정한 줄 알았는데 아니었던' 것들 정리.
크롤 동작 자체를 바꾸는 변경은 없다.

- Dockerfile.worker: ENV LPS_CHROME_EXECUTABLE 제거.
  읽는 코드가 없는데 값이 박혀 있어 "컨테이너 Chrome 경로가 설정돼 있다"는 오해를 만들었다.
  경로의 유일한 소스는 [WorkerConfig].chrome_executable 이다(설정 시 --no-sandbox 동반).

- config.local.toml.example: profile_dir 경고 추가.
  컨테이너에서 ".profiles" 로 두면 /app/.profiles(컨테이너 레이어)에 쌓여 재생성마다 쿠키가
  날아가고, compose 가 마운트한 lps-profiles 볼륨은 붙어만 있고 아무 일도 하지 않는다.
  로컬·배포서버 양쪽에서 실측(/profiles 는 7/9·7/16 잔재, /app/.profiles 에 9MB 최신).

- config.prod.toml.example 신규: 배포서버 설정 템플릿.
  로컬과 다른 값만 ★ 표시. 헤더에 로드 경로의 함정을 명시했다 —
  docker-compose.prod.yml 이 이 파일을 config.local.toml 자리에 마운트하므로
  APP_ENV=local 인데도 내용은 prod 설정이다(파일명만 보면 오해한다).

- worker_main.py: budget_leak 알림이 "ip_request_budget 하향 검토"를 단정하던 것을 수정.
  차단이 ip_req#1 에 몰리면 새 IP 첫 요청부터 막히는 것이라 예산과 무관하다.
  bot_detection.ip_request_no 분포를 보고 처방을 고르도록 문구를 바꿨다.

⚠️ Dockerfile.worker 가 바뀌었으므로 배포 시 lps-worker 재빌드 필요.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 16:39:14 +09:00

106 lines
5.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 복사해서 사용: cp config.local.toml.example config.local.toml
# 실제 config.local.toml 은 시크릿 포함이라 커밋하지 않는다(.gitignore: *.toml).
#
# ── 설정 소스는 TOML 하나다(2026-07-13 협의 — env/.env 이중 관리 제거) ──
# 호스트 실행: APP_ENV=local(기본) → 이 파일
# Docker : APP_ENV=dev|prod → config.dev.toml / config.prod.toml 을 컨테이너에 마운트
# (각 example 참고, 실행은 ../run_docker.sh 대화형 권장)
# env 는 APP_ENV·PROCESS_COUNT/WORKER_CONCURRENCY(실행 스크립트 대화형 입력)·LPS_LIVE(테스트)만 남는다.
[WebServerConfig]
server_name = "LpsServer"
port = 9600
process_count = 1
is_ssl = false
is_test = true
# CORS 허용 오리진(프론트). 비우면 [] (CORS 미적용). 5173=vite dev.
cors_origins = ["http://localhost:5173", "http://127.0.0.1:5173"]
# API guard 키 — 비우면 개방 모드(개발). prod 는 채운다(복수 등록 = 무중단 키 교체).
# 생성 예: openssl rand -hex 32. 호출자(negodata)도 같은 키를 설정해야 한다.
api_keys = []
[LogConfig]
print_console = true
log_level = "debug"
# DB Read/Write 분리. 관리형 DB(RDS/Aurora/Azure)는 host 에 엔드포인트, sslmode="require".
# LPS 도메인 로직/테이블이 생기기 전까지는 접속하지 않으므로(엔진 lazy) placeholder 여도 부팅된다.
[MainDBConfig]
db_type = "postgresql"
name = "lps_db"
write_host = "127.0.0.1"
write_port = 5432
write_id = "<DB_USER>"
write_pw = "<DB_PASSWORD>"
read_host = "127.0.0.1"
read_port = 5432
read_id = "<DB_USER>"
read_pw = "<DB_PASSWORD>"
show_log = false
pool_size = 10 # connection_budget>0 이면 무시(자동 산정). budget=0 일 때만 이 값 사용.
max_overflow = 20 # 〃
# 커넥션 예산(자동 산정). process_count 에 맞춰 pool_size/max_overflow 를 자동 계산:
# (pool+overflow) × 2엔진 × process_count ≤ connection_budget.
# 'lps API 가 쓸 총 커넥션 상한' — 공유 PG(max_connections)·동거 서비스(worker 등)를 고려한 값.
# 예) 전용 PG(max_connections=100)면 90 근처, 공유 PG면 40 권장. 0 이면 자동 끔(위 pool 값 사용).
connection_budget = 40
sslmode = "" # 로컬: "" / 관리형 DB: "require"|"verify-ca"|"verify-full"
# 워커 런타임 (worker_main.py). 동시성만 실행 시 WORKER_CONCURRENCY env 로 임시 override 가능.
[WorkerConfig]
concurrency = 1 # 상품 동시 검색 수(워커별 브라우저 세트, Chrome 최대 4×N). 로컬 권장 2~3
fallbacks = [] # 오픈마켓 폴백(기본 OFF). 예: ["gmarket", "auction", "st11"] — 켜기 전 라이브 스모크
# Chrome 프로필 베이스. 영속 경로면 재시작에도 쿠키 유지(재웜업 회피).
# ⚠️ 컨테이너로 띄우면 반드시 "/profiles" — compose 가 lps-profiles 볼륨을 그 경로에 마운트한다.
# ".profiles" 로 두면 /app/.profiles(컨테이너 레이어)에 쌓여 재생성 때마다 쿠키가 전부 날아가고,
# 볼륨은 붙어만 있고 아무 일도 하지 않는다(2026-07-28 로컬·배포서버 양쪽에서 실측).
# 호스트 직접 실행(run_local_worker.sh)일 때만 ".profiles" 를 쓴다.
profile_dir = ".profiles"
job_deadline_sec = 300 # 잡 1건 처리 상한(크롤 행 방어). 0=무제한(테스트용)
shutdown_grace_sec = 60 # graceful 종료 유예 — docker stop_grace_period 를 이보다 길게
chrome_channel = "chrome" # 로컬: 실제 Chrome
chrome_executable = "" # 컨테이너: "/opt/google/chrome/chrome" (설정 시 channel 무시)
heartbeat_file = "/tmp/lps_worker_heartbeat" # Docker HEALTHCHECK 가 신선도 확인
# 임계 알림 (AlertManager — 룰 의미는 docs/operations.md 표)
[AlertConfig]
webhook = "" # Slack 호환 웹훅 URL. 비우면 로그로만 알림
cooldown_min = 30 # 같은 룰 재발송 억제(분). 해소 알림은 즉시
dead_1h = 20 # 최근 1h DEAD 잡 수
blocks_1h = 80 # 최근 1h 봇 감지 수
queue_lag_sec = 300 # 가장 오래된 PENDING 대기 초
pool_pct = 90 # DB 커넥션 풀 포화율(%)
source_fail_30m = 5 # 소스별 30분 내 시도 N회 이상 & 성공 0건
deadline_1h = 5 # 최근 1h 잡 데드라인 강제종료 수
cost_1h_usd = 1.0 # 최근 1h 검색원가 합($)
ports_low_pct = 30 # 가용 프록시 포트 비율(%)
block_sessions_6h = 1 # 최근 6h '예산 회전에도 차단된' IP 세션 수
# ── 시크릿(API 키 등)도 이 파일에서 통합 관리 (미커밋). ──
# 네이버 쇼핑 오픈API (https://developers.naver.com/apps). 여러 개면 429/403 로테이션 자동 포함.
[NaverConfig]
[[NaverConfig.keys]]
id = "<NAVER_CLIENT_ID>"
secret = "<NAVER_CLIENT_SECRET>"
# 추가 키는 아래처럼 블록을 더 넣으면 됨:
# [[NaverConfig.keys]]
# id = "..."
# secret = "..."
# AI 유사도 판정/검색어 생성 (OpenAI)
[OpenAIConfig]
api_key = "<OPENAI_API_KEY>"
model = "gpt-4o-mini"
# DECODO residential 프록시 (쿠팡 전용, 포트기반 sticky). 값 다 채우면 활성(비면 프록시 미사용).
[DecodoConfig]
host = "" # 예: gate.decodo.com
username = "" # 대시보드 USERNAME (예: sppd6a3ze3)
password = "" # 대시보드 PASSWORD
port_start = 0 # 예: 10001
port_end = 0 # 예: 10010 — 포트를 늘리면(계약 변경) 이 범위만 넓히면 됨(코드 무변경)
session_minutes = 10 # 대시보드 Sticky 지속시간(분)과 일치
cost_per_gb = 0.0 # DECODO 요금($/GB) — 검색 원가의 대역폭 비용 산정용(플랜에 맞게, 예 3.0)
ip_request_budget = 3 # IP당 요청 예산 — 도달 시 차단 전 선제 회전(0=비활성). 튜닝은 docs/database.md
port_cooldown_sec = 0 # 차단 감지 포트 격리 초. 0=자동 max(sticky, 30분)