카샤의 만개시기

도메인 주도 설계란 무엇인가? 10분 요약 본문

Architecture/DDD

도메인 주도 설계란 무엇인가? 10분 요약

SKaSha 2022. 2. 16. 22:48

도메인 주도 설계란

도메인

자동화된 비즈니스 프로세스나 현실 세계의 문제

도메인 전문가

해당 분야의 전문가 (ex. 은행의 업무 체계는 은행가가 도메인 전문가)

추상화

도메인을 표현한 모델

도메인 모델

도메인을 소프트웨어로 모델링한것.
특정한 다이어그램이 아니라 그 다이러그램이 전달하고자 한 아이디어 (에릭 에반스 said)
즉 도메인 전문가에의 지식을 선택적으로 추상화하여 조직화 한것.

도메인 모델을 만들때 정보를 조직화, 체계화하고 이를 작은 부분으로 나눠서 그 조각들을 다시 논리적 모듈로 그룹화하여 한번에 하나씩 다루어야 한다.
모메인 모델을 만들때 불필요한 요소들은 제거해야하며 이러한 요소는 명확하지 않을때도 있다.
도메인 모델을 이용하여 도메인 전문가, 설계자, 개발자들이 의사소통해야한다.

소프트웨어 설계 애자일론

  • 폭포수 설계
    지식의 전달이 한방향으로 가는 한계

  • 익스트림 프로그래밍
    팀원들이 설계 결정을 내리는것을 두려워해 진도가 나가지 못하는 분석 마비 현상이 발생하기도 하는데 이는 프로젝트 초기에 도메인의 중요한 요소를 다루는 완벽한 모델을 만드려고 하여서이다.
    대신 구현을 매우 용이하게 변경할 수 있는 유연성을 확보해 놓고,
    비즈니스 이해관계자의 지속적인 참여와 수많은 리팩터링 작업을 통해 개발을 반복적으로 수행한다

유비쿼터스 언어

도메인 전문가, 설계자, 개발자들은 서로 다른 그들만의 전문 용어를 사용한다.
모델은 sw와 도메인이 서로 교차하는 지점이기 때문에 모델 기반의 언어를 사용하는것이 적절하며 이것이 DDD의 핵심 원칙이다.

모델 주도 설계

분석 모델과 코스 설계를 분리하는것보다 좀 더 나은 접근 방식은 도메인 모델링과 설계를 밀접하게 관련시키는 것이다.
모델이란 소프트웨어 그 자체와 설계 고려 사항에 초점을 맞추어 만들어져야하며, 개발자들은 모델링 프로세스가 진행되는 동안 함께 참여애야한다.
코드와 그 기반이 되는 모델을 밀접하게 연관시킴으로써, 코드에 의미가 생기고 모델은 실제적으로 중요한 가치를 지니게 된다.

모델 주도 설계를 위한 블록

복잡한 프로그램을 레이어로 분할해야 한다.
각 레이어 내부에서 설계를 수행하여 응집도 높고 자기 하위 레이어에만 의존하도록 만들어야 한다.

  • 사용자 인터페이스
    사용자에게 정보를 보여주고 사용자의 명령을 해석하는 책임을 짐
  • 애플리케이션 레이어
    애플리케이션 활동을 조율하는 얇은 레이어로 업무 로직을 포함하지 않음.
    비즈니스 객체의 상태는 보관하지 않지만 애플리케이션 작업의 처리 사앹는 보관함.
  • 도메인 레이어
    도메인 정보, 비즈니스 객체의 상태를 포함.
    비즈니스 객체와 그들의 상태를 역속화하는 책임은 인프라스트럭쳐 레이어로 위임된다
  • 인프라스트럭처 레이어
    다른 레이어 모두를 지원하는 라이브러리로 동작.
    레이어간의 통신을 제공하고 비즈니스 객체의 영속성을 구현하고 사용자 인터페이스 레이어의 라이브러리를 포함한다.

엔티티

연속성과 식별성을 갖는 객체로 여러 상태를 거치는 동안에도 유일하다

값 객체

도메인의 어떤 측면을 표현하는데 식별자가 필요하지 않은 객체
불변으로 사용하여야하며 상태를 변경해야 한다면 새로운 VO를 만들어라

