DesignPatterns

[디자인 패턴] 도메인 모델 패턴 vs 트랜잭션 스크립트 패턴

누구세연 2024. 11. 13. 21:57

애플리케이션에서 비즈니스 로직을 어떻게 설계하느냐에 따라 성능이나 유지보수성, 확장성에 큰 영향을 줍니다.

그중 도메인 모델 패턴(Domain Model Pattern)과 트랜잭션 스크립트 패턴(Transaction Script Pattern)은 비즈니스 로직을 애플리케이션에서 처리하는 두 가지 대표적인 방식입니다.

 

이 글에서는 두 패턴의 대해서 그리고 각 패턴을 언제 사용하는 것이 좋을지 정리해 보겠습니다.🙂

 

도메인 모델 패턴이란?

도메인 모델 패턴은 도메인 주도 설계(DDD)에서 많이 사용하는 방식입니다.

비즈니스 로직을 도메인 객체 안에 포함하여 객체 지향적으로 관리합니다.

복잡한 비즈니스 로직이 포함된 시스템에서 코드가 실제 비즈니스 개념에 맞게 동작하도록 설계하는 것이 목표입니다.

  • 객체 중심 설계
    도메인 객체 자체가 상태와 로직을 함께 관리합니다.
  • 비즈니스 로직을 객체에 내포
    각 객체가 맡은 역할에 따라 비즈니스 규칙을 스스로 수행하게 만듭니다.
  • 복잡한 로직 처리에 적합
    객체 간의 관계와 상호작용이 필요한 복잡한 비즈니스 로직에 유리합니다.
public class Order {
    private List<Product> products = new ArrayList<>();
    private Customer customer;

    public void addProduct(Product product) {
        products.add(product);
    }

