25 Apr 2019

도메인 주도 설계 04 - 도메인의 격리

소프트웨어의 구현을 건전한 상태로 유지하고, 모델과의 밀접한 관계를 유지하려면 모델링과 설계의 우수한 실천법을 적용해야 한다. 모델의 여러 요소들을 실제로 설계하고 구현할 때는 검증된 일정한 체계적인 방법으로 진행할 수 있다. 소프트웨어에서 도메인 설계 외의 수많은 관심사로부터 도메인 설계를 격리하면 모델과 설계의 관계가 훨씬 분명해질 것이다.


일정한 구분법에 따라 모델 요소를 정의하면 이 모델 요소의 의미가 더욱 명확해진다. 또한 개별 요소에 대해 이미 널리 입증된 패턴을 따른다면 구현에 실질적으로 도움이 되는 모델을 만드는데도 도움이 된다.

00.png


도메인의 격리

시스템에서 도메인과 관련이 적은 것으로부터 도메인 객체를 분리해야 한다. 그래야 도메인 개념을, 다른 소프트웨어 기술에만 관련된 개념과 혼동하거나 시스템이라는 하나의 큰 덩어리에서 도메인을 전혀 바라보지 못하는 문제를 방지할 수 있다.

개발자가 도메인 모델에 집중할 수 있도록 시스템의 수많은 관심사로부터 도메인 설계를 격리하면 모델과 설계의 관계는 훨씬 분명해질 수 있다.


Layerd Architecture (계층형 아키텍처)

01.png

소프트웨어에는 갖가지 작업을 수행하는 설계와 코드가 포함된다. 사용자 입력을 받아들이고, 비즈니스 로직을 수행하며, DB에 접근하고, 네트워크로 통신하며, 사용자에게 정보를 보여주는 등의 다양한 일을 수행한다. 따라서 이런 기능들과 관련된 기술적인 코드의 양은 상당히 많을 수 있다.

간혹 사용자 인터페이스와 DB, 기타 보조적인 성격의 코드를 도메인을 다루는 비즈니스 객체에 직접 작성하기도 한다. 아니면 비즈니스 로직이 UI나 DB의 스크립트에 들어가기도 한다. 이런 일이 발생하는 이유는 단기적으로 이렇게 구현하는 것이 가장 쉬운 방법이기 때문이다.

도메인과 관련된 코드가, 도메인과 관련이 없는 다른 코드를 통해 여기저기 흩어진다면 도메인을 다루는 코드를 확인하고 이해하기가 상당히 어려워진다. UI를 변경하는 것이 실제 비즈니스 로직을 변경하는 것으로 이어질 수도 있다. 업무 규칙을 이해하고 변경하기위해 UI나 DB 스크립트, 자잘한 요소들을 세심하게 추적해야 될 수 있다. 이러면 응집력있고, 모델 주도적인 객체를 구현하는 것이 비현실적이 된다. 기술과 로직이 모든 곳에 같이 포함되어 있다면 프로그램을 이해하기가 불가능해진다.

매우 복잡한 작업을 처리하는 소프트웨어를 작성할 때는 관심사의 분리가 필요하며, 이를 통해 서로 격리된 각 설계 요소에 집중할 수 있다.


시스템을 분리하는 방법은 다양하지만 오랜 경험과 관례를 통해 Layered Architecture라는 몇 개의 일반화된 계층이 널리 받아들여지고 있다. 계층화의 핵심은 한 계층의 모든 요소는 오직 같은 계층에 존재하는 다른 요소나 계층상 “아래”에 위치한 요소에만 의존한다라는 것이다.

이러한 계층화의 가치는 각 계층이 프로그램의 특정 측면만을 전문적으로 다룬다는 데 있다. 따라서 더욱 응집력있는 설계가 가능해지며 훨씬 더 쉽게 이해할 수 있다.

이 계층형 아키텍처는 보통 아래의 네 가지 계층으로 나뉜다.

  • 표현 계층: 사용자에게 정보를 보여주고, 사용자의 요청을 해석하는 일에 책임진다.
  • 응용 계층: 소프트웨어가 수행할 작업을 정의하고 비즈니스 로직이 담긴 도메인 객체가 문제를 해결하도록 한다.
    • 보통 이 계층은 얇게 유지되는데, 업무 규칙이나 도메인 지식이 전혀 포함되지 않으며 오직 수행할 작업을 조정하고 도메인 계층에 포함된 도메인 객체에 작업을 위임한다.
    • 응용 계층은 업무 상황을 반영하는 상태가 존재하지 않는다.
  • 도메인 계층: 업무 규칙과 업무 상황에 대한 상태 관리, 업무 규칙을 표현하는 일을 책임진다.
    • 업무 상황을 반영하는 상태를 제어하고 사용하며, 상태 저장과 관련된 기술적인 세부사항은 인프라스트럭처 계층에 위임한다.
    • 소프트웨어의 핵심이다.
  • 인프라스트럭처 계층: 상위 계층을 지원하는 일반화된 기술적 기능을 제공한다.
    • 메시지 전송이나 도메인 영속화 등이 있다.