서비스

내부적인 상태는 가지지 않으면서 단순히 도메인에 기능을 제공하는 목적을 지님

  • 서비스에 의해 수행되는 오퍼레이션은 일반적으로 엔티티 또는 값 객체에 속할 수 없는 도메인의 개념을 나타낸다
  • 수행되는 오퍼레이션은 도메인의 다른 객체롤 참조한다
  • 오퍼레이션은 상태를 저장하지 않는다

모듈

응집도는 높이고 결합도는 낮추는 방향으로 적용
다른 모듈에서 쉽게 접근할수 있는 인터페이스를 제공함으로써 내부의 구체적인 클래스를 참조하지 않도록 결합도를 감소

집합 (aggregation)

객체의 소유권과 경계를 정의하는데 사용되는 패턴
데이터를 변경할 때 하나의 단위로 간주되는 관련된 객체들의 집합으로 외부와 내부를 가르는 경계를 정해 구분한다.
각 집합은 엔티티라고 하는 하나의 root를 지니며 외부 객체는 root에 대한 참조만을 지니기 때문에 데이터 무결성을 보장하고 불변식을 강제할수 있다.

다대다 관계는 대부분 양방향으로 복잡도를 가파르게 상승시켜 객체들의 생명주기 관리를 어렵게 한다.
관계에 참여하는 객체의 숫자(다수성, multiplicity)는 가능한 한 최소화 하는것이 좋다.

  1. 모델의 핵심 사항이 아닌 관계가 있다면 그 관계를 제거한다
  2. 다수성(multiplicity)의 숫자는 제약사항(constraint)을 추가하여 감소시킨다
  3. 대부분의 경우 양방향 관계는 단방향 관계로 대체될수 있다.

복잡한 참조관계를 가질 경우 데이터 무결성을 지키기 위해 DBMS의 트랜잭션과 lock에 기대게 되며 많은 비용을 요구하게 된다.
그로 인해 모델 설계 수준에서 복잡한 참조관계를 해결하는것이 가장 좋다

팩토리

복잡한 객체 생성의 절차를 캡슐화할 수 있는 순수한 도메인 레이어.

팩토리 구현 방식
  • 팩토리 메소드 패턴
  • 추상 팩토리 패턴

다음과 같은 경우에 팩토리 대신 생성자를 사용한다.

  • 생성 작업이 복잡하지 않다
  • 객체의 생성이 다른 객체의 생성과 연관되어 있지 않으며 모든 속성이 생성자를 통해 전달되어야 한다.
  • 클라이어트가 구현에 관심이 있어서, 사용할 전략패턴을 선택하려고 한다.
  • 클래스가 바로 해당 타입이다. 관련된 계층 구조가 없어서 concrete 구현 목록에서 선택할 필요가 없다.

리파지토리

도메인 모델이 객체의 저장이나 참조와 연관을 없애고 하부의 영속성을 보장하는 인프라스트럭처에 접근할 필요가 없도록 하는 것

모델 무결성 보존

분할된 컨텍스트 (Bounded Context)

모델의 범위를 정의하는 작업의 기본 개념은 모델의 범위를 정하고 컨텍스트 간의 경계를 설정한 다음 모델이 통합된 상태를 최대한 유지하도록 하는것

모듈은 모델의 구성요소들을 조직화하기 위해 사용되고, 분할된 컨텍스트는 발전하는 모델에 담길 논리적 프레임을 제공하는 모듈을 포함하는 개념이다

컨텍스트 맵

서로 다른 분할된 컨텍스트들과 그들의 관계에 대해 개요를 표현한 문서로써 모든 사람은 각 컨텍스트의 범위와 코드의 맵핑 상태를 알고 있어야 한다.

컨텍스트 맵에서 컨텍스트가 명확한 역할과 관계를 설명할수 있도록 패턴을 사용한다

  • 컨텍스트 간 상호작용의 수준이 높음 : 공유커널 패턴, 고객-공급자 패턴
  • 컨텍스트 간 독립성이 높음 : 분할방식 패턴
  • 내외부 상호작용을 다룬 패턴 : 오픈호스트서비스 패턴, 변질방지 패턴

