Skip to content

2.1 도메인 주도 설계의 개요: 본래의 목적을 다시 확인하고 경량 DDD에서 탈피하기 #1536

@jongfeel

Description

@jongfeel

2.1 도메인 주도 설계의 개요: 본래의 목적을 다시 확인하고 경량 DDD에서 탈피하기

2.1.1 도메인 주도 설계란?

도메인이란 소프트웨어 개발의 대상이 되는 업무 영역입니다.
여기서는 조금 더 구체적으로, 도메인을 비즈니스 활동으로, 도메인 로직을 업무 로직이라는 용어로 설명합니다.

2.1.2 도메인 주도 설계의 특징

에릭 에반스의 <도메인 주도 설계> 서문에 따르면, 도메인 주도 설계의 특징은 다음의 세 가지입니다.

  • 복잡한 업무 로직에 초점을 맞춘다.
  • 모델에 기반해서 설계한다.
  • 리팩터링을 자주 수행한다.

도메인 주도 설계의 고유한 특징은 바로 복잡한 업무 로직에 집중하는 것입니다.
이것을 위한 수단으로 모델링과 리팩터링을 중요시하고 있습니다.

복잡한 업무 로직에 초점을 맞춘다

업무 로직과 업무 규칙

업무 규칙이란 업무 목표를 달성하기 위한 행동을 통제하고 결정하기 위한 것입니다.
업무 규칙은 비즈니스 활동에 포함됩니다.

이것을 소프트웨어로 구현한 것이 업무 로직입니다.
업무 로직이란 업무 규칙에 따라 정의된 작업으로, 소프트웨어로 구현한 업무 규칙이라고 할 수 있습니다.

업무 로직은 비즈니스 활동을 표현하는 업무 데이터를 사용하고, 업무 규칙에 따라 정의된 작업을 수행합니다.

복잡한 업무 로직과 경쟁 우위

도메인 주도 설계는 복잡한 업무 로직에 집중합니다.
소프트웨어의 핵심 가치는 복잡한 업무 로직에서 나오기 때문입니다.

경쟁사가 쉽게 따라 할 수 있는 단순한 업무 로직으로는 경쟁 우위를 확보할 수 없습니다.

업무 로직의 발전성

비즈니스 활동에 있어서 중요한 업무 로직일수록 수정과 확장이 유연하게 이루어져야 하며, 소프트웨어가 복잡해지더라도 수정할 수 있는 유연성을 유지하도록 하는 것은 도메인 주도 설계의 중요한 목적입니다.

복잡한 업무 로직에 집중해야 하는 이유

한정된 시간을 이용하여 설계해야 한다면 경쟁 우위를 위한 복잡한 업무 로직에 집중하는 것이, 비즈니스 활동에 있어서 비용 대비 효과가 높은 방법입니다.
이것이 도메인 주도 설계의 근본을 이루는 개념입니다.

모델에 기반해서 설계한다

소프트웨어를 만들기 위한 모델은 두 가지로 분류할 수 있습니다.
하나는 업무 내용이나 요구사항을 이해하기 위한 분석 모델입니다.
다른 하나는 소프트웨어를 실제로 만들기 위한 설계 모델입니다.

분석 모델은 복잡한 비즈니스 활동을 이해하고 이를 통제하는 다양한 업무 규칙을 파악하는 데 필요하며, 설계 모델은 복잡한 업무 규칙을 소프트웨어로 표현하는 데 필요합니다.

도메인 주도 설계는 분석 모델과 설계 모델을 일치시키는 것을 중시합니다.
업무 규칙의 구조인 분석 모델과 소프트웨어의 구조인 설계 모델을 일치시킴으로써 비즈니스 요구에 근거해서 수정과 확장이 쉬워집니다.

리팩터링을 자주 수행한다

