# FastAPI 프로젝트 구조 원칙 **작성일**: 2025-09-17 **수정일**: 2025-10-02 (모범 사례 반영) ## 1. 계층 분리 원칙 ### 필수 계층 ``` 요청 계층 (router/) ↓ 비즈니스 계층 (services/, llm/, brain/) ↓ 데이터 계층 (state/, repositories/) ``` ### 계층별 책임 | 계층 | 역할 | 금지 사항 | |------|------|----------| | **router/** | HTTP 요청/응답 처리만 | DB 직접 접근, 비즈니스 로직 | | **services/** | 비즈니스 로직 구현 | DB 직접 연결 (state를 통해서만) | | **state/** | DB CRUD만 | 비즈니스 로직 포함 | ## 2. 폴더 구조 규칙 ### 표준 구조 ``` {service_name}/ ├── main.py # 앱 실행, 라우터 등록만 ├── app/ │ ├── router/ # HTTP 엔드포인트 │ │ └── v1/ # API 버전 관리 (선택) │ ├── services/ # 비즈니스 로직 │ ├── state/ # DB 접근 (Repository 패턴) │ ├── models/ # ORM 모델 (DB 테이블 정의) │ ├── schemas/ # Pydantic 모델 (API 요청/응답) │ ├── core/ # 설정, 공통 기능 │ ├── db/ # DB 세션 관리 (선택) │ └── utils/ # 유틸리티 └── tests/ ``` ### 폴더 명명 규칙 - `router/` 또는 `api/`: HTTP 처리 - `services/`: 비즈니스 로직 - `state/` 또는 `repositories/`: Repository 패턴으로 CRUD 캡슐화 - `models/`: SQLAlchemy 등 ORM 모델 - `schemas/`: Pydantic 요청/응답 스키마 (models와 분리) - `db/`: DB 엔진/세션 중앙 관리 (선택) - 복수형 사용 권장 ## 3. 파일 명명 규칙 ### router/ - `{기능}_handler.py`: 이벤트 처리 (slack_handler.py) - `{기능}_endpoint.py`: REST API (emotion_endpoint.py) ### services/ - `{도메인}_{기능}.py`: coldmail_filter.py, ir_analyzer.py - 한 파일 최대 300줄 ### state/ (Repository 패턴) - `database.py`: 통합 DB 접근 - `{도메인}_repository.py`: 도메인별 CRUD 캡슐화 ### models/ - `{도메인}_model.py`: ORM 모델 (예: user_model.py, emotion_model.py) ### schemas/ - `{도메인}_schema.py`: API 입출력 스키마 (예: user_schema.py, emotion_schema.py) ## 4. 의존성 방향 규칙 ### 단방향 흐름 ``` router → services → state/repositories ↓ ↓ ↓ schemas core models ↓ utils ``` ### 계층 간 데이터 흐름 - **router**: schemas로 요청/응답 검증 - **services**: schemas + models 사용 가능 - **state/repositories**: models만 사용 (DB 접근) ### 금지 사항 - ❌ 순환 참조: A imports B, B imports A - ❌ 하위가 상위 호출: state가 services 호출 - ❌ 계층 건너뛰기: router가 직접 state 호출 (긴급 상황 제외) ## 5. 코드 작성 원칙 ### LangGraph 워크플로우 - **복잡한 다단계 처리**: LangGraph 적극 활용 - **프로덕션 핵심 워크플로우**: PostgresSaver로 체크포인트 구현 (권장) - **실험/경량 플로우**: stateless LangGraph 허용 ### 계층별 원칙 - **router**: 서비스 호출만, DB/비즈니스 로직 금지 - **services**: 비즈니스 로직 구현, state를 통한 DB 접근 - **state**: DB CRUD만, 비즈니스 로직 금지 ## 6. DB 접근 규칙 ### 환경변수 사용 - `DATABASE_URL`: 메인 DB - `METRICS_DATABASE_URL`: 메트릭 전용 DB - `TEST_DATABASE_URL`: 테스트 DB ### 연결 방식 - **권장**: `db/database.py`에서 DB 세션 중앙 관리 (의존성 주입) - **간단한 경우**: `state/database.py`에서 직접 연결 ### 금지 사항 - ❌ 프로덕션 router/services에서 직접 asyncpg.connect() - ❌ 하드코딩된 DB URL - ❌ JSONB 저장 시 dict 직접 전달 (json.dumps() 필수) - ❌ 프로덕션 요청 경로에서 직접 DB 연결 재사용 ## 7. 파일 크기 제한 - **한 파일 최대 300줄 권장** - 초과 시 기능별 분리 ## 8. Import 규칙 ### 금지 - ❌ wildcard import (`from module import *`) - ❌ 상대 import로 순환 참조 가능성 (`from ..router import x`) ### 권장 - ✅ 명시적 import (`from app.state.database import save_emotion_reading`) - ✅ 모듈 import (`from app.services import coldmail_filter`) ## 9. 체크리스트 코드 작성 전: - [ ] 이 코드는 어느 계층인가? - [ ] DB 접근은 state를 통하는가? - [ ] 비즈니스 로직이 router에 있지 않은가? - [ ] 순환 import 가능성은 없는가? - [ ] 핵심 파일은 300줄 이하로 유지할 수 있는가? ## 10. 예외 상황 ### 허용되는 예외 1. **긴급 핫픽스**: 임시로 계층 건너뛰기 가능 (문서화 필수) 2. **레거시 코드**: 점진적 리팩토링 3. **성능 최적화**: 충분한 근거 필요 ### 예외 처리 시 - TODO 주석으로 계층 위반 표시 - 긴급 수정 사유 명시 ## 11. 로깅 원칙 **로그 레벨 사용 기준** (Python logging 공식 문서): - **DEBUG**: 개발/디버깅용 상세 정보 (중간 과정, 내부 상태) - **INFO**: 정상 동작 및 주요 이벤트 (시작/종료, 주요 단계) - **WARNING**: 잠재적 문제 (예상치 못한 상황, 성능 저하 가능성) - **ERROR**: 오류 발생 (기능 실패, 예외 처리) **규칙**: - 시작/종료는 반드시 INFO 레벨 - 중간 과정은 DEBUG 레벨 - 프로덕션에서는 INFO 기본, DEBUG는 필요 시에만 활성화 ## 12. 모범 사례 참고 본 문서는 FastAPI 커뮤니티의 다음 모범 사례를 반영하였습니다: 1. **models/schemas 분리**: DB 스키마와 API 스펙 독립 관리 2. **Repository 패턴**: state/repositories에서 CRUD 캡슐화 3. **DB 세션 중앙화**: db/database.py에서 의존성 주입 4. **API 버전 관리**: router/v1/, router/v2/ 구조 5. **관심사 분리**: 요청/비즈니스/데이터 계층 명확한 역할 분담