티스토리 뷰

728x90
반응형

예전에 Spring Data JDBC에 대해 다루며 DDD에 대해 잠깐 언급한 적이 있다.

 

2022.08.29 - [개발/Spring] - [Spring]Spring Data JDBC - 도메인 엔티티&테이블 설계

 

[Spring]Spring Data JDBC - 도메인 엔티티&테이블 설계

지난 글에선 JDBC, ORM, Spring Data JDBC에 대해 살펴보았다. 2022.08.26 - [개발/Spring] - [Spring]JDBC(Java DataBase Connectivity) 2022.08.26 - [개발/Spring] - [Spring]SQL Mapper vs. ORM 2022.08.26 -..

gnidinger.tistory.com

아주 짧게만 언급하고 넘어가서 개념이 잘 잡히지 않았는데,

 

이 글에서 DDD에 대해 조금 더 알아보기로 하자.

 

Domain Driven Design, DDD

 

DDD란 말 그대로 도메인을 중심에 놓고 앱을 설계해 나가는 방식을 말한다.

 

Loose Coupling, High Cohesion을 핵심 가치로, 모듈 간의 의존성은 최소화하고 응집성은 최대화 함으로써

 

핵심적인 기능은 모두 가지면서도 가벼운 설계를 만드는 것이 목적이라 할 수 있다.

 

더 구체적으로는 도메인 모델 패턴이라고 하는 소프트웨어 추상화를 달성하기 위한 원칙과 패턴의 집합이라고 할 수도 있다.

 

그렇다면 도메인 도메인 모델 패턴이란 무엇일까?

 

Domain

 

도메인은 한 마디로 말하자면 현실세계 업무의 한 영역이라고 할 수 있다.

 

혹은 개발자가 애플리케이션으로 “해결하고자 하는 문제 영역”을 의미한다고 할 수도 있다.

 

조금 더 구체적으로 도메인은 '영역, 범위'의 뜻을 가지고 있으며 

 

프로그래밍의 경우엔 애플리케이션 내의 로직들이 관여하는 정보와 활동의 영역이라고 생각하면 편하다. 

 

예를 들어 배달 주문 서비스를 만들 때 회원을 등록하거나 삭제하는 작업은 "회원"과 관련된 작업들이고, 

 

따라서 "회원"이라는 도메인이 있다고 볼 수 있게 된다.

 

예를 들자면 위 그림은 전자 상거래 도메인의 하위 도메인을 나타내고 있다.

 

Transaction Script Pattern vs. Domain Model Pattern

 

두 패턴의 차이는 간단하게 비즈니스 로직이 위치하는 계층의 차이이다.

 

Transaction Script Pattern

 

먼저 트랜잭션 스크립트 패턴의 경우 서비스 계층의 Service 객체가 비즈니스 로직을 가지고 있다.

 

구체적으로 하나의 트랜잭션으로 구성된 로직을 하나의 함수 또는 하나의 스크립트에서 처리하는 구조라 할 수 있다.

 

즉 위 그림처럼 서비스 객체가 비즈니스 로직을 가지고 앱의 실행 흐름에 따라 도메인 객체를 이용한다.

 

이때 도메인 객체는 단지 정보의 덩어리 역할만 하게 된다.

 

은행의 계좌이체 서비스처럼 하나의 트랜잭션 안에서 모든 로직을 수행해야 할 때 주로 사용하며,

 

구현이 쉽고 모듈화에 따라 높은 효율을 낼 수 있다는 장점이 있다.

 

하지만 비즈니스 로직이 복잡해질수록 코드의 중복이 심해져 유지보수가 어려워진다는 단점이 존재하고,

 

이를 해결하기 위해 나온 것이 도메인 모델 패턴이다.

 

Domain Model Pattern

 

도메인 모델 패턴의 경우 이름을 따라 도메인 모델 계층의 Entity 클래스가 비즈니스 로직을 가지고 있다.

 

조금 더 직관적으로 말하자면 특정 대상과 대상의 행위가 함께 객체를 이루는 형태라고 할 수도 있다.

 

이 방식은 비즈니스 로직은 각각의 도메인이 처리하도록 하고 서비스 객체는 트랜잭션, 도메인 간 순서 보장만 하는 것이다.

 

즉 위 그림처럼 도메인 객체가 주도권을 갖고 서비스 객체를 컨트롤하게 된다.

 

이렇게 비즈니스 로직이 도메인에 가까워지면 당연하게도 서비스의 책임이 도메인으로 분산되어 서비스 객체는 단순해지며,

 

분산되어 명확한 책임을 가지게 된 도메인 객체 덕분에 유지보수와 테스트가 편리해진다.

 

이는 위에 적어둔 트랜잭션 스크립트 패턴의 단점을 정확하게 보완하면서도 객체지향적인 설계를 가능하게 한다.

 

단점은 하나의 도메인 모델을 구축하는데 시간이 많이 들어 초기 구현이 어렵다는 점이 있다.

 

Domain Driven Design, DDD

 

DDD는 결국 위에서 말한 대로 도메인을 중심에 놓고 도메인 모델 패턴을 목표로 앱을 설계해 나가는 방식이다.

 

즉, 애플리케이션의 구조를 도메인 간의 관계를 반영한 형태로 잡을 수 있다는 것인데,

 

도메인을 중심으로 애플리케이션의 구조를 하나씩 살펴보자.

 

Domain, Subdomain, Entity, VO, Aggregate

 

위에서도 한 번 예를 들었지만 그림을 다시 불러오자.

 

전자 상거래 시스템이라는 Domain에 Customer, Prodcut 등의 Subdomain이 속한 것을 볼 수 있다.

 