설계의 어려움에 대처하는 방법이 설계를 지속적으로 개선하는 활동, 즉 리팩터링입니다.
모델이든 설계든 처음부터 완벽하게 좋은 것을 만들 수는 없습니다.
이해하기 위한 분석 모델과 소프트웨어를 만들기 위한 설계 모델이 처음부터 자연스럽게 일치하기는 어렵습니다.
이와 같은 전제하에 도메인 주도 설계에서는 업무 지식을 가지고 있는 도메인 전문가와 소프트웨어 개발 지식을 가지고 있는 개발자가 함께 모델과 설계의 개선을 반복해 나갑니다.

도메인 주도 설계에서 리팩터링은 양방향으로 이루어집니다.
모델 개선이 코드 변경으로 이어지고, 코드 리팩터링이 모델의 진화로 이어집니다.
업무 지식을 배우면서 모델과 설계의 양방향 리팩터링을 반복함으로써, 분석 모델과 설계 모델을 일치시킵니다.

2.1.3 도메인 주도 설계의 설계 기법 이해하기

모든 설계 기법의 목적은 복잡한 업무 로직에 초점을 맞추는 것입니다.
또한 그 목적을 달성하기 위해 설계 기법끼리 조합하여 활용하는 것이 필요합니다.
도메인 주도 설계의 설계 기법을 이해하고, 효과적으로 활용하기 위해서는 이 두 가지를 파악하는 것이 중요합니다.

전략적 설계와 전술적 설계

분류 방법은 반 버논(Vaughn Vernon)의 저서 <도메인 주도 설계 구현(Implementing Domain-Driven Design)>(에이콘출판, 2016)에서 소개되었습니다.
전략적 설계와 전술적 설계는 서로 보완하는 관계이며, 그 목적은 복잡한 업무 로직을 효과적으로 다루는 데 있습니다.
전략적 설계를 수행하려면 전술적 설계가 제대로 실행되아야 하고, 마찬가지로 전술적 설계를 진행하려면 전략적 설계와의 조화가 필요합니다.

전략적 설계

전략적 설계는 넓은 시야에서 모델을 만드는 것을 중요하게 생각합니다.
반면 전술적 설계에서 중점적으로 대처해야 할 부분을 파악한 다음, 전체를 구성하는 각각의 요소를 어떻게 상호 연계할 것인가를 결정하기 위한 일련의 기법입니다.

전략적 설계 기법의 대표적인 예는 유비쿼터스 언어, 경계 컨텍스트, 컨텍스트 맵, 핵심 도메인이 있습니다.

전술적 설계

전술적 설계는 복잡한 업무 로직을 소프트웨어로 표현하기 위한 기법으로, 실제 소스 코드를 구현하기 위한 기술적인 측면에 가까운 설계 기법입니다.

대표적인 기법으로 엔터티, 값 객체, 애그리게이트, 모듈이 있으며, 부가적인 기법으로는 도메인 이벤트, 리포지터리가 있습니다.

2.1.4 경량 DDD

반 버논은 저서에서 경량 DDD를 다음과 같이 소개하고 있습니다.

  • 기술적인 관점으로 전술적 설계를 도입한다.
  • 전술적 설계의 극히 일부를 적용한다.
  • 전략적 설계에 전념하지 않는다.

반 버논이 전술적 설계의 다른 이름으로 경량 DDD를 소개한 것은 아닙니다.
그는 전술적 설계는 도메인 주도 설계의 기초이자 중요한 설계 활동이라고 이야기합니다.
에릭 에반스도 마찬가지이며, 전략적 설계를 위한 모델 주도 설계의 기본적인 구성 요소로서 전술적 설계가 중요하다고 말하고 있습니다.

이 두 사람의 주장에 따르면 전략적 설계의 기초가 되는 전술적 설계와 전략적 설계를 따르지 않는 경량 DDD는 다릅니다.
특히 다음과 같은 차이점이 있습니다.

  • 복잡한 업무 로직에 초점을 맞추지 않는다.
  • 설계 기법을 서로 관련짓지 않는다.

경량 DDD와 본래의 전술적 설계는 동일하지 않습니다.
전술적 설계는 복잡한 업무 로직에 초점을 맞춘 설계 활동의 기본입니다.
복잡한 업무 로직을 정확하게 이해하고, 계속 진화하는 소프트웨어로 구현하려면 다양한 전술적 설계를 활용하는 것이 필요합니다.

