최근 들어 마이크로 서비스에 관련하여 책을 읽고, 관련 자료를 찾아보고 있다.
그런데 찾아보면서 도메인 주도 설계(DDD)라는 용어가 나오게 되었다.
그래서 DDD에 대해서 한 번 정리해보려고 한다.
DDD란?
도메인 주도 설계(DDD, Domain-Driven Design)는 해당 도메인과 일치하도록 소프트웨어를 모델링하는 데에 중점을 둔 소프트웨어 설계 접근 방식이다.
요약하면 도메인 위주로 모델링, 즉 설계해 나아가는 방식을 말한다.
Domain이란?
도메인은 소프트웨어나 애플리케이션에서 해결해야하는 문제를 나타낸다.
예를 들어, 택배를 관리하는 프로그램을 만든다고 가정하자.
택배를 주문하는 고객이 있을 수 있고, 판매하는 업체가 있을 수 있으며, 택배 물품을 관리하는 택배사가 존재할 수 있다.
위에서 언급한 고객, 판매 업체, 택배사가 모두 도메인이라고 볼 수 있다.
판매 업체는 택배사에 택배를 보내고, 택배사에서 고객에게 배달하고, 고객은 리뷰나 문의 등을 판매 업체에게 남길 수가 있다.
이는 즉 도메인들이 서로 상호작용 한다는 것을 의미한다.
즉, DDD는 개개의 도메인들이 서로 상호작용하며 문제 해결을 위한 설계를 하는게 바로 도메인 주도 설계이다.
DDD를 사용하는 이유
어떠한 소프트웨어를 개발하기 전, 설계를 진행하는 단계에서 각각의 도메인을 선정하고 추상화하여 문제를 해결한다.
소프트웨어는 초기 단계에서 작은 것들 부터 설계가 시작되면서 점차 그 규모가 커지게 된다.
이때 도메인끼리 서로가 강한 결합으로 되어 있다면, 한 곳에서 문제가 발생했을 때 이를 해결하기 위해 엄청난 공수가 들어가게 된다.
그리고 협업을 하는 입장에서 다른 사람들이 도메인을 이해하지 못한다면, 이 역시 협업을 하면서 큰 걸림돌로 작용을 할 것이다.
그래서 도메인 주도 설계를 통해서 비즈니스 요구 사항을 명확히 이해하고, 소프트웨어의 유연성을 향상시키며 새로운 요구사항을 빠르게 반영하는 것을 목표로 한다.
또한 애플리케이션 또는 그 안의 모듈간의 의존성을 최소화(Loosly coupling)하고, 응집성은 최대화(High cohesion)하는 것을 목표로 한다.
그래서 DDD는 다음과 같은 목표를 기반으로 한다.
- 핵심 도메인과 그 기능에 집중하라.
- 도메인의 모델을 정교하게 구축하라.
- 애플리케이션 모델을 발전시키고, 새롭게 생기는 도메인 관련 이슈를 해결하기 위해 도메인 전문가와 끊임없이 협력하라.
DDD의 설계 방식
DDD는 크게 개념 설계와 개발을 위한 구체적인 설계로 나뉘게 된다.
개념적 설계(Strategic Design)
개념적 설계란, Context에 대해 생각하고 이를 기준으로 디자인을 하는 것을 말한다.
여기서 Context란, 특정 객체 혹은 상황이 벌어지는 주변 환경을 말한다.
예를 들어 물을 페트병에 담아서 판매한다고 가정하자.
이때 물을 마트에서 판매하는 가격과 편의점에서 판매하는 가격이 다를 수 있다.
또한 브랜드에 따라 마트와 편의점에서 판매하는 물이 같은 물일 수도 있고 다른 물로 간주될 수도 있다.
이 처럼, 사물이나 행동 양상이 벌어지는 상황에 집중하여 디자인 하는 것이 개념적 설계(Strategic Design)의 핵심이라고 할 수 있다.
개념적 설계의 예로, 주택을 짓는 경우를 생각할 수 있다.
- 어떤 주택을 지을지 생각한다.
- 그런 집 전문가와 상의를 한다.
- 주택을 지을 때 어떤 핵심적인 가치에 집중하여 집을 지을지 선택한다.
- 예를 들어 안방이 넓어야 하거나, 수영장이 커야 한다던가 중점적인 사항을 명시한다.
- 다른 집을 최대한 많이 조사하여 마음을 원하는 집의 형상을 떠올린다.
- 그 형상을 실제 집으로 만들어 내기 위해 모델링을 한다.
- 모델링을 토대로 구체적인 설계도를 그린다. 이 설계도에는 주택의 매우 구체적인 부분들을 명시한다.
이렇게 DDD를 통한 설계 과정에서 사용되는 용어는 다음과 같다.
용어 | 설명 |
Domain | 집 전체에 대한 설계 |
SubDomain | 집을 구성하는 부분 집합(ex 거실, 수영장 등) |
Domain Model | 실제 SubDomain의 구체적인 형상 |
Context | 집을 구성하는 각 부분 구간들에 대한 환경 |
위와 더불어 추가적으로 알아야 하는 내용은 다음과 같다.
유비쿼터스 언어(Ubiquitous Language)
DDD에서는 개발자와 사용자간 도메인 모델에 기초하는 공통적인 언어를 사용해야 한다.
개발자와 비즈니스 전문가가 사용하는 용어가 다르면 오해와 혼란이 발생할 수 있기 때문이다.
이 처럼 모든 사람들이 공통으로 이해하고 사용하는 언어를 유비쿼터스 언어라고 한다.
도메인에서 사용하는 언어는 코드에 그대로 반영이 되어야 한다.
만일 똑같이 반영되지 않으면 개발자는 해당 용어를 해석하고 이해해야하는 부담이 생긴다.
그래서 코드의 가독성을 높이고 코드를 분석하고 이해하는데 시간을 절약하기 위해 유비쿼터스 언어를 사용해야 한다.
경계된 컨텍스트(Bounded Context)
특정 모델이 정의되고 적용될 수 있는 영역을 의미한다.
DDD에서는 모델을 경계된 컨텍스트로 구분한다.
그리고 경계된 컨텍스트 안에서는 유비쿼터스 언어를 사용해야 한다.
이로서 외부와 분리하여 경계 안에서의 지식을 일관되게 유지 시켜 준다.
특정 모델은 어떤 경계된 컨텍스트를 놓이는가에 따라 다르게 이해될 수 있다.
예를 들어, 주택 정문에서 caretaker라는 모델이 있다면 '경비원'을 뜻한다.
하지만 이 단어가 주택 건물 안에서 가지는 의미는 '아이를 돌보는 사람'이 될 수도 있다.
컨텍스트 매핑(Context Map)
각 경계된 컨텍스트들 사이의 관계를 말한다.
컨텍스트 경계를 식별하고, 이들간의 관계를 표현한 그림을 의미한다.
구체적 설계(Tactical Design)
구체적 설계는 개발을 위해 구체적인 설계를 하는 것을 의미한다.
세부적인 사항을 구현하는 것을 위해 필요하며, 주로 경계된 컨텍스트 내의 구성 요소들을 관리한다.
계층화된 아키텍쳐(Layered Architecture)는 구체적 설계를 진행할 때 모든 프로세스를 업무 순서로 쪼개고, 계층을 나누어 설계하는 것을 말한다.
스프링 부트(Spring Boot)에서는 각 계층(Layer)에 목적에 맞게 3가지 어노테이션(Annotation)을 제공한다.
Layer | Annotation |
Presentation Layer | @Controller, @RestController |
Service Layer, Domain Layer | @Service |
Data Layer | @Repository |
도메인 모델링 구성
기존 객체 모델링은 자유도가 높아 문제 영역을 파고들수록 여러 층의 복잡한 계층 구조를 만들게 될 가능성이 높다.
구체적 셀계에서는 도메인 모델링 구성 요소의 역할에 따라 유형을 정의하고, 이러한 규칙에 따라 모델링을 하면 단순하게 설계가 가능하다.
도메인 모델링 구성 요소는 다음과 같다.
- 엔티티
- 값 객체
- 애그리거트
- 팩토리
- 레포지토리
엔티티(Entity)
엔티티는 다른 엔티티와 구별할 수 있는 식별자를 가진 도메인의 실체 개념을 표현하는 객체이다.
식별자는 고유하되, 엔티티의 속성 및 상태는 계속 변할 수 있다.
또한 식별자를 가지고 있기 때문에 Business Logic을 구현할 수 있고 DB로 상태 추적이 가능하다.
값 객체(VO, Value Object)
VO는 각 속성이 개별적으로 변화하지 않는 개념적 완전성을 모델링한다.
VO의 value 타입은 불변하며, 객체의 값을 변경하는 방법은 새로운 value 객체를 할당하는 것 뿐이다.
예를 들어 소프트웨어 내에서 화폐를 취급하는 객체가 있다면, 이는 화폐에 관한 모든 처리를 스스로 처리할 수 있어야 한다.
이때 단위 환산, 표현법 변경 등은 다양한 도메인 로직을 가져야 하며, 제 3자에 의해 변하지 않고 일관성을 유지해야 한다.
애그리거트(Aggregate)
관련 엔티티의 집합을 의미한다.
예를 들어 customer, customerInfo, address라는 세 종류의 Entity가 있다면, 이 모든 정보는 Customer라는 주제로 뭉칠 수가 있다.
이들 간에는 비즈니스 의존 관계를 맺고 있으며, 비즈니스 정합성을 맞출 필요가 있다.
따라서 애그리거트의 단위가 트랜잭션의 기본 단위가 된다.
애그리거트는 응집력을 유지하고 서로간의 느슨한 결합을 유지한다.
팩토리(Factory)
팩토리는 복잡한 엔티티 혹은 애그리거트를 생성하는 것을 담당한다.
예를 들어 엔진과 부속품을 넣으면 자동차가 나오는 공장과 같이, 특정 정보를 factory에 넣으면 결과로 엔티티나 애그리거트를 만들어주게 된다.
이때 이 안에서 벌어지는 일에 대해서는 개발자가 더 이상 신경을 쓰지 않아도 되는 하나의 모듈로 사용할 수 있다.
팩토리는 자신의 생성물과 가장 밀접한 관계에 있는 위치에 있어야 한다.
레포지토리(Repository)
일반적인 Data를 관리하는 역할을 한다.
애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의한다.
레포지토리는 애그리거트(루트) 단위로 존재하며, 테이블 단위로 존재하는 것이 아니다.
(애그리거트 1개당 레포지토리 1개)
출처 : 도메인 주도 설계, 도메인 주도 설계란? DDD란?, [IT정보] 도메인 주도 설계(Domain Driven Design, DDD) 개념,
'개념정리 > 설계' 카테고리의 다른 글
MSA란, 모놀리식과의 차이점 (0) | 2024.01.21 |
---|