62 lines
3.4 KiB
Markdown
62 lines
3.4 KiB
Markdown
# Negodata Backend
|
||
|
||
DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 **JWT id/pw 로그인**만 예시 구현.
|
||
[negosium-backend](../../backend/README.md) 와 동일 구조이며, 실행·테스트·벤치마크 종합은 [레포 최상위 README](../../README.md) 참고.
|
||
|
||
## 디렉토리 구조
|
||
|
||
```
|
||
negodata/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 negodata/backend
|
||
pip install -r requirements.txt # 실행
|
||
python web_main.py # APP_ENV 기본 local
|
||
pip install pytest pytest-asyncio httpx # 테스트 도구
|
||
python -m pytest
|
||
```
|
||
- 서버: http://localhost:9400/docs
|
||
- 환경: `config.{local,test,docker}.toml` (`APP_ENV` 로 선택, docker 는 DB 호스트=`host.docker.internal`, database=`negodata_db`)
|