경량 DDD가 되어 버리는 이유

대부분의 예시 코드는 설명을 위해 최대한 단순하게 만들었으므로 예제만 봐서는 도메인 주도 설계가 복잡한 업무 로직에 초점을 맞추는 설계 방법임을 간과하기 쉽습니다.
경량 DDD란 이렇게 단순화된 코드를 도메인 주도 설계의 구체적인 예로 오해한 상태에서 생겨난 용어일지도 모릅니다.

2.1.5 본래의 도메인 주도 설계에 집중하기

경량 DDD 단계를 빨리 벗어나려면 두 가지 관점을 의식하는 것이 중요합니다.
복잡한 업무 로직에 초점을 맞추는 것과 설계 기법을 조합하는 것입니다.

2.1.6 기초가 되는 설계 기법

전략적 설계에서는 유비쿼터스 언어, 전술적 설계에서는 값 객체 등이 있습니다.

유비쿼터스 언어

업무 로직을 올바르게 설계하려면 먼저 업무 규칙을 정확하게 이해하는 것이 중요합니다.
이를 위해 반드시 참고해야 할 핵심 정보의 원천은 바로 도메인 전문가입니다.
도메인 전문가와 함께 모델을 만들고, 설계에 활용하기 위한 기본 수단으로 유비쿼터스 언어를 사용하는 것입니다.

유비쿼터스 언어의 대상은 복잡한 업무 로직을 표현하기 위해 사용되는 값 객체입니다.

값 객체

업무 로직은 업무 규칙을 소프트웨어로 구현한 계산과 판단 규칙입니다.
이러한 업무 규칙에 따른 계산에서는 금액, 수량, 날짜 등과 같은 업무 활동의 상태를 측정하며, 그 결과도 금액, 수량, 구분 등의 값으로 판단하고 표현합니다.

업무 규칙을 기술하기 위한 용어가 유비쿼터스 언어이며, 이러한 기본 용어를 소프트웨어로 표현한 것이 값 객체입니다.

2.1.7 핵심이 되는 설계 기법

전략적 설계에서는 핵심 도메인, 전술적 설계에서는 애그리게이트입니다.

핵심 도메인

핵심 도메인은 경쟁 우위를 창출하기 위한 차별화된 업무 영역입니다.
그리고 복잡한 업무 로직은 핵심 도메인의 업무 활동과 업무 규칙을 반영합니다.

경쟁 우위를 창출하기 위한 핵심 도메인의 업무 로직은 복잡하며 자주 변경됩니다.
이 핵심 도메인과 복잡한 업무 로직이야말로, 도메인 주도 설계를 도입해야 하는 중요한 이유입니다.

애그리게이트

애그리게이트는 복잡한 업무 로직을 표현하는 수단입니다.
업무 데이터와 업무 로직을 캡슐화한 각각의 ‘값 객체’들을 결합하여 복잡한 업무 로직을 표현하는 클래스가 바로 애그리게이트입니다.

애그리게이트를 설계하는 것은 복잡한 업무 로직을 소스 코드로 표현하기 위한 하나의 노력입니다.
프로그래밍 언어를 사용하여 복잡한 업무 로직을 언어화하고 구조화함으로써 핵심 도메인을 쉽게 파악하게 되는 것입니다.

복잡한 업무 로직은 소스 코드에서 애그리게이트 클래스 이름과 메서드 이름으로 표현됩니다.
그리고 그 이름은 유비쿼터스 언어의 중요한 용어가 됩니다.

핵심 도메인을 식별하고 경쟁 우위를 유지하기 위해 애그리게이트 모델의 설계와 리팩터링을 지속적으로 수행합니다.
이것이 복잡한 업무 로직에 초점을 맞추는 도메인 주도 설계의 핵심 활동입니다.

2.1.8 전체를 연계하는 설계 기법

전체를 조망하고 연결하기 위한 설계 기법이 전략적 설계로 분류되는 컨텍스트 맵과 전술적 설계로 분류되는 모듈입니다.

