본문 바로가기
카테고리 없음

헥사고날 - 도메인 개념

by 인생은즐겁게 2026. 1. 21.
반응형

 도메인

구성 요소 역할 상태 변경 대표 예
Entity 상태/정체성 보유 + 행위(전이) 수행 Member, Order
VO 값 불변 + 값 검증 Money, Email, MemberId
Policy 엔티티 조합 판단(허용/불허) RefundPolicy, SubscriptionPolicy
Type 의미 고정(상태/분류/코드) MemberStatus, PaymentMethod
Domain Event 일어난 사실표현(후속 반응 연결) MemberActivated, PaymentCompleted
Domain Service (선택) 엔티티 2개 이상 얽힌 핵심 규칙/연산 PricingService
Factory (선택) 복잡한 생성 규칙 캡슐화 OrderFactory
Specification (선택) 복잡한 조건식을 재사용 가능한 형태로 EligibleForRefundSpec

 

1 엔티티(Entity)

(1)     정의

엔티티는 상태를 가진 주체이고, 그 상태를 바꾸는 책임을 스스로 진다.

(2)     특징

    정체성(ID)이 있다.

    상태를 가진다

    상태 변경(전이)을 직접 수행한다.

    자기 자신에 대한 규칙을 안다.

(3)     하는 일

    상태 전이 판단 + 변경

    자기 상태에 대한 질문에 답함

 

 

class Member(
    private var status: MemberStatus
) {
    fun activate() {
        require(status == PENDING)
        status = ACTIVE
    }
 
    fun isActive(): Boolean =
        status == ACTIVE
}

상태 변경이 가능하며, 변경된 상태도 확인이 가능하다.

 

2 정책(Policy)

(1)     정의

정책은 여러 조건을 종합해서 어떤 행동이 허용되는지 판단하는 규칙이다.

(2)     특징

    상태를 가지지 않는다.

    변경하지 않는다.

    판단만 한다. (true/false, 계산 결과 등)

    하나 이상의 엔티티를 볼 수 있다.

(3)     하는 일

    엔티티 조합으로 판단 여부

: Policy는 판단만 하고 엔티티는 판단을 하기 위해 제공함

 

class Member(
    private var status: MemberStatus
) {
    fun activate() {
        require(status == PENDING)
        status = ACTIVE
    }
 
    fun isActive(): Boolean =
        status == ACTIVE
}

 

3 VO (Value Object)

(1)     정의

값 그 자체의 의미와 규칙을 캡슐화한 뷸변 객체이며 값의 유효성을 책임진다.

(2)     특징

    값 검증과 의미 보장

    잘못된 값의 유입 차단

    유효한지 보장하기 위해서 정규식도 사용함

 

class Email(val value: String) {
    init {
        require(EMAIL_REGEX.matches(value)) {
            "이메일 형식이 올바르지 않습니다."
        }
    }
 
    companion object {
        private val EMAIL_REGEX =
            Regex("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")
    }
}

 

(3)     하는 일

    값 검증

    의미 캡슐화

    갑 기반 비교

 

 

4 도메인 Type

(1)     정의

Type은 도메인에서 사용하는 의미가 고정된 분류·상태·코드를 코드로 명확하게 정의한 것이다.

(2)     특징

(3)     하는 일

    의미 고정

 

enum class MemberStatus {
    PENDING,
    ACTIVE,
    SUSPENDED
}

 

    분기 기준 제공

 

when (member.status()) {
    ACTIVE -> ...
    SUSPENDED -> ...
}

 

    도메인 언어 통일

 

 

5 도메인 이벤트(Event)

(1)     정의

도메인에서 의미 있는 변화가 이미 일어났다는 사실을 표현한 객체다.

과거형 사실(Fact)만 표현한다.

(2)     특징

    사실 전달

    과거형 시제

    마커 인터페이스 상속

 

interface DomainEvent

 

 

data class MemberActivated(
    val memberId: MemberId
) : DomainEvent

 

(3)     하는 일

    일이 이미 일어났다는 걸 도메인 밖에 알리는 것

    엔티티에서 상태 변경 후 등록

    유스케이스에서 수거(pull)

    유스케이스에서 전파(publish)

    리스너가 이벤트에 반응

주체 하는 일
Entity 이벤트 생성 & 등록
UseCase 이벤트 수거 & 전파
Listener 이메일, 알림 등 실제 처리

 

 

 

6 도메인 서비스

(1)     정의

도메인 규칙 기반 연산·계산을 담당하는 객체다.

(2)     특징

    도메인 규칙 있음

    정체성(ID) 없음

    DB/트랙잭션/외부 호출 없음

    여러 엔티티를 입력으로 사용

(3)     하는 일

    도메인 규칙으로 계산하거나 조합한다.

    계산 및 연산

) 가격 계산, 할인 계산, 조건 기반 결과 산출

 

class PricingService {
 
    fun calculate(
        order: Order,
        coupon: Coupon,
        point: Point
    ): Money {
        var price = order.totalPrice()
 
        if (coupon.isUsable(order)) {
            price = price.minus(coupon.discount())
        }
 
        price = price.minus(point.usableAmount())
 
        return price
    }
}

 

7 Factory

(1)     정의

도메인 규칙에 어긋나지 않도록 엔티티를 항상 유효한 초기 상태로 성성하는 도메인 구성요소다.

(2)     특징

규칙은 있지만, 상태는 없다

(3)     하는일

    기본 상태 설정

    필수 VO 조립

    생성 시 검증

    잘못된 생성 경로 차단

    (필요 시) 초기 도메인 이벤트 등록

 

반응형

댓글