C#

C# 기초부터 고급까지 Chapter 3.8. Domain-Driven Design(DDD) 도입과 구조 설계

Juan_ 2025. 5. 12. 23:11
728x90

📘 Chapter 3.8: Domain-Driven Design(DDD) 도입과 구조 설계


✅ 이 챕터에서 배울 것

  • DDD란 무엇인가? 왜 쓰는가?
  • 도메인, 유비쿼터스 언어, 애그리거트, 엔티티, 밸류오브젝트
  • 계층별 구성 (Domain, Application, Infra, API)
  • 실무 프로젝트 예제 구조
  • 레이어 간 의존 방향
  • 실무에서 마주치는 DDD 오해와 해결 전략

1️⃣ DDD란?

"복잡한 비즈니스 도메인을 객체 모델로 설계하는 방법론"

마틴 파울러의 말:

💬 "도메인 전문가와 개발자가 공통 언어(Ubiquitous Language)를 기반으로 소프트웨어를 만든다."

✅ 왜 쓰는가?

문제 상황DDD 도입 효과
요구사항 변경 잦음유연한 구조로 적응 가능
기술 중심 설계비즈니스 중심 설계로 전환
코드 구조가 뒤죽박죽도메인 단위로 정리 가능
팀 간 소통 안 됨공통 용어 기반으로 일치

2️⃣ 핵심 개념 요약

용어설명
도메인해결하려는 문제 영역 (ex: 주문 시스템)
유비쿼터스 언어모든 팀원이 공유하는 용어 체계
엔티티ID를 기준으로 구분되는 객체 (ex: Order)
밸류 오브젝트값으로만 의미가 있는 객체 (ex: Address)
애그리거트엔티티 + 관련 밸류 오브젝트 묶음
리포지토리객체를 영속화/조회하는 인터페이스
서비스도메인의 비즈니스 로직 처리 담당
애플리케이션 서비스유스케이스 조율 담당

3️⃣ 레이어 구조

/Domain
  - Entity, ValueObject, Repository 인터페이스
/Application
  - 유스케이스, 서비스, CommandHandler
/Infrastructure
  - DB 접근 구현체, 외부 API 연동
/Presentation
  - API, UI

✅ 의존성 방향

Presentation → Application → Domain ← Infrastructure
                        ↑
                (Ports and Adapters)

💡 Clean Architecture와 DDD는 구조적으로 유사!


4️⃣ 실전 프로젝트 예제: 주문 시스템

📁 Domain Layer

🧱 Order.cs (Entity)

public class Order
{
    public Guid Id { get; private set; }
    public List<OrderItem> Items { get; private set; } = new();

    public void AddItem(Product product, int quantity)
    {
        Items.Add(new OrderItem(product, quantity));
    }
}

🧱 OrderItem.cs (Value Object)

public class OrderItem
{
    public Product Product { get; }
    public int Quantity { get; }

    public OrderItem(Product product, int quantity)
    {
        Product = product;
        Quantity = quantity;
    }
}

📁 Application Layer

🧠 OrderService.cs

public class OrderService
{
    private readonly IOrderRepository _repo;

    public OrderService(IOrderRepository repo)
    {
        _repo = repo;
    }

    public void PlaceOrder(Guid userId, List<(Guid, int)> productInfo)
    {
        var order = new Order();

        foreach (var (productId, qty) in productInfo)
        {
            var product = ProductStore.Get(productId);
            order.AddItem(product, qty);
        }

        _repo.Save(order);
    }
}

📁 Infrastructure Layer

public class EfOrderRepository : IOrderRepository
{
    private readonly AppDbContext _context;

    public EfOrderRepository(AppDbContext context)
    {
        _context = context;
    }

    public void Save(Order order)
    {
        _context.Orders.Add(order);
        _context.SaveChanges();
    }
}

📁 Presentation (API)

[ApiController]
[Route("api/orders")]
public class OrderController : ControllerBase
{
    private readonly OrderService _orderService;

    public OrderController(OrderService service)
    {
        _orderService = service;
    }

    [HttpPost]
    public IActionResult CreateOrder(CreateOrderDto dto)
    {
        _orderService.PlaceOrder(dto.UserId, dto.Items);
        return Ok();
    }
}

5️⃣ DDD 흔한 오해

오해진실
모든 클래스에 DDD 용어 써야 함아니, 비즈니스 중심 영역만 적용
Entity/VO 나누는 게 중요중요한 건 유비쿼터스 언어 + 경계 명확화
DDD = 복잡함프로젝트에 맞게 경량 도입 가능
꼭 Hexagonal이어야 함계층 구조도 OK, 의존 방향만 잘 지키면 됨

✅ 정리 요약

항목설명
DDD란?도메인 중심 소프트웨어 설계 방법론
핵심 개념엔티티, VO, 애그리거트, 서비스, 리포지토리
구조Domain → Application → Infra, API
실무 장점유지보수, 확장성, 팀 협업 극대화
도입 팁작게 시작하고 점진적으로 확장하자

📢 다음 챕터 예고 🎓

다음 챕터주제
Chapter 3.9CQRS + MediatR 패턴 실전 예제
728x90