Post

[DDD] 도메인 주도 설계란 무엇인가

[DDD] 도메인 주도 설계란 무엇인가

DDD 전체 구조

전략적 설계 (Strategic Design)

“무엇을 만들 것인가?” - 큰 그림 관점

1. 유비쿼터스 언어 (Ubiquitous Language)

개발자, 기획자, 도메인 전문가가 똑같은 용어로 소통

예: 경매 시스템

  • “입찰한다” → placeBid()
  • “낙찰된다” → closeAuction()
  • “재등록한다” → reListItem()
  • 이렇게 실제 대화에서 쓰는 용어를 그대로 코드에 반영하면, 도메인 전문가가 말한 규칙 = 코드가 된다.

2. 경계 컨텍스트 (Bounded Context)

같은 개념이라도 다른 컨텍스트에서 다르게 취급할 수 있음

예: User라는 개념도 상황(컨텍스트)에 따라 다르게 쓰임

  • 로그인 컨텍스트 → “인증 주체” (아이디/비밀번호가 중요)
  • 결제 컨텍스트 → “구매자” (결제수단, 주소가 중요)
  • 경매 컨텍스트 → “입찰자” (입찰 금액이 중요)

즉, 같은 User라도 어디에 쓰이냐에 따라 모델이 달라지고, 그걸 경계로 나눠 관리


전술적 설계 (Tactical Design)

“어떻게 만들 것인가?” - 구체적 구현 관점

1. 엔티티 (Entity)

식별자를 가지고 있다 → 즉 생명주기를 가지고 있다

2. 값 객체 (Value Object)

값 자체가 중요한 객체

3. 애그리거트 (Aggregate)

엔티티와 값 객체가 뭉쳐 있는 덩어리, 이 덩어리에서 대표를 정하는 것 → 애그리거트 루트(Aggregate Root)

외부에서는 이 루트를 통해서만 접근 가능. 내부의 세부 엔티티나 값 객체는 루트가 책임지고 관리

예: 주문(Order)

  • 루트: Order (애그리거트 루트)
  • 안에 들어가는 것: OrderLine(주문 상품들), Money(가격), Address(배송지)
  • 외부에서 주문을 바꿀 때는 항상 Order 객체를 통해서만 해야 함 → 그래야 무결성이 보장

4. 도메인 서비스 (Domain Service)

도메인 규칙이나 절차를 코드로 구현하는 곳

유비쿼터스 언어(도메인 전문가랑 합의한 용어)를 반영

  • 예: “입찰한다(placeBid)”, “주문을 결제한다(payOrder)” 같은 행위
  • 즉, 비즈니스 로직 구현 역할, 애플리케이션 서비스는 유스케이스 조율 역

5. 리포지토리 (Repository)

엔티티/애그리거트를 DB에 저장하거나 꺼내는 책임

  • “동일성” 기준으로 동작 (id = 000001인 User 찾아줘)
  • 즉, 데이터 저장/조회 역할

핵심: 동일성 vs 동등성

DDD(도메인 주도 설계)에서 엔티티(Entity)와 값 객체(Value Object)를 구분하려면 동일성과 동등성을 잘 알아야 한다. 이 차이를 명확히 알지 못하면, 도메인 모델은 현실을 제대로 표현하지 못하고 버그로 이어진다.

예를 들어 두 사람이 있다고 하자. 이름, 나이, 이메일이 모두 똑같다고 해서 같은 사람일까? 아니다. 주민등록번호, 계좌번호처럼 고유 식별자가 다르다면 전혀 다른 사람이다.

반대로 1000원 지폐 두 장은 일련번호는 다르더라도 금액이 같으면 같은 ‘가치’를 가진다.

동일성 (Identity)

  • 객체가 고유하게 구별되는 기준
  • DB에서는 주로 Primary Key에 해당
  • 값이 바뀌어도 같은 객체로 취급
1
2
User u1 = new User(1L, "kim", "kim@test.com");
u1.changeEmail("new@test.com");
  • id = 1L 이라는 동일성은 변하지 않음
  • email 값은 변했지만 u1은 여전히 동일한 User 객체

동등성 (Equality)

  • 객체의 속성 값이 같으면 같은 것처럼 여김
  • equals() / hashCode() 재정의로 표현
  • 값이 변하면 다른 것으로 취급
1
2
Money m1 = new Money(1000, "KRW");
Money m2 = new Money(1000, "KRW");
  • 두 객체는 다른 인스턴스지만 값이 같으므로 동등(equal)
  • m1.equals(m2) -> true
  • 이런 걸 값 객체(Value Object) 라고 부름

결론

  • 엔티티(User, Order, Auction, …) → 동일성으로 구분
  • PK, UUID 같은 식별자 필요
  • 값 객체(Email, Money, Address, …) → 동등성으로 구분
  • 불변(Immutable)하게 만들어 값만 같으면 같은 객체 취급

코드가 도메인을 표현한다.

This post is licensed under CC BY 4.0 by the author.