Skip to main content

Spakky DDD

Spakky Framework를 위한 Domain-Driven Design 빌딩 블록입니다. Entity, AggregateRoot, ValueObject, DomainEvent, Command, Query 모델의 공통 기반을 제공합니다.

설치

pip install spakky-domain

주요 기능

  • Entity: 고유 identity와 생명주기를 가진 객체
  • Value Object: 속성 값으로 비교되는 불변 객체
  • Aggregate Root: 이벤트 관리를 포함하는 일관성 경계
  • Domain Event: 이벤트 기반 아키텍처를 위한 불변 이벤트
  • CQRS: Command와 Query 유스케이스 추상화

빠른 시작

엔티티

엔티티는 시간이 지나도 유지되는 고유 identity를 가진 객체입니다.

from uuid import UUID, uuid4

from spakky.core.common.mutability import mutable
from spakky.domain.models.entity import AbstractEntity


@mutable
class User(AbstractEntity[UUID]):
    name: str
    email: str

    @classmethod
    def next_id(cls) -> UUID:
        return uuid4()

    def validate(self) -> None:
        if not self.email:
            raise ValueError("Email is required")

값 객체

값 객체는 불변이며 속성 값으로 비교됩니다.

from spakky.core.common.mutability import immutable
from spakky.domain.models.value_object import AbstractValueObject


@immutable
class Money(AbstractValueObject):
    amount: int
    currency: str

    def validate(self) -> None:
        if self.amount < 0:
            raise ValueError("Amount cannot be negative")

애그리거트 루트

애그리거트 루트는 도메인 이벤트를 관리하는 엔티티입니다.

from typing import Self
from uuid import UUID, uuid4

from spakky.core.common.mutability import mutable, immutable
from spakky.domain.models.aggregate_root import AbstractAggregateRoot
from spakky.domain.models.event import AbstractDomainEvent


@immutable
class OrderCreatedEvent(AbstractDomainEvent):
    order_id: UUID
    customer_id: UUID


@mutable
class Order(AbstractAggregateRoot[UUID]):
    customer_id: UUID
    total: int

    @classmethod
    def next_id(cls) -> UUID:
        return uuid4()

    def validate(self) -> None:
        if self.total < 0:
            raise ValueError("Total cannot be negative")

    @classmethod
    def create(cls, customer_id: UUID, total: int) -> Self:
        order = cls(uid=cls.next_id(), customer_id=customer_id, total=total)
        order.add_event(OrderCreatedEvent(order_id=order.uid, customer_id=customer_id))
        return order

도메인 이벤트

도메인 이벤트는 도메인 내부의 상태 변화를 표현합니다.

from spakky.core.common.mutability import immutable
from spakky.domain.models.event import AbstractDomainEvent, AbstractIntegrationEvent


# Internal domain event
@immutable
class UserRegistered(AbstractDomainEvent):
    user_id: str
    email: str


# Cross-boundary integration event
@immutable
class UserRegisteredIntegration(AbstractIntegrationEvent):
    user_id: str
    email: str

CQRS 유스케이스

읽기와 쓰기 작업을 분리합니다.

핵심 원칙:

  • Command: 도메인 Aggregate 영속화에 Repository 사용
  • Query: ORM/SQL로 직접 구현(Repository에 query 메서드 추가 금지)
  • Query 관심사를 도메인 레이어 밖에 두어 도메인 오염을 방지합니다.
from uuid import UUID

from spakky.core.common.mutability import immutable
from spakky.domain.application.command import AbstractCommand, IAsyncCommandUseCase
from spakky.domain.application.query import AbstractQuery, IAsyncQueryUseCase


# Command
@immutable
class CreateUserCommand(AbstractCommand):
    name: str
    email: str


class CreateUserUseCase(IAsyncCommandUseCase[CreateUserCommand, UUID]):
    async def run(self, command: CreateUserCommand) -> UUID:
        # Business logic here
        ...


# Query
@immutable
class GetUserQuery(AbstractQuery):
    user_id: UUID


class GetUserUseCase(IAsyncQueryUseCase[GetUserQuery, User | None]):
    async def run(self, query: GetUserQuery) -> User | None:
        # Business logic here
        ...

API 레퍼런스

모델

클래스 설명
AbstractEntity[T] identity type T를 가진 엔티티의 기반 클래스
AbstractAggregateRoot[T] 도메인 이벤트를 관리하는 Entity
AbstractValueObject 불변 value object
AbstractEvent 모든 이벤트의 기반 클래스
AbstractDomainEvent 도메인 이벤트(bounded context 내부)
AbstractIntegrationEvent 통합 이벤트(경계 간 통신)

애플리케이션

클래스 설명
AbstractCommand command DTO의 기반 클래스
AbstractQuery query DTO의 기반 클래스
ICommandUseCase 동기 command use case interface
IAsyncCommandUseCase 비동기 command use case interface
IQueryUseCase 동기 query use case interface
IAsyncQueryUseCase 비동기 query use case interface

관련 패키지

패키지 설명
spakky-data Repository와 transaction 추상화
spakky-event Event publisher/consumer interface와 @EventHandler stereotype

개발 검증

패키지 단위 검증은 해당 패키지 디렉토리에서 실행합니다.

uv run ruff format .
uv run ruff check .
uv run pyrefly check
uv run pytest

pytest는 각 패키지 pyproject.toml의 coverage 설정을 사용합니다.

라이선스

MIT License

Metadata

Release files for spakky-domain 8.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spakky-domain 8.1.0
File Size Uploaded
spakky_domain-8.1.0.tar.gz 8.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for spakky-domain 8.1.0
File Interpreter ABI Platform
spakky_domain-8.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.3 kB

Release files / spakky_domain-8.1.0.tar.gz

Download URL spakky_domain-8.1.0.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
62552ee3ea4aacced8322d98f67ad48d251c7329cffcf67d92e44f2ccecf46f4
BLAKE2b-256 checksum
How to use checksums
3854eaafc4ebd37de767bdf385491cfbc37ba2f1c2e57964d124e801d074d27f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.

Transparency log

Release files / spakky_domain-8.1.0-py3-none-any.whl

Download URL spakky_domain-8.1.0-py3-none-any.whl
Size 13.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
834ecc2ff3c9a5560e4eb3c1049365208393c27d3b5218b83e6dad7e5140b140
BLAKE2b-256 checksum
How to use checksums
f3069e4cfded087349cbbad6ccbb23de38b66c7c7939adb279f749b6096eec5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

8.1.0 This release

2 release files

8.0.0

2 release files

7.2.0

2 release files

7.1.1

2 release files

7.1.0

2 release files

7.0.0

2 release files

6.13.0

2 release files

6.12.0

2 release files

6.11.0

2 release files

6.10.1

2 release files

6.10.0

2 release files

6.9.1

2 release files

6.9.0

2 release files

6.8.0

2 release files

6.7.0

2 release files

6.6.1

2 release files

6.6.0

2 release files

6.5.0

2 release files

6.4.0

2 release files

6.3.1

2 release files

6.3.0

2 release files

6.2.0

2 release files

6.1.3

2 release files

6.1.2

2 release files

6.1.1

2 release files

6.1.0

2 release files

6.0.0

2 release files

5.0.1

2 release files

5.0.0

2 release files

4.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page