    public BigDecimal calculateTotal() {
        return products.stream()
                       .map(Product::getPrice)
                       .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

이 코드에서는 Order라는 도메인 객체가 products와 customer라는 상태(필드)를 가지고 있습니다. 또한 addProduct()와 calculateTotal() 같은 비즈니스 로직 메서드를 포함하고 있습니다.

  • 객체 중심의 설계: Order 객체가 addProduct()와 calculateTotal() 같은 메서드를 통해 제품 추가와 총액 계산을 스스로 수행합니다.
  • 비즈니스 로직의 내포: 제품의 가격을 모두 합산해 총액을 계산하는 로직이 Order 객체 내부에 존재하며, 제품을 추가하는 작업도 객체 스스로 수행합니다.
  • 복잡한 비즈니스 로직 관리에 적합: 제품과 고객 간 관계를 통해 다양한 비즈니스 규칙을 객체 간 상호작용으로 처리할 수 있습니다.

이러한 특징 때문에 이 코드가 도메인 모델 패턴에 해당한다고 볼 수 있습니다. 실제 비즈니스 개념에 맞춘 객체가 상태와 비즈니스 로직을 함께 관리하면서, 코드가 더 직관적으로 비즈니스 로직을 표현할 수 있게 됩니다.

 

장점

 

  • 표현력: 도메인 개념에 맞춰 로직을 설계하여 코드가 직관적이고 이해하기 쉬워집니다.
  • 유지보수성: 비즈니스 로직이 객체에 포함되어, 코드 변경 시 유지보수가 용이합니다.
  • 재사용성: 객체 단위로 재사용이 가능하여 모듈화 된 설계를 할 수 있습니다.

단점

 

  • 복잡도: 객체가 많아질수록 복잡도가 증가하고, 잘못된 객체 설계 시 관계가 엉킬 수 있습니다.
  • 초기 학습 곡선: 도메인 모델을 이해하고 설계하는 데 시간이 필요합니다.

 

 

 

트랜잭션 스크립트 패턴이란?

트랜잭션 스크립트 패턴은 비즈니스 로직을 특정 작업 단위로 나눠서 각각의 로직을 절차적으로 처리하는 방식입니다.

각 비즈니스 로직이 독립된 메서드로 작성되며 빠르게 트랜잭션을 처리할 때 유리합니다.

  • 절차 지향 설계
    비즈니스 로직을 메서드로 정의하여 절차적으로 실행합니다.
  • 단순한 로직 처리에 적합
    비교적 간단한 로직을 빠르게 처리하기에 적합합니다.
  • 빠른 개발 가능
    초기 개발 속도가 빠르며, 유지보수가 용이합니다.
public class OrderService {

    public void addProductToOrder(Order order, Product product) {
        order.getProducts().add(product);
    }

    public BigDecimal calculateTotal(Order order) {
        return order.getProducts().stream()
                    .map(Product::getPrice)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

이 코드에서는 OrderService라는 서비스 클래스가 비즈니스 로직을 담고 있습니다. 이 클래스는 addProductToOrder()와 calculateTotal() 같은 메서드를 통해 트랜잭션 단위로 로직을 처리합니다.

  • 절차 지향 설계: 각 메서드가 독립적으로 트랜잭션 단위로 작업을 수행하며, 절차적으로 작성되어 있습니다.
  • 단순한 로직 처리: 비즈니스 로직이 객체에 내포되어 있지 않고, 서비스 클래스 메서드에 명확하게 절차적으로 나눠져 있습니다.
  • 단순한 로직을 빠르게 처리: 트랜잭션 스크립트 패턴은 메서드가 각 기능을 독립적으로 수행하므로 간단한 비즈니스 로직을 처리할 때 적합합니다.

이와 같이 OrderService 클래스는 순차적으로 비즈니스 로직을 처리하는 데 중점을 두고 있기 때문에, 트랜잭션 스크립트 패턴의 특성을 잘 보여줍니다. 이 패턴에서는 로직이 객체에 내포되지 않으므로 상대적으로 코드가 단순해지고, 로직을 절차적으로 수행하는 데 집중하게 됩니다.

 

장점

  • 단순성: 코드가 단순하며 구조를 이해하기 쉽습니다.
  • 빠른 개발: 비즈니스 로직이 단순한 경우 빠르게 개발할 수 있어 효율적입니다.
  • 유연성: 특정 로직을 메서드 단위로 호출할 수 있어 기능별 수정이 용이합니다.

단점

  • 로직 중복 가능성: 로직이 여러 메서드에 중복될 가능성이 높아, 유지보수가 어려워질 수 있습니다.
  • 비즈니스 로직 집중 부족: 로직이 객체에 포함되지 않으므로 객체가 도메인 개념을 표현하지 못하며, 코드 일관성이 떨어질 수 있습니다.
  • 확장성의 한계: 시스템이 복잡해질수록 로직이 분산되고 중복이 생기기 쉽습니다.

 

 

두 패턴의 차이점 비교

구분 도메인 모델 패턴 트랜잭션 스크립트 패턴
설계 중심 객체 지향, 도메인 개념 중심 절차 지향, 함수 중심
적합한 시스템 복잡하고 객체 간 상호작용이 많은 시스템 간단한 로직을 빠르게 처리하는 시스템
개발 속도 초기 설계 시간이 더 필요 초기 개발 속도가 빠름
장점 유지보수성, 재사용성, 도메인 표현력 단순성, 유연성, 빠른 개발
단점 복잡성 증가, 학습 곡선 필요 중복 로직 가능성, 확장성 한계

 

 

언제 어떤 패턴을 선택할까?

두 패턴 중 하나를 선택할 때는 비즈니스 로직의 복잡도유지보수 요구사항을 고려하는 것이 중요합니다.

  • 도메인 모델 패턴: 복잡한 비즈니스 로직이 많고 객체 간 관계가 중요한 경우에 사용하기 적합합니다. 도메인 객체가 비즈니스 로직을 포함하기 때문에 유지보수와 확장성이 뛰어나며, 코드가 실제 비즈니스와 더 가깝게 표현됩니다.
  • 트랜잭션 스크립트 패턴: 간단한 로직을 빠르게 구현해야 할 때 유리합니다. 코드가 절차적으로 작성되어 개발 속도가 빠르며, 각 트랜잭션이 별도 메서드로 구성되기 때문에 간단한 애플리케이션이나 단순한 로직에 적합합니다.

 

💡 도메인 모델 패턴과 트랜잭션 스크립트 패턴은 비즈니스 로직을 효과적으로 관리하기 위해 고안된 설계 패턴입니다.
애플리케이션의 규모와 요구사항에 따라 적절한 패턴을 선택하는 것이 중요하며, 상황에 따라 두 패턴을 혼용해 유연하게 설계하는 것도 고려할 만합니다.