이 글은 '도메인 주도 개발 시작하기'라는 책을 읽으며 공부하고 정리한 내용이다.
제 2장, 아키텍처 개요에 대하여 다룬다.
1장에서 잠깐 짧게 알아보았던 아키텍처의 구성 요소에 대해 깊게 알아보자.
'표현', '응용', '도메인', '인프라스트럭처'는 아키텍처를 설계할 때 출현하는 대표적인 네 가지 영역이다.
이 중, 표현 영역은 사용자의 요청을 받아 응용 영역에 전달하고,
응용 영역의 처리 결과를 다시 사용자에게 보여주는 역할을 한다.
사용자는 웹 브라우저를 사용하는 사용자일 수도, REST API를 호출하는 외부 시스템일 수도 있다.
웹 애플리케이션의 표현 영역은 HTTP 요청의 형식을 변환하여
응용 영역에 전달하고, 응답을 HTTP 응답으로 변환해 전송하는 식으로 이루어진다.
인프라스트럭처 외의 영역은 구현 기술을 사용한 코드를 직접 만들지 않고,
인프라스트럭처 영역에서 제공하는 기능을 사용해 필요한 기능을 개발한다.
다음은 계층 구조 아키텍처에 대해 알아보자.
네 영역을 구성할 때, 표현/응용 영역은 도메인 영역을,
도메인 영역은 이프라스트럭쳐 영역을 사용하므로 계층 구조를 적용하기 적당해보인다.
도메인에 복잡도에 따라 응용과 도메인을 분리하거나 합치기도 한다.
계층 구조는 상위 계층에서 하위 계층으로의 의존만 존재한다.
그러나 때때로 구현의 편리함을 위해서는 유연하게 적용할 때도 있다.
이러한 계층적 구조는 코드를 독립적으로 테스트하기가 어렵다는 점이며,
구현 방식을 변경하거나 추가하기 어렵다는 특징이 있다.
DIP란 뭘까? 딥??디비디비딥?? DBDB DIP? 데이터베이스? 엌ㅋㅋㅋ ㅈㅅ
DIP는 Dependency Inversion Principle, 의존관계 역전 원칙을 말한다.
이는 말그대로 저수준 모듈이 고수준 모듈을 의존하게 하는 방법이다.
고수준 모듈이 제대로 동작하려면 저수준 모듈을 사용해야 하는데,
위에서 방금 말한 것처럼 구현 변경과 테스트가 어렵다는 문제가 발생한다.
이를 해결하기 위해 반대로 의존하도록 바꾸는 기법이 DIP이다.
그런데 이게 가능한가? 어떻게 구현할 수 있을까?
추상화한 인터페이스를 통해 구현하면, 의존하는 코드가 없고
무언가를 적용한다는 사실만 알 뿐이다. 따라서 무언가를 구현한 클래스는
인터페이스를 상속받아 구현한다.
인터페이스는 의미가 있는 기능들을 제공하기에 고수준,
구현체는 인터페이스를 상속받아 구현하기에 저수준 모듈이 된다.
그렇게 되면 저수준 모듈 관련 코드를 이해할 필요가 없게 된다.
따라서 이렇게 반대로 의존하면 인프라스트럭처 영역에 의존할 때 발생했던
두 가지의 문제를 해소할 수 있다.
DIP를 잘못 생각하면 인터페이스와 클래스를 분리한다! 라고만 생각할 수 있다.
핵심은 의존에 있기에, 저수준 모듈에서 인터페이스를 추출하는 등의 실수를 해서는 안된다.
도메인 영역의 주요 구성요소에 대해 알아보자.
구성요소는 엔티티, 밸류, 애그리거트, 리포지터리, 도메인 서비스
총 5개가 있다.
고유의 식별자를 가지는 객체로, 자신의 라이프 사이클을 가진다.
도메인의 고유한 개념을 표현하며, 모델의 데이터와 그에 관련된 기능을 함께 제공한다.
고유의 식별자를 갖지 않으며, 개념적으로 하나의 값을 표현할 때 사용한다.
다른 밸류 타입의 속성으로도 사용할 수 있다.
연관된 엔티티와 밸류 객체를 개념적으로 하나로 묶은 것이다.
예를 들면 Order Entity, OrderLine Value, Orderer Value를
'주문' 하나로 묶은 것.
도메인 모델의 영속성을 처리한다.
DB에 객체를 로딩하거나 저장하는 기능을 제공한다.
특정 엔티티에 속하지 않은 도메인 로직을 제공한다.
사실 공부를 하면서 가장 모호했던 개념이기도 한데,
엔티티는 도메인 기능을 함께 제공한다는 차이점이 있다.
데이터 뿐만 아니라, 그 데이터를 파싱하기 위한 기능도 제공한다.
도메인이 커질수록, 개발할 도메인 모델도 커져 엔티티와 밸류가 많아진다.
이들이 많을 수록 모델이 점점 복잡해지기에, 이를 묶기 위해 애그리거트가 사용된다.
애그리거트를 한마디로 표기하면 관련 객체를 하나로 묶은 군집이다.
이를 사용하면 관련 객체를 묶어 군집 단위로 모델을 볼 수 있다.
그럼 이제 이러한 구성요소들을 알아보았으니, 이 구성요소들을 처리하는
요청 처리 흐름에 대해 짧게 간단한 사진을 통해 알아보자.
앞에서 말했던 것처럼, 표현 영역에서 사용자가 전송한 데이터를 검사하고,
응용 영역에 맞게 전달 후 다시 받아 데이터를 변환해 응답하는 형식으로 이루어진다.
인프라스트럭처는 표현, 응용, 도메인 영역을 지원한다.
이를 바로 사용하는 것보다, 인터페이스를 해당 영역에서 구현한 다음
그 인터페이스를 상속받아 구현하는 것이 더욱 시스템을 부드럽게 해준다.
위의 사진처럼, 영역 별로 나누어 모듈을 구성할 수 있다.
도메인이 크면, 하위 도메인으로 나눠 각 하위 도메인마다 패키지를 구성할 수 있다.