컨텍스트 맵

경계 컨텍스트는 모델의 분할 단위이자, 독립적인 개발 단위입니다.
대부분의 소프트웨어 개발은 컨텍스트 여러 개를 연결해야 하는 경우가 많습니다.
경계 컨텍스트는 사내의 기존 시스템일 수도 있고, 외부의 클라우드 서비스(SaaS, Software as a Service)일 수도 있습니다.

컨텍스트 맵은 핵심 도메인과 복잡한 업무 로직의 관점에서 컨텍스트 간의 관계를 시각화하고 검토하기 위한 수단입니다.

서로 다른 모델 연계하기

컨텍스트를 연결하는 방법, 즉 모델을 연결하는 방법에는 기본적으로 다음 세 가지 선택이 있습니다.

  • 모델 내에서 연계와 관련된 부분을 공유한다.
  • 자신의 모델을 상대방의 모델에 맞게 변환한다.
  • 상대방의 모델을 자신의 모델에 맞게 변환한다.

첫 번째, 경계 컨텍스트는 각자 고유한 모델로 구분되어야 하는데 그러한 경계를 넘나들면서 공유할 수 있다면, 애초에 경계 컨텍스트의 구분 방식에 문제가 있다고 볼 수 있습니다.

두 번째, 상대방의 모델을 그대로 사용하는 데 별다른 문제가 없다면 비교적 간단하게 구현할 수 있습니다.
상대방의 모델에 맞추다 보면 자신의 모델이 왜곡될 수도 있기 때문에 주의를 기울여야 합니다.

이러한 여러 상황을 고려한다면 실제로는 세 번째 방법을 선택하는 경우가 많을 것입니다.
하지만 모델 변환과 유지보수에 많은 비용이 발생하므로 변환 대상 범위를 최대한 줄이고 단순하게 만들어서 전체 비용을 줄이려고 노력해야 합니다.

어떤 연계 방식을 선택할지 결정하는 데 중요한 요소는 전략적 설계의 ‘핵심 도메인’과 전술적 설계의 ‘값 객체’입니다.

핵심 도메인을 지키기 위한 방법으로 세번째 방법을 선택하는 것이 좋습니다.

모듈

큰 틀에서 전체를 바라보고 정리하기 위해 사용되는 전술적인 설계 기법이 모듈입니다.
모듈은 프로그래밍 언어에 따라 패키지(package) 또는 네임스페이스(namespace)라고 불리는 소스 코드의 단위입니다.
대부분은 파일을 정리하는 폴더 구조처럼 되어 있습니다.

모듈 이름은 업무상 중요한 관심사를 표현하는 수단으로 유비쿼터스 언어에 포함되어야 하는 중요한 용어입니다.

도메인 모델을 설명하는 짧은 문장을 최상위 모듈의 이름으로 만들 수 있다면 도메인 주도 설계 본연의 목적에 맞는 좋은 모듈 구조라고 할 수 있습니다.

객체 지속화와 재구축

애그리게이트 객체처럼 업무 로직을 표현하는 클래스를 설계할 때 데이터베이스의 구조와 연관시키면 클래스 구조가 많이 복잡해집니다.
이렇게 불필요하게 복잡해지는 것을 피하기 위한 방안이 전술적 설계의 리포지터리입니다.

리포지터리는 업무 로직을 표현하지 않기 때문에 데이터베이스 조작이나 객체 생성에 대한 자세한 내용을 알 필요가 없습니다.
단지 이러한 기술적인 관심사를 분리하기 위한 도구이며 다음과 같은 두 가지의 설계 방식이 있습니다.

  • 애그리게이트의 최신 상태 유지와 업데이트
  • 저장과 참조의 분리

에릭 에반스가 <도메인 주도 설계>를 집필할 당시의 리포지터리 설계 방식은 전자에 가까웠습니다.
최근에는 저장과 참조를 분리하는 후자의 방식을 채택하는 경우가 많아졌습니다.

Metadata

Metadata

Assignees

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions