# Negosium Backend DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 **JWT id/pw 로그인**만 예시 구현. 실행·테스트·벤치마크 종합은 [레포 최상위 README](../README.md) 참고. ## 디렉토리 구조 ``` 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 는 세션을 직접 열지 않고 람다를 매니저에 넘긴다. 세션/트랜잭션은 매니저가 책임. ```python 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` 로 오프로드(이벤트 루프 비차단). → [벤치마크](../README.md#성능--벤치마크) ## 엔드포인트 | 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 토큰 필요) | ## 실행 / 테스트 ```bash # 레포 최상위에서 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`)