밤 늦게까지 여는 카페

도메인 주도 개발 시작하기 - 2. 아키텍처 개요 본문

리뷰

도메인 주도 개발 시작하기 - 2. 아키텍처 개요

Jㅐ둥이 2022. 11. 25. 08:32
반응형

안녕하세요! 오늘은 도메인 주도 개발 시작하기의 두 번째번째 챕터인 아키텍처 개요를 공부하려고 합니다.

책을 읽으면서 내용의 흐름이 아쉽다고 느끼고 있습니다.
그렇지만 두 번째 챕터에서 이런 평가를 내리는 것이 섣부른 판단일 수 있죠!

내용 살펴보겠습니다 :)


꿀팁 요약

  • DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출해야 한다.
  • DIP가 항상 옳은 것은 아니다.
  • 도메인 모델, 패키지 모두 크기가 너무 커지면 다시 모듈화 시키자.

2.1 네 개의 영역

혹시 프로젝트를 시작하면서 설계 단계에 들어가면 어떤 방식으로 구조를 그려나가시나요?
소프트웨어를 설계할 때 "표현", "응용", "도메인", "인프라스트럭처" 4개의 영역으로 나누는 것은 전형적인 설계 방식입니다.

각 영역에 대해서 간단히 짚고 넘어가보겠습니다.

표현 영역

표현 영역은 사용자의 요청을 받아 응용 영역에 전달하는 역할을 합니다.
사용자로부터 받은 HTTP 요청을 응용 영역으로 전달하고, 응용 영역의 처리 결과를 다시 사용자에게 전달하죠.

  • 그 유명한 MVC 패턴이 표현 영역을 위한 패턴에 해당합니다.

사용자와 직접적으로 소통하는 영역이다보니 정말 중요한 영역입니다.

응용 영역

응용 영역은 표현 영역으로부터 전달받은 요청을 처리하기 위해서 도메인 모델의 로직을 사용합니다.

도메인 모델들을 조립하여 사용자에게 필요한 기능을 제공하니 표현 영역 못지 않게 중요합니다.

도메인 영역

도메인 영역은 도메인 모델을 구현합니다. 소프트웨어의 도메인들을 구현하는 영역입니다.

도메인 영역의 설계가 불안정하면 소프트웨어의 중심이 흔들릴 수 있어서 정말 중요한 영역이죠.

인프라스트럭처 영역

인프라스트러처 영역은 사용한 스택들을 직접적으로 다루는 영역입니다.
어떤 데이터베이스를 사용했는지, 어떤 메시징 서비스를 사용했는지 등 실질적인 기능 구현 및 연동을 담당하고 있습니다.

실제 구현을 다루는 영역이다보니 소프트웨어의 근간을 지탱하고 있는 영역입니다.


아뿔싸, 중요하지 않은 영역이 없네요!ㅋㅋㅋㅋㅋㅋ

2.2 계층 구조 아키텍처

2.1에서 나눈 4가지 영역을 어떻게 구성하셨나요?
아마 많은 분들이 표현, 응용, 도메인, 인프라스트럭처 순의 계층 구조로 구성하셨을 거에요.

이렇게 계층 구조를 적용하셨다면 상위 계층은 하위 계층에 의존하지만 하위 계층은 상위 계층에 의존하지 않도록 구현을 하게 될 거에요.

여기서 싸한 느낌을 받지 않으셨나요?
이렇게 되면 상위 계층을 테스트, 작동시키기 위해서는 모든 하위 계층이 구현되어야 합니다.
(단위 테스트라고 작성했는데 완료까지 분단위의 시간이 소요될 수 있습니다...)

이 문제를 어떻게 해결할 수 있을까요? 답은 바로...

2.3 DIP

DIP! 의존성 역전 원칙으로 하위 계층이 상위 계층에 의존성을 가지도록 하는 것입니다.
추상화 된 인터페이스를 사용하여 구현에 대한 의존성을 분리시킵니다.
(디자인 패턴 포스팅들에서 많이 사용하고 있습니다ㅎㅎ)

DIP를 통해서 상위 계층이 하위 계층에 변경에도 강인해지며 테스트도 더욱 쉽고 빠르게 진행할 수 있게 됩니다.
mock 객체를 이용하여 테스트를 진행할 수 있거든요!

꿀팁

1. DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출해야 합니다!

단순히 추상화된 인터페이스를 추출했다고 DIP를 한 것이 아닌
고수준 모듈 관점에서의 인터페이스를 만들어 저수준 모듈이 이를 따르는 것이 중요합니다.

2. DIP가 항상 옳은 것은 아닙니다!

