Leeyebin의 블로그

2. 아키텍처 개요 본문

공부 기록실/도메인 주도 개발 시작하기

2. 아키텍처 개요

안되면될때까지 2023. 3. 15. 20:24

2.1 네 개의 영역

 

1. 표현 영역

- 사용자의 요청을 받아 응용 영역에 전달한다.

2. 응용 영역

- 기능을 구현하기 위해 도메인 영역의 도메인 모델을 사용한다.

- 로직을 직접 수행하기보다는 도메인 모델에 로직 수행을 위임한다.

3. 도메인 영역

-도메인 모델을 구현한다.

4. 인프라 스트럭처

-구현 기술에 대한 것(RDBMS / MQ, SMTP...)

-논리적인 개념을 표현하기보다는 실제 구현을 다룬다.

 

2.2 계층 구조 아키텍처

표현 계층은 응용 계층에 의존하고 응용 계층이 도메인 계층에 의존한다.

반대 방향으로는 의존 하지는 않는다.

엄격하게는 상위 계층은 바로 아래 계층에만 의존을 가져야 하지만 구현의 편리함을 위해 유연하게 적용할 수 있다.

응용 계층 -> 도메인 계층 / 응용 계층 -> 인프라스트럭처 계층에 의존하게 할 수 있다.

 

인프라스트럭처에 의존하면 생기는 문제 두 가지

-테스트 어려움

-기능 확장의 어려움

 

2.3 DIP(Dependency Inversion Principle)

고수준 모듈과 저수준 모듈

가격 할인 계산 예제

고수준 모듈

-의미 있는 단일 기능을 제공하는 모듈

-그림에서는 '가격 할인 계산'

 

저수준 모듈

-'가격 할인 계산'을 위해서는 고객 정보를 구하고 룰을 실행해야하는 두 가지 하위 기능이 필요하다.

 

고수준 모듈이 제대로 동작하려면 저수준 모듈을 사용해야한다.(고수준 모듈이 저수준 모듈에 의존하게 됨)

But, 구현 변경과 테스트가 어렵다는 문제가 발생한다.

->DIP는 저수준 모듈이 고수준 모듈에 의존하도록 바꾼다.

->인터페이스 사용

 

 

'가격 할인 계산' 예시

 

DIP를 적용하면 인프라스터럭처 영역에 의존할 때 발생했던 두 가지 문제를 해결할 수 있다.

 

2.3.1 DIP 주의사항

DIP의 핵심

-고수준 모듈이 저수준 모듈에 의존하지 않도록 하기 위함이다.

-DIP를 적용한 결과 구조만 보고 저수준 모듈에서 인터페이스를 추출하는 경우가 있는데 잘못된 구조이다.

-DIP 적용시 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출해야한다.

 

 

2.3.2 DIP와 아키텍처

 

 

인프라 스트럭처에 위치한 클래스가 도메인이나 응용 영역에 정의한 인터페이스를 상속받아 구현하는 구조가 된다.

그래서 도메인과 응용 영역에 대한 영향을 주지 않거나 최소화하면서 구현 기술을 변경하는 것이 가능하다.

 

DIP를 항상 적용할 필요는 없다.
구현 기술에 의존적인 코드를 도메인에 일부 포함하는 게 효과적일 때도 있기때문에 DIP의 이점을 얻는 수준에서 적용 범위를 검토하는 것이 좋다.

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

요소 설명
엔티티 고유의 식별자를 갖는 객체로 자신의 라이프 사이클을 갖는다.
밸류 고유의 식별자를 갖지 않는 객체로 주로 개념적으로 하나인 값을 표현할 때 사용된다.
애그리거트 연관된 엔티티와 밸류 객체를 개념적으로 하나로 묶은 것이다.
리포지터리 도메인 모델의 영속성을 처리한다.
도메인 서비스 특정 엔티티에 속하지 않은 도메인 로직을 제공한다.

 

2.4.1 엔티티와 밸류

DB엔티티 VS 도메인 모델의 엔티티

DB엔티티

-개별 데이터만 드러남

 

도메인 모델의 엔티티

-데이터와 함께 기능을 제공하는 객체

-도메인 관점에서 기능을 구현하고 캡슐화를 통해 데이터가 임의로 변경되는 것을 막는다.

-두 개 이상의 데이터가 개념적으로 하나인 경우 밸류 타입을 이용해서 표현할 수 있다.

 

2.4.2 애그리거트

엔티티와 밸류 개수가 많아질수록 모델은 점점 더 복잡해진다.

 

 

애그리거트

  • 관련 객체를 하나로 묶은 군집
  • 예시
    • 주문이라는 도메인 개념은 '주문/배송지 정보/주문자/주문 목록/총 결제 금액의 하위모델로 구성됨
    • 하위 개념을 표현한 모델을 하나로 묶어서 '주문'이라는 상위 개념으로 표현 할 수 있다.
  • 도메인 모델에서 전체 구조를 이해하는데 도움이 된다.
  • 루트 엔티티
    • 군집에 속한 객체를 관리하는 루트 엔티티를 갖는다.
    • 애그리거트 루트가 제공하는 기능을 실행한다.
    • 애그리거트 루트를 통해서 간접적으로 애그리거트 내의 다른 엔티티나 밸류 객체에 접근할 수 있다.
애그리거트 구현시 고려할 것이 많다.
어떻게 구성했느냐에 따라 구현이 복잡하기도 하고 트랜잭션 범위가 달라지기도 한다.
선택한 구현 기술에 따라 애그리거트 구현에 제약이 생기기도 한다.

2.4.3 리포지터리

물리적인 저장소에 도메인 객체를 보관해야 한다.(RDBMS, NoSQL, 로컬 등)

구현을 위한 도메인 모델이다.

 

응용  서비스와 리포지터리는 밀접한 연관이 있다.

-응용 서비스는 필요한 도메인 객체를 구하거나 저장할 때 리포지터리를 사용한다.

-응용 서비스는 트랜잭션을 관리하는데 트랜잭션 처리는 리포지터리 구현 기술의 영향을 받는다.

 

리포지터리는 응용 서비스가 필요하는 메서드를 제공한다.

-애그리거트를 저장하는 메서드

-애그리거트 루트 식별자로 애그리거트를 조회하는 메서드

 

2.5 요청 처리 흐름

표현 영역

-사용자가 전송한 데이터를 응용 서비스가 요구하는 형식으로 변환해서 전달한다.

 

응용 서비스

-도메인 모델을 이용해서 기능을 구현한다.

-기능 구현에 필요한 도메인 객체를 리포지터리에서 가져와 실행하거나 신규 도메인 객체를 생성해서 리포지터리에 저장한다.

-도메인의 상태를 변경하는 경우에는 변경 상태가 올바르게 반영되도록 트랜잭션을 관리해야 한다.

 

2.6 인프라스트럭처 개요

인프라스트럭처

-표현 영역, 응용 영역, 도메인 영역을 지원한다.

-도메인 객체의 영속성 처리, 트랜잭션, SMTP/REST 클라이언트 등 프레임워크, 구현 기술, 보조 기능을 지원한다.

-DIP를 이용해서 인프라스트럭처의 기능을 직접 사용하는 것보다 도메인/응용 영역에 정의한 인터페이스를 인프라스트럭처 영역에서 구현하는게 좋다.(시스템의 유연함과 테스트를 위해)

-그러나 응용/도메인 영역이 인프라스트럭처에 의한 의존을 완전히 갖지 않도록 시도하는 것은 자칙 수현을 더 복잡하고 여렵게 만들 수 있다.(예 : 스프링의 @Transactional)

 

 

 

 

 

 

 

 

 

 

Comments