chore(lps): 시크릿용 .env 도입 — API 키(NAVER/OpenAI/Azure) 주입 경로

키는 코드/커밋이 아닌 환경변수로 주입한다(감사: 시크릿 하드코딩 금지).
config.local.toml=비-시크릿 설정, .env=시크릿으로 분리.

- .env.example(템플릿, 커밋) + .env(로컬, 미추적)로 키 슬롯 제공
  · NAVER_CLIENT_ID/SECRET(+로테이션 _2..), OPENAI_API_KEY, AZURE_OPENAI_*
- server_configs 가 기동 시 lps/.env 를 load_dotenv 로 환경변수 주입
- requirements: python-dotenv 추가
- README: .env 셋업 단계 안내

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
민헌 2026-07-08 17:14:34 +09:00
parent fb72ab625f
commit c4b8692f3a
4 changed files with 33 additions and 1 deletions

22
lps/.env.example Normal file
View File

@ -0,0 +1,22 @@
# LPS 환경변수 (시크릿). 복사해서 .env 로 만들고 값을 채우세요:
# cp .env.example .env
# .env 는 커밋되지 않습니다(.gitignore). 값은 큰따옴표 안에 넣으세요.
# 앱/워커 기동 시 config/server_configs 가 이 파일을 환경변수로 로드합니다.
# ── 네이버 쇼핑 검색 오픈 API ─────────────────────────────────────────
# https://developers.naver.com/apps → 애플리케이션 등록 → 사용 API '검색'
NAVER_CLIENT_ID=""
NAVER_CLIENT_SECRET=""
# 로테이션(선택): 429/403 쿼터 회피용 추가 키는 _2, _3 ... 로 늘리면 자동 포함
# NAVER_CLIENT_ID_2=""
# NAVER_CLIENT_SECRET_2=""
# ── AI (상품 유사도 판정 / 검색어 생성) ───────────────────────────────
# 사용하는 쪽만 채우면 됩니다. (A) OpenAI 또는 (B) Azure OpenAI(레퍼런스 방식)
# (A) OpenAI
OPENAI_API_KEY=""
# (B) Azure OpenAI
AZURE_OPENAI_API_KEY=""
AZURE_OPENAI_ENDPOINT=""
AZURE_OPENAI_DEPLOYMENT=""
AZURE_OPENAI_API_VERSION="2024-08-01-preview"

View File

@ -37,9 +37,12 @@ lps/
## 로컬 실행 ## 로컬 실행
```bash ```bash
cp config/config.local.toml.example config/config.local.toml # 값 채우기 cp config/config.local.toml.example config/config.local.toml # DB 등 비-시크릿 설정
cp .env.example .env # 시크릿(API 키) — NAVER/OPENAI 등
./run_local_server.sh # → http://localhost:9600/docs ./run_local_server.sh # → http://localhost:9600/docs
``` ```
> `config.local.toml` = 비밀 아닌 설정(포트/DB), `.env` = 시크릿(API 키). 둘 다 git 미추적.
> 워커는 별도 프로세스: `python worker_main.py`
## 테스트 ## 테스트
```bash ```bash

View File

@ -1,8 +1,14 @@
import os import os
from dotenv import load_dotenv
from config.config_loader import Configs from config.config_loader import Configs
from config.config_models import WebServerConfig, LogConfig, MainDBConfig from config.config_models import WebServerConfig, LogConfig, MainDBConfig
# 시크릿(.env: API 키 등)을 환경변수로 로드. lps 루트의 .env 를 읽는다(없으면 조용히 무시).
# TOML(비밀 아님) 과 env(시크릿) 를 분리 — 키는 코드/커밋에 넣지 않는다.
load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))
# 실행 환경 결정 (기본 local). 환경변수 APP_ENV 로 변경. # 실행 환경 결정 (기본 local). 환경변수 APP_ENV 로 변경.
APP_ENV = os.environ.get("APP_ENV", "local") APP_ENV = os.environ.get("APP_ENV", "local")

View File

@ -5,6 +5,7 @@ greenlet # SQLAlchemy async 의 sync/async 브리지에 필수 (일부 환경
asyncpg asyncpg
orjson orjson
pydantic>=2.0 pydantic>=2.0
python-dotenv # .env(시크릿: API 키) 로드 — server_configs 에서 환경변수로 주입
httpx # 외부 사이트/오픈API(최저가 조회) 호출용 async HTTP 클라이언트 httpx # 외부 사이트/오픈API(최저가 조회) 호출용 async HTTP 클라이언트
# --- 크롤링(LPS) — 안티봇 대응은 어댑터 안에 격리. 트레드밀 대비 버전 pin. --- # --- 크롤링(LPS) — 안티봇 대응은 어댑터 안에 격리. 트레드밀 대비 버전 pin. ---