공유커널

분할된 컨텍스트 간에 도메인 일부가 공유되어야 한다면, 명시적으로 공유된 부분을 지정하여 상대 팀과 의사소통을 하면서 변경되어야 한다.
공유 커널의 목적은 중복을 줄이는 것이지만 여전히 분할된 두 컨텍스트는 유지되어야 한다

고객-공급자

두 서브시스템 한쪽이 다음 한쪽에 완전히 의존하는 식의 특별한 관계를 맺는 경우이며 공통된 코드를 기술적으로 가질수 없는 구조.
고객-공급자 관계는 양쪽 팀이 관계 유지에 관심이 있을 때 성공할 수 있다.
두 팀이 단일 관리 체계 하에 있을때에 의사결정 절차가 쉬워지고 화합을 이끌 수 있다.
순응적 테스트 수트가 만들어져야 하고 인터페이스 요구 사항이 준수될 때 마다 언제든 테스트되어야 한다

순응

고객-공급자 관계에서 두 팀이 서로 다른 회사거나 공급자가 매우 바쁘다면 관계를 유지할 수 없게 되고 고객이 공급자의 모델을 사용해기 위해서는 순응해야한다.

변질 방지 레이어

레거시 어플리케이션이나 분리된 어플리케이션과 상호작용을 할 일이 생기는데, 자신의 모델과 외부의 모델이 독립되도록 클라이언트와 외부 모델 사이에 변질 방지 레이어를 두는게 좋다
이 레이어는 두개의 서로 다른 도메인과 언어 간에 양방향 번역자의 역할을 하여 클라이언트 모델이 외부로부터 영향 받지 않는 일관된 상태로 남는 장점이 있다

변질 방지 레이어 구현 방법
  • Facade 패턴을 이용하여 서브시스템에 있는 인터페이스들을 통합하여 고수준의 인터페이스 제공
  • Adapter를 이용하여 클래스의 인터페이스를 클라이언트가 이해할 수 있는것으로 변환하여 두 시스템간의 번역 수행
  • Translator를 이용하여 객체와 데이터를 번역

분할 방식

모델링과 설계의 관점에서 공통된 부분이 없다면 어플리케이션을 쪼개서 개발할 수 있다
독립적으로 개발된 모델들은 통합하기가 매우 어렵기 때문에 통합의 가치가 파생되는 문제점보다 작은지 살펴보아야한다

오픈 호스트 서비스

서브시스템이 많은 다른 시스템과 통합되어야 할때, 각각의 번역기를 사용하면 유지관리 비용이 늘어나게 된다
외부 서브시스템을 서비스로 감싸 서비스의 제공자로 제공하여 모든 다른 서브 시스템들이 해당 서비스를 통해서만 접근 하도록하여 번역 레이어가 필요하지 않게 한다.

증류 (Distillation)

혼합체를 구성하고 있는 물질을 분리해 내는 절차로써 혼합체로부터 특별한 물질을 분리하는것.
도메인의 규모가 크다면 이를 재정의하고 추상화 작업을 하더라도 대규모 모델로 표현 될 수 밖에 없기 때문에,
도메인의 정수를 표현하는 핵심 도메인을 정의해야함.
도메인을 증류 처리할때 생기는 부산물은 모데인의 다른 파트를 구성하는 일반 서브도메인.
핵심 도메인과 서브 도메인을 분리하는데 많은 노력을 가해야한다

DDD 조언

DDD는 팀 전체가 하는 거대한 작업이다

도메인 모델링의 위험

  1. 단순한 상태를 유지해라
  2. 구체적인 시나리오에 초점을 맞추고 추상적 생각은 실제 사례에 연결되어 있어야만 한다
  3. DDD를 모든 것에 적용하려고 하지 마라. 컨텍스트맵을 그리고 어느 부분에 DDD를 적용할 것인지 결정하고 경계 바깥에 있는것은 신경쓰지 마라
  4. 실험을 많이 하고 실수를 많이 할것이라고 예상하라. 모델링은 창조적인 작업이다

관련 서적

도메인 주도 설계란 무엇인가? (쉽고 간략하게 이해하는 DDD)

Comments