사용하는 구현 기술에 따라서 어느 정도는 구현 기술(프레임워크, 라이브러리 등)에 의존적인 코드를 도메인에 포함시키는 것이 효과적일 때도 있습니다.
DIP의 이점과 구현 기술의 이점을 취사 선택할 수 있도록 고민해봅시다.

2.4 도메인 영역의 주요 구성요소

그래도 DDD 공부인데 도메인 영역에 대해서 조금 더 다뤄야겠죠?
도메인 영역은 다음 구성요소들로 이루어져 있습니다.

  • 엔티티
  • 밸류
  • 애그리거트
  • 리포지터리
  • 도메인 서비스

각각에 대해서 조금 더 정리해보겠습니다.

엔티티, 밸류

도메인 주도 개발 시작하기 - 1. 도메인 모델 시작하기 에서 엔티티, 밸류에 대해 이미 다뤘으니
이번에는 새로운 내용을 중심으로 얘기해볼거에요.

많은 분들이 도메인 모델의 엔티티와 DB 엔티티를 많이 헷갈려하는데 그 차이점에 대해서 얘기해보겠습니다.

1. 도메인 모델의 엔티티는 데이터와 함께 도메인 기능을 제공합니다.

도메인 모델은 단순한 데이터 구조가 아닙니다. 도메인 관점에서 기능을 구현하고, 기능 구현을 캡슐화하고 있습니다.

2. 도메인 모델의 엔티티는 밸류 타입을 이용하여 두 개 이상의 데이터가 개념적으로 하나인 경우에도 쉽게 표현할 수 있습니다.

DB 엔티티로는 도메인 모델의 엔티티 마냥 의미를 전달하기 어려운 경우가 많습니다...

애그리거트

혹시 개발하고 있는 모듈 하나의 크기가 너무 커지면 어떻게 하시나요?
저는 큰 모듈 1개를 쪼개서 추상화 작업을 거쳐 적당한 크기의 모듈로 나눕니다.

도메인 모델에도 이와 비슷한 개념으로 애그리거트가 있습니다.
도메인이 클수록 도메인 모델도 커지고, 이에 따라 아주 많은 엔티티와 밸류가 생길 것입니다.

그러다가 엔티티와 밸류가 너무 많아져 개발자가 파악하기 어려워지면 어떻게 해야 할까요?
관련된 엔티티, 밸류 타입을 묶어서 조금 더 간단한 구조로 이해하는 방법이 있습니다.

바로 이 묶인 엔티티, 밸류 타입들이 애그리거트입니다.

애그리거트의 중요성

애그리거트를 어떻게 구성했느냐에 따라 구현이 복잡해지기도 하고, 트랜잭션 범위가 달라지기도 합니다.
또한 선택한 구현 기술에 따라서 애그리거트 구현에 제약이 생길수도 있기 때문에 신중함이 요구됩니다.

리포지터리

리포지터리는 도메인 객체를 영속화하는데 필요한 기능을 추상화한 것입니다.

2.5 요청 처리 흐름

요청 흐름을 간단하게 설명하는 부분으로 넘어가겠습니다 :)

2.6 인프라스트럭처에 대한 편견

인프라스트럭처 영역은 구현 기술을 직접적으로 사용하는 영역으로
일반적으로 이 영역의 의존성을 제거해야 하는데 집중해야 하죠.

하지만! "항상" 이란 것은 없잖아요?
2.3에서도 언급했지만 항상 인프라스트럭체에 대한 의존을 없앨 필요는 없습니다.

확장성, 테스트 용이성뿐만 아니라 구현의 편리함도 고려해야 하는데
의존성 제거에만 집중하다보면 바퀴를 다시 만드는 고생과 이를 유지보수해야 하는 비용이 발생합니다.

2.7 모듈 구성 꿀팁

DDD로 개발할 때, 패키지 혹은 디렉토리 아키텍처를 어떻게 잡는지 알려드립니다.

1차적으로 영역별로 모듈이 위치할 패키지를 구성합니다.

그 다음 도메인 모듈은 도메인에 속한 애그리거트를 기준을 패키지를 구성합니다.
도메인이 크면 하위 도메인으로 나누고, 각 하위 도메인마다 별도 패키지를 구성하면 적절한 패키지 크기를 유지할 수 있습니다.

모듈 구조를 얼마나 세분화해야 하는지에 대해 정해진 것은 없지만 한 패키지에 너무 많은 코드가 작성되어 읽기 어려운 정도만 아니면 됩니다.
저자는 한 패키지 내부의 타입 개수가 10~15개를 넘어가면 패키지 분리를 시도한다고 합니다.

반응형