Skip to content

dan1901/Clean-Architecture-FastAPI-Boilerplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clean Architecture FastAPI Boilerplate

Python 3.13과 FastAPI를 사용한 클린 아키텍처 보일러플레이트입니다.

🏗️ 아키텍처 특징

1. 클린 아키텍처 (Clean Architecture)

이 프로젝트는 Uncle Bob의 클린 아키텍처 원칙을 따릅니다:

  • 도메인 중심 설계: 비즈니스 로직이 프레임워크나 외부 의존성으로부터 독립적
  • 의존성 역전 원칙: 내부 레이어는 외부 레이어에 의존하지 않음
  • 테스트 용이성: 각 레이어를 독립적으로 테스트 가능

2. 레이어 구조

src/
├── domain/          # 도메인 레이어 (엔티티, 비즈니스 규칙)
├── application/     # 애플리케이션 레이어 (유스케이스, 비즈니스 로직)
├── interfaces/      # 인터페이스 레이어 (컨트롤러, 프레젠터)
├── infra/          # 인프라 레이어 (DB, 외부 서비스)
└── shared/         # 공통 모듈 (설정, 유틸리티, 예외)

Domain Layer (도메인 레이어)

  • 비즈니스 엔티티와 규칙을 정의
  • 프레임워크나 외부 라이브러리에 의존하지 않음
  • 예: User 모델, UserStatus 열거형, 도메인 예외

Application Layer (애플리케이션 레이어)

  • 유스케이스를 구현
  • 도메인 모델을 조작하는 비즈니스 로직 포함
  • 포트(인터페이스)를 통해 인프라와 통신
  • 예: CreateUserUseCase, UserRepositoryPort

Interface Layer (인터페이스 레이어)

  • HTTP 엔드포인트, 이벤트 핸들러 등 외부 인터페이스
  • 요청을 받아 애플리케이션 레이어로 전달
  • 예: FastAPI 라우터, HTTP 스키마

Infrastructure Layer (인프라 레이어)

  • 데이터베이스, 외부 API, 메시지 큐 등 구체적인 구현
  • 애플리케이션 레이어의 포트를 구현
  • 예: SQLAlchemy 리포지토리, Redis 클라이언트

3. 주요 패턴

  • Repository Pattern: 데이터 접근 로직을 추상화
  • Use Case Pattern: 각 비즈니스 기능을 독립적인 유스케이스로 구현
  • Dependency Injection: 의존성을 외부에서 주입하여 결합도 감소
  • Port & Adapter Pattern: 인터페이스를 통해 외부 시스템과 통신

🚀 시작하기

필수 요구사항

  • Python 3.13+
  • MySQL 8.0+
  • Redis 7.0+
  • RabbitMQ 3.0+ (선택사항)

환경 설정

  1. 프로젝트 클론
git clone <repository-url>
cd boilerplate
  1. 환경 변수 설정
cp .env.example .env
# .env 파일을 열어 필요한 값들을 설정
  1. 가상환경 생성 및 의존성 설치
# 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 .
  1. 데이터베이스 마이그레이션
# 마이그레이션 초기화
alembic init migrations

# 마이그레이션 생성
alembic revision --autogenerate -m "Initial migration"

# 마이그레이션 실행
alembic upgrade head
  1. 애플리케이션 실행
# 개발 서버 실행
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000

# 또는 Docker Compose 사용
docker-compose up

📝 사용 방법

새로운 도메인 추가하기

  1. 도메인 모델 생성
# 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)
  1. 리포지토리 포트 정의
# 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
  1. 유스케이스 구현
# 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
  1. 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

API 문서

애플리케이션 실행 후 다음 URL에서 API 문서를 확인할 수 있습니다:

🛠️ 개발 도구

코드 품질 도구

# 린팅
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              # 프로젝트 문서

🤝 기여하기

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 라이선스

이 프로젝트는 MIT 라이선스 하에 있습니다.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published