# LPS (Lowest Price Search) 인터넷 최저가를 찾는 솔루션. **프레임워크는 `backend` 와 동일**하게 구성한 골격이며, 구체적인 도메인 로직(크롤링/오픈API 연동/최저가 산정 등)은 아직 정해지지 않았다. ## 스택 / 아키텍처 (backend 미러링) - **FastAPI** 앱 (`router/router.py`) + `web_main.py` 부트스트랩 - **설정**: `config/` — TOML 로더(`config.local.toml`) + pydantic 모델, `APP_ENV`(기본 local) - **DB**: `common/database/db_session_manager.py` — 논리 DB × Read/Write 엔진, service→람다 위임 패턴 - 엔진은 lazy 생성이라 **DB 없이도 부팅/healthz 동작**한다. 테이블·crud 가 생기면 그때 실제 접속. - **공통 응답 규약**: `common/models/gmodel.py` — `Res_WebPacketProtocol.result`(성공/코드/설명) - **결과 코드**: `common/enums.py` — `ErrorType`, `DBType`, `DBWRType` - 계층 컨벤션: `router`(컨트롤러) → `services`(비즈니스) → `crud`(DB 접근) ## 폴더 구조 ``` lps/ ├── web_main.py # 진입점 ├── requirements.txt / Dockerfile / .dockerignore ├── run_local_server.sh # 로컬 실행(대화형), 포트 9600 ├── pytest.ini / conftest.py ├── config/ │ ├── config_loader.py / config_models.py / server_configs.py │ └── config.local.toml.example # cp 해서 config.local.toml 로 사용(시크릿, 미커밋) ├── common/ │ ├── enums.py / logger.py / singleton.py │ ├── utils/gtime.py │ ├── models/gmodel.py # 프로토콜 base │ └── database/{db_session_manager.py, model/models.py(MAIN_BASE)} ├── router/ │ ├── router.py # app + /healthz (도메인 라우터 미등록) │ └── v1/validator/dependencies.py# RemoveNoneResponse ├── services/ # (비어있음) 도메인 서비스 추가 위치 ├── crud/ # (비어있음) DB 접근 계층 추가 위치 └── tests/test_health.py # 스모크 테스트 ``` ## 로컬 실행 ```bash cp config/config.local.toml.example config/config.local.toml # 설정+시크릿 전부(포트/DB/API 키) ./run_local_server.sh # → http://localhost:9600/docs ``` > `config.local.toml` 한 파일에 설정과 시크릿(API 키)을 통합 관리(git 미추적). > 배포는 이 파일을 마운트하거나, 환경별로 바뀌는 값만 env override(DB_HOST 등). > 워커는 별도 프로세스: `python worker_main.py` ## 테스트 ```bash python -m pytest # tests/ (기본 healthz 스모크) ``` ## 포트 - backend 9300 / negodata 9400 / agent 9500 과 겹치지 않도록 **LPS 는 9600** 사용. ## 새 도메인 추가 순서 (backend 컨벤션) 1. `common/database/model/models.py` 에 테이블 정의(+ `DBType`) 2. `crud/_crud.py` (ABC 인터페이스 + 구현) 3. `services/_service.py` (비즈니스 로직) 4. `router/v1//{protocol.py, .py}` 작성 후 `router/router.py` 에서 `include_router`