Python 3.13과 FastAPI를 사용한 클린 아키텍처 보일러플레이트입니다.
이 프로젝트는 Uncle Bob의 클린 아키텍처 원칙을 따릅니다:
- 도메인 중심 설계: 비즈니스 로직이 프레임워크나 외부 의존성으로부터 독립적
- 의존성 역전 원칙: 내부 레이어는 외부 레이어에 의존하지 않음
- 테스트 용이성: 각 레이어를 독립적으로 테스트 가능
src/
├── domain/ # 도메인 레이어 (엔티티, 비즈니스 규칙)
├── application/ # 애플리케이션 레이어 (유스케이스, 비즈니스 로직)
├── interfaces/ # 인터페이스 레이어 (컨트롤러, 프레젠터)
├── infra/ # 인프라 레이어 (DB, 외부 서비스)
└── shared/ # 공통 모듈 (설정, 유틸리티, 예외)
- 비즈니스 엔티티와 규칙을 정의
- 프레임워크나 외부 라이브러리에 의존하지 않음
- 예: User 모델, UserStatus 열거형, 도메인 예외
- 유스케이스를 구현
- 도메인 모델을 조작하는 비즈니스 로직 포함
- 포트(인터페이스)를 통해 인프라와 통신
- 예: CreateUserUseCase, UserRepositoryPort
- HTTP 엔드포인트, 이벤트 핸들러 등 외부 인터페이스
- 요청을 받아 애플리케이션 레이어로 전달
- 예: FastAPI 라우터, HTTP 스키마
- 데이터베이스, 외부 API, 메시지 큐 등 구체적인 구현
- 애플리케이션 레이어의 포트를 구현
- 예: SQLAlchemy 리포지토리, Redis 클라이언트
- Repository Pattern: 데이터 접근 로직을 추상화
- Use Case Pattern: 각 비즈니스 기능을 독립적인 유스케이스로 구현
- Dependency Injection: 의존성을 외부에서 주입하여 결합도 감소
- Port & Adapter Pattern: 인터페이스를 통해 외부 시스템과 통신
- Python 3.13+
- MySQL 8.0+
- Redis 7.0+
- RabbitMQ 3.0+ (선택사항)
- 프로젝트 클론
git clone <repository-url>
cd boilerplate- 환경 변수 설정
cp .env.example .env
# .env 파일을 열어 필요한 값들을 설정- 가상환경 생성 및 의존성 설치
# uv 사용 (권장)
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -e .
# 또는 pip 사용
python -m venv .venv
source .venv/bin/activate
pip install -e .- 데이터베이스 마이그레이션
# 마이그레이션 초기화
alembic init migrations
# 마이그레이션 생성
alembic revision --autogenerate -m "Initial migration"
# 마이그레이션 실행
alembic upgrade head- 애플리케이션 실행
# 개발 서버 실행
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
# 또는 Docker Compose 사용
docker-compose up- 도메인 모델 생성
# src/domain/product/models.py
from pydantic import BaseModel, Field
class Product(BaseModel):
id: str | None = Field(default=None)
name: str = Field(..., min_length=1, max_length=100)
price: float = Field(..., gt=0)
stock: int = Field(..., ge=0)- 리포지토리 포트 정의
# src/application/product/ports.py
from abc import ABC, abstractmethod
from domain.product.models import Product
class ProductRepositoryPort(ABC):
@abstractmethod
async def save(self, product: Product) -> Product:
pass- 유스케이스 구현
# src/application/product/usecases/create_product.py
class CreateProductUseCase:
def __init__(self, product_repository: ProductRepositoryPort):
self.product_repository = product_repository
async def execute(self, command: CreateProductCommand) -> Product:
# 비즈니스 로직 구현
pass- HTTP 엔드포인트 추가
# src/interfaces/http/v1/product/routers.py
@router.post('/', response_model=ProductResponse)
async def create_product(
request: CreateProductRequest,
use_case: CreateProductUseCase = Depends(get_create_product_usecase),
) -> ProductResponse:
# 엔드포인트 구현
pass# src/tests/unit/application/test_create_user.py
import pytest
from unittest.mock import AsyncMock
from application.user.usecases.create_user import CreateUserUseCase
from application.user.commands import CreateUserCommand
@pytest.mark.asyncio
async def test_create_user_success():
# Given
mock_repository = AsyncMock()
use_case = CreateUserUseCase(mock_repository)
# When
command = CreateUserCommand(...)
result = await use_case.execute(command)
# Then
assert result.email == command.email애플리케이션 실행 후 다음 URL에서 API 문서를 확인할 수 있습니다:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
# 린팅
ruff check src/
# 포매팅
ruff format src/
# 타입 체크
mypy src/# 모든 테스트 실행
pytest
# 커버리지 포함
pytest --cov=src
# 특정 테스트만 실행
pytest src/tests/unit/boilerplate/
├── src/
│ ├── domain/ # 도메인 레이어
│ │ └── user/
│ │ ├── models.py # 도메인 모델
│ │ ├── enums.py # 열거형
│ │ └── exceptions.py # 도메인 예외
│ ├── application/ # 애플리케이션 레이어
│ │ └── user/
│ │ ├── ports.py # 리포지토리 인터페이스
│ │ ├── commands.py # 커맨드 객체
│ │ └── usecases/ # 유스케이스
│ ├── interfaces/ # 인터페이스 레이어
│ │ └── http/
│ │ └── v1/
│ │ └── user/
│ │ ├── routers.py # API 엔드포인트
│ │ ├── schemas.py # 요청/응답 스키마
│ │ └── depends.py # 의존성 주입
│ ├── infra/ # 인프라 레이어
│ │ ├── database/ # 데이터베이스 설정
│ │ └── redis/ # Redis 설정
│ └── shared/ # 공통 모듈
│ ├── config/ # 애플리케이션 설정
│ ├── exceptions/ # 공통 예외
│ └── utils/ # 유틸리티
├── migrations/ # Alembic 마이그레이션
├── tests/ # 테스트
├── docker-compose.yml # Docker Compose 설정
├── Dockerfile # Docker 이미지
├── pyproject.toml # 프로젝트 설정
└── README.md # 프로젝트 문서
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
이 프로젝트는 MIT 라이선스 하에 있습니다.