응용 계층이 아닌 도메인 계층에서 업무 규칙을 다루어야 한다. 응용 계층은 어느 한 작업을 정의만 할 뿐, 실질적인 비즈니스 로직은 도메인 계층에 위임한다.

인프라스트럭처 계층은 지원하는 도메인의 구체적인 업무 규칙이나 지식을 가져서는 안된다.

Model Driven Design을 가능케 하는 것은 결정적으로 도메인 계층을 분리하는 데 있다.

복잡한 프로그램을 여러 개의 계층으로 나누고, 응집력있고 오직 아래에 위치한 계층에만 의존하는 각 계층에서 설계를 발전시켜나가야 한다. 상위 계층은 하위 계층의 공개된 인터페이스만을 사용하는 등, 각 계층은 다른 계층들과의 연결을 느슨하게 유지해야 한다. 이런 깔끔한 관심사의 분리를 통해 각 계층의 설계를 이해하고 유지하기가 쉬워진다.

도메인 모델과 관련된 코드는 모두 도메인 계층으로 모으고, 사용자 인터페이스 코드나 응용 계층 코드, 인프라스트럭처 코드로부터 격리시켜야 한다. 그래야 도메인 객체는 도메인 모델을 표현하는 것에만 집중할 수 있다. 이를 통해 모델에 풍부하고 명확한 업무 지식을 반영할 수 있다.

도메인 계층을 다른 계층으로부터 분리하면, 각 계층을 훨씬 명료하게 설계할 수 있다. 격리된 계층을 유지하는데 드는 비용은 훨씬 더 적은데, 이는 격리된 계층이 각자 다른 속도로 발전해서 서로 다른 요구사항에 대응할 것이기 때문이다. 도메인을 격리할 때의 가장 좋은 점은 부수적인 것을 배제하고 개발자로 하여금 도메인 설계에만 집중할 수 있다는 것이다.


아키텍처 프레임워크

기술적 측면을 다루는 인프라스트럭처의 기능을 인터페이스를 통해 호출되는 Service 형태로 제공하면, 계층화의 동작 방식과 각 계층이 느슨하게 결합되는 방식이 직관적으로 보여진다. 그런데 일부 기술적인 문제에서는 더욱 침습적인(intrusive) 형태의 인프라스트럭처가 필요하다.

예전 J2EE에서처럼 특정 계층이 특수한 방식으로 구현되기를 요구하기도 한다. 어느 특정 클래스의 하위 클래스가 되어야 한다거나 일정한 메서드 이름 규칙을 사용해야 하는 것처럼 말이다.

가장 바람직한 아키텍처 프레임워크라면 개발자가 도메인 모델을 표현하는 것에만 집중할 수 있도록 복잡한 기술적 난제를 해결한다. 스프링 프레임워크도 이를 따르는 애플리케이션 프레임워크로, DI나 AOP, 서비스 추상화 등을 통해 개발자가 비즈니스 로직에 집중할 수 있도록 해준다.


도메인 계층은 모델이 살아가는 곳

도메인 주도 설계에서는 오직 한가지 특정한 계층이 중요하다.

도메인 모델은 소프트웨어에서 가장 중요한 업무 개념을 표현한 것이다. 도메인 계층은 그러한 모델과 설계 요소에 직접적으로 연관된 모든 것들을 명시한 곳이며, 비즈니스 로직에 대한 설계와 구현으로 구성된다. 도메인 로직이 도메인과 관련없는 다른 관심사와 섞여 있다면, 변경되는 요구사항에 대한 유연한 대응을 달성하기가 쉽지 않다. 도메인 주도 설계의 전제조건은 도메인 구현을 격리하는 것이다.


도메인 구현을 격리하지 않을 때

도메인 구현을 다른 관심사와 분리하지 않고 개발한다면 다음과 같은 상황에 직면할 수 있다.

  • 데이터베이스를 이용하는 방식 말고는 여러 애플리케이션을 통합하기가 수월하지 않다.
  • 행위를 재사용하지 않으며, 도메인에 대한 추상화가 제대로 이루어지지 않는다. 비즈니스 로직을 수행하는 각 연산마다 로직이 중복되는 경우가 생긴다.
  • 추상화의 부재로 리팩터링의 여지가 제한될 수 있다.

Tags:
Stats:
0 comments