2장 아키텍처 개요
생성일: 2024년 1월 29일 오후 10:32
아키텍처
웹브라우저에서 요청(HTTP)→표현영역에서 요청을 가공 후 응용영역에 전달 → 응용영역이 처리 결과를 표현영역에 전달 →표현영역이 응답결과를 가공 후 사용자(웹브라우저)에게 보여줌
- 표현영역은 HTTP요청을 변환 → 응용영역에 전달 , 응용영역의 응답을 HTTP응답으로 변환→웹 브라우저에 전송
- ex) HTTP 파라미터를 객체타입으로 변환 , 응용영역의 결과를 JSON형식으로 변환
- 응용영역은 제공해야할 기능을 직접 구현 X, 도메인 모델에 로직 수행을 위임
- ex) 주문 취소 로직을 직접 구현 X, Order 객체에 취소 처리를 위임.
- 도메인 영역은 도메인 모델 구현과 핵심 로직 구현
- ex) ‘배송지 변경’, ‘결제완료’, ‘주문 총액 계산’
- 인프라 스트럭처 영역은 구현 기술을 다룸.
- ex) RDBMS 연동, 메시징 큐에 메시지 전송, SMTP 를 이용한 발송기능 구현
DIP
- 계층 구조는 상위 계층에서 하위 계층으로의 의존만 존재 (응용계층이 도메인 계층을 의존)
- 계층 구조를 유연하게 적용해서 (그림 2) 응용→ 도메인, 응용→ 인프라 스트럭처 의존하기도함.
→ 나머지 계층이 구현 기술을 다루는 인프라스트럭처 계층에 종속
ex) 룰엔진 Drools 를 사용하는 가격 계산 예제
문제점
- 테스트가 어려움
- 구현변경의 어려움
public class CalculateDiscountService {
private DroolsRuleEngine ruleEngine;
public CalculateDiscountService() {
ruleEngine = new DroolsRuleEngine();
}
public Money calculateDiscount(OrderLine orderLines, String customerId) {
Customer customer = findCusotmer(customerId);
//==== Drools에 의존
MutableMoney money = new MutableMoney(0); //룰 적용 결괏값 보곤하기 위해 추가한 타입
List<?> facts = Arrays.asList(customer, money);
facts.addAll(orderLines);
ruleEngine.evalute("discountCalculation", facts); //"dis~ " 는 Drools의 세션 이름
//=== Drools에 의존
return money.toImmutableMoney();
}
}
→ DIP로 해결
- 고수준→ 저수준 의존에서 고수준 ←저수준 의존으로 바꿈
- how? 추상화한 인터페이스
- 고수준 모듈이 기능이 구현된 클래스를 의존하던 것을 인터페이스를 의존하게 하고 바꾸고,기능 구현을 인터페이스를 상속받는 클래스에서 함.
- 고수준 모듈이 저수준 모듈을 사용할 때 저수준 모듈에 의존해야하는데, 반대로 저수준 모듈이고수준 모듈에의존한다해서 DIP라고 함 (Dependency inversion principle)
위 1,2의 문제 해결
- 테스트의 어려움ex) Mock 프레임 워크 : Mockito
- → 의존하는 것이 클래스에서 인터페이스에서 바뀌었으므로,
구현클래스가 없어도 테스트 대역 객체를 사용해 거의 모든 기능 테스트 가능 - 구현 변경의 어려움→ 구현 객체를 생성하는 코드만 변경
// 사용할 저수준 객체 생성 RuleDiscounter ruleDiscounter = new DroolsRuleDiscounter(); // 구현 하는 객체를 바꾸기만 하면 됨 RuleDiscounter ruleDiscounter = new SimpleRuleDiscounter(); //구현 객체를 의존주입을 통해 전달 받음. 수정 필요없음. //구현 기술을 변경해도 고수준 모듈을 (CalculateDiscountService)를 수정할 필요 없음 CalculateDiscountService disService = new CalculateDiscountService(ruleDiscounter);
- → 구현을 추상화한 인테페이스에 의존하므로 구현객체를 의존주입을 이용해 전달 받음
⇒ DIP를 적용하면 도메인 영역과 응용영역에 영향을 최소화해 구현 기술을 변경할 수 있지만 무조건으로 적용하지 말고 DIP의 이점을 얻는 수준에서 적용 범위를 검토
ex) @Transactional 을 이용하면 스프링에 대한 의존은 있지만 다양한 이점이 존재.
도메인 영역의 주요 구성요소
- 엔티티 : 고유의 식별자를 갖음. Order, Member, Product 와 같이 고유한 개념을 표현하고 관련된 기능을 제공
- 밸류 : 식별자를 가지지 않음 개념적으로 하나의 값을 표현. ex) Money, Address
- 애그리거트 : 개념적으로 연관된 엔티티와 벨류를 묶음 ex) ‘주문’ 에그리거트
- 리포지터리 : 도메인 모델의 영속성을 처리. DBMS 테이블에서 엔티티 객체를 로딩,저장
- 도메인 서비스 : 특정한 엔티티에 속하지 않은 도메인 로직 제공. 여러 엔티티와 밸류를 빌요로 할때 도메인 서비스에서 로직을 구현.
ex) 할인 금액 계산.
사진
'책 > 도메인 주도 개발 시작하기' 카테고리의 다른 글
Chapter 10. 이벤트 (0) | 2025.03.17 |
---|---|
Chapter 8. 애그리거트와 트랜잭션 (0) | 2025.03.17 |
[도메인 주도 개발 시작하기] Chapter 6. 응용서비스와 표현 영역 (0) | 2025.03.17 |
[도메인 주도 개발 시작하기] Chapter 1. 도메인 모델 시작하기 (0) | 2025.03.17 |
[도메인 주도 개발 시작하기] Chapter 4. 리포지터리와 모델 구현 (0) | 2025.03.17 |