<aside>
💡
Notation
- 이탤릭은 더 큰 수준의 프로젝트에서 삭제되는 지침이다.
- 볼드는 이전 수준에는 없다가 새로 추가되는 지침이다.
</aside>
토이 프로젝트
- 이 프로젝트는 도메인 주도 설계의 목적과 용어를 차용한 클린 아키텍처를 적용한다.
스캐폴드 및 가이드
- root
- .git/
- myproject
- domain/
- xxx_entity (예를 들어: user_entity)
- xxx_vo (예를 들어: user_vo)
- xxx_irepo (예를 들어: user_irepo) - xxx_repo 에서 구현될 인터페이스, 반환 타입은 도메인 객체
- xxx_igateway (예를 들어: user_igateway) - xxx_gateway 에서 구현될 인터페이스, 반환 타입은 도메인 객체
- xxx_exception (예를 들어: user_exception)
- application/
- xxx_service (예를 들어: user_service, … )
- interface/
- xxx_controller (예를 들어: user_controller, … ) - Router & Response Model
- infra/
- db_models - ORM 프레임워크로 작성한 DB 모델
- xxx_repo (예를 들어: user_repo, … )
- xxx_gateway (예를 들어: user_gateway, … )
- utils/
- settings.py
- main.py
- README.md
- pyproject.toml
- …
- 루트 디렉토리에서
python3 -m myproject.main
으로 백엔드 애플리케이션을 실행하는 flat 구조다.
- 애플리케이션 계층에서는 인터페이스를 타입으로 받은 뒤, 나중에 인프라 등 구현체를 주입받는다.
- utils/ 에는 다양한 애플리케이션에서 공통으로 사용하는 유틸성 모듈을 저장한다. 예를 들어 다음과 같은 작업을 하는 모듈이 포함될 수 있다.
- repository에서 ORM 프레임워크를 통해 얻은 값을 도메인 객체로 변환하는 일
- e.g. SQLAlchemy의
inspect()
함수를 사용하여 repository의 return을 도메인 객체화.
- API Schema 객체 ↔ Domain 객체 변환은 API Schema에 정의하되, Request/Response Pydantic Schema의
from_attributes=True
기능을 사용하지 말고, 프로퍼티 매핑을 나열하는 방식으로 작성한다.
- xxx_repo는 repository 패턴에 따라 구현한다. 반환값은 도메인 객체여야 한다.
기술 선택
- pydantic은 v2 이상을 사용한다.
- 패키지와 의존성은 pyproject.toml과 uv를 통해 관리한다.
- ORM 프레임워크은 SQLAlchemy를 사용하고 autocommit을 사용한다.
- ORM 클래스를 작성할 때
__repr__
에 id
와 name
을 담아 디버깅을 용이하게 만든다.
- Database는 Supabase를 사용한다.
모범 사례
- id 타입은 UUID 대신 ULID를 사용한다.
- vo는 frozen=True로 설정하여 immutable하게 만든다.
- FastAPI의 Depends는 Annotated 폼 -
arg: Annotated[Type, Depends(dependable)]
- 으로 적는다.