개발노트

25.03.12 도메인 주도 설계 ( DDD )란? 본문

MSA

25.03.12 도메인 주도 설계 ( DDD )란?

ddong-kka 2025. 3. 12. 00:57

개요

프로젝트 설계과정에서 DDD를 필수로 도입하고해야할 거 같아서 한번 정리해보겠다.

자진해서 팀장을 한다고했는데 일을 키운게 아닌가 걱정이된다.

학부에서 내가 팀장을 하면 프로젝트가 터지는 경험을 4번이나 했다.

징크스를 깨고싶다

 


도메인 주도 설계 (  DDD ) 란?

소프트웨어의 복잡성을 효과적으로 관리하기 위해 도메인( 비즈니 영역 )에 집중하는 설계 방식이다.

즉, 단순히 코드 구조를 정리하는 것이 아니라 비즈니스 로직과 도메인 모델을 중심으로 시스템을 구축하는 방법론이다.

 

기술적인 요소보다는 비즈니스 도메인(업무 영역)에 집중하여 현실 세계의 개념을 코드로 표현하는 방식이다.

변경에 유연하고 유지보수가 쉬운 시스템을 구축하는 것이 주 목표다.


DDD의 핵심 개념

출처 : https://medium.com/myrealtrip-product/what-is-domain-driven-design-f6fd54051590

 

도메인 ( Domain )

  • 애플리케이션이 해결하는 비즈니스 문제 영역을 뜻한다.
  • 예를 들어, 쇼핑몰, 금융 시스템, 병원 예약 시스템 등이 도메인이 될 수 있다.

 

서브 도메인 ( SubDomain )

  • 도메인은 일반적으로 여러 개의 작언 서브 도메인으로 나뉜다.
  • 예를 들어, 쇼핑몰 도메인은 다음과 같이 서브도메인으로 구성될 수 있다.
    • 상품 관리 (Product Management)
    • 주문 처리 (Order Processing)
    • 결제 시스템 (Payment System)
    • 배송 관리 (Shipping Management)

 

바운디드 컨텍스트 ( Bounded Context )

  • 하나의 서브도메인을 담당하는 논리적인 경계를 의미한다.
  • 바운디드 컨텍스트 내에서는 독립적인 도메인 모델이 존재하며, 다른 바운디드 컨텍스트와 협력한다.
  • 예를 들어, 주문 처리결제 시스템은 서로 다른 바운디드 컨텍스트로 나뉠 수 있다.

 

도메인 모델 ( Domain Model )

  • 현실 세계의 개념을 소프트웨어로 표현한 모델이다.
  • 비즈니스 로직을 포함하며, 엔티티(Entity), 밸류 오브젝트(Value Object), 애그리게이트(Aggregate) 등의 개념을 포함한다.

 

엔티티 ( Entity )

  • 고유한 식별자를 가지며, 변경 가능한 객체이다.
  • 예를 들어, 사용자(User), 주문(Order) 등이 엔티티가 될 수 있다.

 

밸류 오브젝트 ( Value Object )

  • 식별자가 없고, 값 자체로 의미를 가지는 불변 객체이다.
  • 예를 들어, 주소(Address), 가격(Price) 등이 밸류 오브젝트로 사용될 수 있다.

 

애그리게이트 ( Aggregate )

  • 연관된 도메인 객체들을 하나로 묶은 개념이다.
  • 애그리게이트 내부의 객체들은 애그리게이트 루트( Aggregate Root )를 통해서만 접근할 수 있다.
  • 예를 들어, 주문(Order)은 여러 개의 주문 아이템(OrderItem)을 포함하는 애그리게이트가 될 수 있다.

 

도메인 서비스 ( Domain Service )

  • 엔티티나 밸류 오브젝트에 포함하기 어려운 비즈니스 로직을 캡슐화하는 서비스이다.
  • 예를 들어, 할인 정책( Discount Policy )을 도메인 서비스로 만들 수 있다.

 

리포지토리 ( Repository )

  • 애그리게이트를 저장하고 조회하는 역할을 한다.
  • 예를 들어, OrderRepository는 Order 애그리게이트를 저장하고 가져오는 역할을 한다.

 


DDD를 적용한 설계 예제

// ✅ 주문 엔티티 (Aggregate Root)
public class Order {
    private Long id; // 주문 ID
    private List<OrderItem> items; // 주문 항목 리스트
    private OrderStatus status; // 주문 상태
    private Address shippingAddress; // 배송지 주소 (Value Object)

    public Order(List<OrderItem> items, Address shippingAddress) {
        this.items = items;
        this.shippingAddress = shippingAddress;
        this.status = OrderStatus.PENDING;
    }

    public void completeOrder() {
        this.status = OrderStatus.COMPLETED;
    }
}

// ✅ 주문 아이템 (Value Object)
public class OrderItem {
    private String productName;
    private int quantity;
    private BigDecimal price;

    public OrderItem(String productName, int quantity, BigDecimal price) {
        this.productName = productName;
        this.quantity = quantity;
        this.price = price;
    }
}

// ✅ 배송 주소 (Value Object)
public class Address {
    private String street;
    private String city;
    private String zipCode;

    public Address(String street, String city, String zipCode) {
        this.street = street;
        this.city = city;
        this.zipCode = zipCode;
    }
}

// ✅ 주문 상태 (Enum)
public enum OrderStatus {
    PENDING, COMPLETED, CANCELLED
}

 

 


 

DDD를 적용할 때의 장점과 단점

장점

 

  • 비즈니스 로직 중심 설계
    → 복잡한 비즈니스 규칙을 명확하게 정의할 수 있다.
  • 유지보수성 향상
    → 도메인 중심으로 설계하여 코드 가독성이 좋아지고, 확장성이 좋아진다.
  • 도메인 모델의 재사용성 증가
    → 도메인 객체와 로직이 잘 분리되어 재사용이 쉽다.

 

단점

 

  • 초기 설계 비용이 크다
    → 바운디드 컨텍스트와 도메인 모델을 정의하는 데 많은 시간이 필요하다.
  • DDD를 이해하고 적용하기 어렵다
    → 개발자들이 도메인 모델을 깊이 이해해야 한다.
  • 작은 프로젝트에서는 과도할 수 있다
    → 단순한 CRUD 중심의 프로젝트에는 적합하지 않을 수 있다.