o2o-negosium-original/backend
민헌 a2c299aa14 refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일
용어 체계: 값=anchoring_value(정수‰)·가격=anchoring_price·조정=adjustment·구간=price_range·표본=sample

- DB: rate_adjustments→anchoring.adjustments (id→adjustment_id, price_bracket_index→price_range_index,
  nego_count→sample_count, anchor_rate_before/after→anchoring_value_before/after,
  consumed_session_ids→used_session_ids)
- sessions: target_anchoring_price→anchoring_price, anchor_rate_permille→anchoring_value,
  last_offered_price→last_offer_price, anchoring_adjustment_id→used_by_adjustment_id
- 뷰: rate_history/current_rates→value_history/current_values, delta_permille→value_change
- 코드: calc_price_range_index·calc_anchoring_price·evaluate_samples·get_current_value·
  get_latest_adjusted_value·get_current_anchoring_value·fetch_current_values·get_base_anchoring_value·
  Adjustment(ORM)·update_last_offer_price, 상수 ANCHORING_VALUE_MIN/MAX·ADJUSTMENT_STEP·
  PRICE_RANGE_COUNT/INDEX_MAX, 배치 로그 키 bracket=→price_range=
- API: negodata protocol 필드 target_anchoring_price→anchoring_price (front 생성 모델·컴포넌트 동반)
- 기존 DB 마이그레이션 신설: schedules/anchoring/migrations/20260706_rename_anchoring.sql
  (멱등 DO 블록 — 테이블·컬럼·뷰·인덱스·PK 제약. 코드 배포와 동시 적용 필요)
- postgres-init 01·04, 문서 6종 동기화
- 실배포 전 수정 포함: main.py argparse 화(--dry-run 단독·오타 플래그 기동 전 차단),
  박제 정합식 calc_anchoring_price 재사용, clamped 지표가 실제 포화만 집계(경계값 유지 제외)

주의: sessions.anchoring_value(정수‰)와 quotation_settings.anchoring_value(구 float 비율)는
같은 이름·다른 단위 — 구 컬럼은 미변경.

검증: 모듈 20·negodata 50·backend 57 테스트 통과, front tsc·vite build 통과,
로컬 DB 마이그레이션 적용 후 배치 dry-run·상주 기동·양 서버 부팅 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:17:01 +09:00
..
common refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
config Merge branch 'feature/negodata' 2026-06-23 08:31:13 +09:00
crud refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
loadtest chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
router Merge branch 'main' into refactor/backend 2026-07-02 09:01:48 +09:00
scripts [chore] negodata: enum 주석 영문값 보강 + 견적상태 3종 정리 + 대시보드 정비 2026-06-30 17:25:38 +09:00
services refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
tests refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
.dockerignore chore(config): agent mock 모드 제거 및 .dockerignore 정리 2026-06-19 17:32:38 +09:00
conftest.py feat(backend): supplier_users 기반 인증 재구축 및 단일세션 토큰 저장 2026-06-18 11:16:33 +09:00
Dockerfile Agent 서버 구축: 멀티테넌트 협상 PoC (UCB Q-Table 학습 + /chat + 14 API + 학습검증 하네스), config 단일화(local.toml) + 빌드 경량화 2026-06-17 11:10:03 +09:00
pytest.ini 백엔드 프레임 설계 2026-06-15 15:53:39 +09:00
README.md requirement.dev.txt 삭제 . 2026-06-15 15:57:20 +09:00
requirements.txt feat(backend): 협상 채팅(chat) API + agent 위임 2026-06-18 14:24:57 +09:00
run_local_locust.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
run_local_pgwatch.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
run_local_server.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
web_main.py 백엔드 프레임 설계 2026-06-15 15:53:39 +09:00

Negosium Backend

DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 JWT id/pw 로그인만 예시 구현. 실행·테스트·벤치마크 종합은 레포 최상위 README 참고.

디렉토리 구조

backend/
├── web_main.py                  # 엔트리포인트 (uvicorn)
├── config/                      # 환경설정 (APP_ENV 별 toml 로드)
├── common/
│   ├── enums.py                 # ErrorType / DBType / DBWRType / EXCEPTION_*
│   ├── models/gmodel.py         # 프로토콜 베이스 (WebPacketProtocol 등)
│   └── database/
│       ├── db_session_manager.py# ★ DB Read/Write + 람다 실행 핵심
│       └── model/models.py      # ORM 모델 (tbl_account)
├── crud/user_crud.py            # DB 접근 (I*CRUD 인터페이스 + 구현)
├── services/auth_service.py     # 비즈니스 로직
└── router/
    ├── router.py                # FastAPI app
    └── v1/
        ├── auth/{account,protocol}.py   # 엔드포인트 / Req_·Res_
        └── validator/dependencies.py    # ★ JWT 발급·검증, 해시, RemoveNoneResponse

핵심 패턴

  • MVC: router(컨트롤러) → service(로직) → crud(쿼리). crud 는 인터페이스/구현 분리.
  • Depends 주입: service 가 IUserCRUD = Depends(UserCRUD), router 가 Depends(AuthService), 인증은 Depends(IsValidAccessToken).
  • DB Read/Write 분리: DBType × DBWRType 조합마다 별도 async 엔진(조회=Read, 변경=Write).
  • 람다 DB 실행: service 는 세션을 직접 열지 않고 람다를 매니저에 넘긴다. 세션/트랜잭션은 매니저가 책임.
    err, acc = await DB_SESSION_MNG.execute_lambda(           # 단일 조회
        tbl_account.DBType(), DBWRType.DB_READ.value, lambda s: crud.get_account_by_id(s, id))
    err = await DB_SESSION_MNG.execute_lambda_run(            # 여러 변경 = 1 트랜잭션
        [tbl_account.DBType()], [lambda s: crud.update_last_login(s, uid)])
    
  • 비동기: 전 계층 async/await, SQLAlchemy async + asyncpg, task 단위 scoped session.
  • Protocol 규약: 모든 패킷 WebPacketProtocol 상속, Req_*/Res_*(응답엔 result: ErrorInfo), 라우터별 protocol.py.
  • ResponseNone: 응답의 None 필드 재귀 제거(RemoveNoneResponse).
  • bcrypt 비차단: GetHashedPW/VerifyPW 를 asyncio.to_thread 로 오프로드(이벤트 루프 비차단). → 벤치마크

엔드포인트

Method Path 설명
POST /v1/auth/create 계정 생성 (pw bcrypt 해시)
POST /v1/auth/login 로그인, access/refresh 토큰 발급
POST /v1/auth/refresh_token access 토큰 재발급 (refresh 필요)
GET /v1/auth/me 내 정보 (access 토큰 필요)

실행 / 테스트

# 레포 최상위에서 docker compose up -d (backend만; DB 는 외부 PostgreSQL). 상세는 루트 README.
cd backend
pip install -r requirements.txt        # 실행
python web_main.py                      # APP_ENV 기본 local
pip install pytest pytest-asyncio httpx  # 테스트 도구
python -m pytest
  • 서버: http://localhost:9300/docs
  • 환경: config.{local,test,docker}.toml (APP_ENV 로 선택, docker 는 DB 호스트=host.docker.internal)