또한 Entity, VO는 Domain을 개념화한 Domain Object의 종류이며,

 

 

  • Entity

    • 식별자를 가짐
    • DB 테이블의 칼럼으로만 이루어진 클래스
    • 다른 클래스를 상속받거나 구현해선 안 됨
  • Value Object

    • 값(Value)을 담는 객체
    • 식별자 없음 → 값이 하나만 변해도 다른 객체가 됨 → 불변성을 가짐(Read-Only, no Setter Method)

과 같은 차이점을 지닌다.

 

계속해서 Aggregate는 이 도메인 객체(Entity, VO)를 묶어 만든 하나의 단위 또는 집합이라 할 수 있다.

 

서로 관련이 있는 Subdomain을 Aggregate로 묶은 것을 확인할 수 있다.

 

Bounded Context

 

Bounded Context는 이렇게 정의된 Aggregate를 포함하는 개념이라고 할 수도 있는데,

 

반드시 Aggregate보다 큰 범위라고 할 수는 없다.

 

그야말로 문맥(Context)에 따라 서브도메인을 구분한 개념이 Bounded Context인데, 예를 들면 아래와 같다.

 

여기서 문맥(Context)이란 직관적으로 작업 단위로 팀을 나누는 것과 비슷하다고 생각하면 된다.

 

조금 추상적으로는

 

  • Aggregate - Problem Space
  • Bounded Context - Solution Space

라고 볼 수도 있다. Aggregate에서 발생하는 업무를 Bounded Context에서 해결한다는 뜻이다.

 

또한 이상적으론 Aggregate와 Bounded Context는 1대 1로 대응되는 것이 권장된다.

 

이는 DDD의 목적이 도메인의 철저한 분리 및 강한 응집성(Loose Coupling, High Cohesion)을 바탕으로

 

역할과 책임을 명확히 하면서 변경과 확장에 유리한 설계를 하는 것이기 때문이다.

 

위의 예에선 Shipping Aggregate와 Product Aggregate는 각각 하나의 컨텍스트에 속하지만

 

나머지는 그렇지 않은 것을 볼 수 있다.

 

Ubiquitous Language

 

이렇게 문맥(Context)에 따라 영역을 나누면 같은 객체의 역할도 문맥에 따라 다른 의미를 갖게 되는데,

 

(예를 들면 영어의 Account는 '계정'이라는 뜻도 갖지만 '계좌'라는 뜻도 갖는다.)

 

이때 필요해지는 것이 유비쿼터스 언어(Ubiquitous Language)이다.

 

보편 언어라고 번역할 수도 있는 유비쿼터스 언어는 쉽게 말해 한 Context에서 쓰이는 언어를 말한다.

 

도메인 전문가, 아키텍트, 개발자 등 모두에게 공유되는 유비쿼터스 언어는

 

한 작업 단위(팀)에 속하는 모든 사람들이 하나의 뜻으로 받아들이고 소통하는 언어로서

 

회의록부터 도메인, 코드까지 사용되는 언어이다.

 

유비쿼터스 언어의 역할은 같은 단어를 다른 뜻으로, 혹은 다른 단어를 같은 뜻으로 사용하는 것을 막고

 

다른 작업 단위(Context)와 언어가 섞이는 것을 방지해준다.

 

즉, 각 컨텍스트는 서로 배타적인 유비쿼터스 언어를 갖는다.

 

바꿔 말하면 유비쿼터스 언어 자체가 Bounded Context의 경계를 정한다고 볼 수도 있다.

 

이를 위해 용어를 정의하고 사전을 만드는 것이 중요한데, 그 예는 아래와 같다.

 

한글 영문
회원 customer 회원을 관리하는 기준 테이터
회원 이름 name 회원의 이름
전화번호 phone 회원의 전화번호
결제 payment 회원의 결제내역
주소 address 회원의 주소

 

위와 같이 용어사전을 만들어 협업 시 오해의 여지를 최대한 줄일 수 있다.

 

Event Storming

 

이벤트 스토밍은 Event + Brain Storming의 합성어로 이벤트를 중심으로 모여 브레인스토밍을 한다는 뜻이다.

 

간단하게 이해관계자(서비스에 필요한 도메인 전문가와 개발자)가 모여 진행하는 워크샵이라고 보면 된다.

 

이름처럼 개발보다는 비즈니스 프로세스에 집중하는 이벤트 스토밍은 팀 구성원 전체의 프로젝트에 대한 이해도를 높이고

 

새로운 Domain, Aggregate, Bounded Context 등을 추출하는 목적을 갖는다.

 

또한 추출한 요소들로 대략적으로 처음 그림과 같은 도표를 구성해 작업의 방향을 가늠하기도 한다.

 

 

Summary

  • Domain Driven Design, DDD - 도메인을 중심에 놓고 앱을 설계해 나가는 방식
  • Domain - 현실세계 업무의 한 영역, 혹은 개발자가 애플리케이션으로 해결하고자 하는 문제 영역
  • Domain Model Pattern - 도메인 모델 계층의 Entity 클래스가 비즈니스 로직을 가지는 패턴
  • Aggregate - 하나의 단위로 취급할 수 있는, 도메인 객체의 집합
  • Bounded Context - Aggregate를 포함하는 작업 단위(팀), 혹은 Solution Space
  • Ubiquitous Language - 한 Context(작업 단위=팀)에 속하는 모든 사람들이 하나의 뜻으로 받아들이고 소통하는 언어
  • Event Storming - 이해관계자(도메인 전문가와 개발자)가 모여 진행하는 워크샵
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함