목록책/도메인 주도 개발 시작하기 (11)
효습
11.1 단일 모델의 단점조회 화면 특성상 조회 속도가 빠를수록 좋은데 여러 애그리거트의 데이터가 필요하면 구현 방법을 고민해야함이런 고민이 발생하는 이유는 시스템 상태를 변경할 때와 조회할 때 단일 도메인 모델을 사용하기 때문이다.객체 지향으로 도메인 모델을 구현할 때 주로 사용하는 ORM 기법은 도메인 상태 변경 기능을 구현하는 데는 적합하지만 주문 상세 조회 화면처럼 여러 애그리거트에서 데이터를 가져와 출력하는 기능을 구현하기에는 쉽지 않다.→ 이를 해결하는 방법은 상태 변경을 위한 모델과 조회를 위한 모델을 분리하는 것이다. 11.2 CQRS시스템이 제공하는 기술은 크게 상태를 변경하는 기능과 상태 정보를 조회하는 기능 , 두 가지이다.도메인 모델 관점에서 상태 변경 기능은 주로 한 애그리거트의 ..
10.1 시스템 간 강결합 문제 쇼핑몰에서 구매를 취소해서 환불해야하는 상황환불 기능을 실행하는 주체는 주문 도메인 엔티티도메인 객체나 응용 서비스에서 환불 기능을 구현할 수 있음보통 결제 시스템은 외부에 존재하므로 외부의 결제 시스템을 호출한다. 이때 발생할 수 있는 두 가지 문제외부 서비스(결제 시스템)이 정상이 아닐 경우 트랜잭션 처리는 어떻게 할지 애매하다.환불 기능을 실행하는 과정에서 익셉션이 발생하면 트랜잭션을 롤백? 아니면 일단 커밋?외부 서비스에서 익셉션일 발생하면 환불에 실패했으므로 주문 취소가 맞아보이나 일단 주문의 상태를 변경하고 나중에 환불만 다시 시도할 수도 있음환불을 처리하는 외부 시스템의 응답 시간이 길어지면 그만큼 대기 시간이 길어짐 → 외부 시스템의 영향을 받음+) 이 외에..
9.1 도메인 모델과 경계 처음 도메인 모델을 만들 때 빠지기 쉬운 함정이 도메인을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것이다. 논리적으로 같은 존재처럼 보이지만 하위 도메인에 따라 다른 용어를 사용하는 경우가 있다. 한 개의 모델로 모든 하위 도메인을 표현하려는 시도는 올바른 방법이 아니며 표현할 수도 없다. → 하위 도메인마다 모델을 만들어야 한다. 각 모델은 명시적으로 구분되는 경계를 가져서 섞이지 않도록해야 한다. 여러 하위 도메인의 모델이 섞이기 시작하면 모델의 의미가 약해질 수 있다. 여러 도메인의 모델이 서로 얽히기 때문에 각 하위 도메인별로 다르게 발전하는 요구사항을 모델에 반영하기 어려워진다. 모델은 특정한 컨텍스트(문맥) 하에서 완전한 의미를 갖는다. 이렇게 구분되는 경계..
8.1 애그리거트와 트랜잭션 운영자가 배송 상태를 변경할 때, 사용자가 배송지 주소를 수정하는 경우가 발생할 수 있다. 트랜잭션마다 리포지터리는 새로운 애그리거트 객체를 생성하므로 운영자 스레드와 고객 스레드는 같은 주문 애그리거트를 나타내는 다른 객체이다. 따라서 운영자 스레드는 주문 애그리거트 객체를 배송 상태로 변경하더라도 고객 스레드가 사용하는 객체에는 영향을 주지 않는다. 그런데 각각의 트랜잭션이 커밋될 경우, 운영자가 배송 상태를 변경하는 중에 고객에 배송지를 변경했으므로 이를 반영하지 못한다. 이렇게 되면 상품이 엉뚱한 곳으로 배송될 수 있고 애그리거트의 일관성이 깨진다. 이를 방지하기 위해서는 운영자가 배송 상태를 변경하는 동안 고객은 주문 애그리거트를 수정하지 못하도록 막는다. 운영자가 ..
7.1 여러 애그리거트가 필요한 기능 도메인 영역의 코드를 작성하다보면, 한 애그리거트로 기능을 구현할 수 없을 때가 있다. 결제 계산 로직을 예로 들면, 상품 애그리거트 : 구매하는 상품의 가격과 배송비 관련 정보가 필요함 주문 애그리거트 : 상품의 구매 개수 정보가 필요 할인 쿠폰 애그리거트: 할인 쿠폰의 적용 여부 , 할인 쿠폰 사용에 관련한 제약 여부 회원 : 회원에 따른 할인 여부 이 상황에서 결제 금액을 계산하는 애그리거트는 어떤 애그리거트일까? → 생각해볼 수 있는 방법은 주문 애그리거트에 필요한 데이터를 모두 가지도록 한 뒤, 할인 금액 계산 책임을 주문 애그리거트에 할당하는 것이다. 그렇다면 결제 금액 계산 로직이 주문 애그리거트의 책임이 맞느냐? 특별 행사로 한 달간 2% 추가 할인이 ..
6.1 표현 영역과 응용 영역 도메인 영역을 잘 구현하지 않으면 사용자의 요구를 충족하는 제대로 된 소프트웨어를 만들지 못한다. 도메인이 제 기능을 하려면 사용자와 도메인을 연결해 주는 매개체가 필요하다. 표현 영역과 응용 영역이 이에 해당한다. 표현 영역은 사용자의 요청을 해석한다. 요청을 받은 표현 영역은 URI , 요청 파라미터,쿠키,헤더 등을 이용해서 사용자가 실행하고 싶은 기능을 판별하고 그 기능을 제공하는 응용 서비스를 실행한다. 실제 사용자가 원하는 기능을 제공하는 것은 응용 영역에 위치한 서비스다. 응용 서비스는 기능을 실행하는 데 필요한 값을 메서드 인자로 받고 실행 결과를 리턴한다. 응용 서비스의 메서드가 요구하는 파라미터와 표현 영역이 사용자로부터 전달받은 데이터는 형식이 일치하지 않..
5.1 시작에 앞서 CQRS는 명령(Command) 모델과 조회(Query)모델을 분리하는 패턴이다. 명령 모델은 상태를 변경하는 기능을 구현할 때 사용한다. 조회 모델은 데이터를 조회하는 기능을 구현할 때 사용한다. 도메인 모델은 주로 명령 모델로 사용된다. 반면 5장의 정렬,페이징,검색 조건 지정과 같은 기능은 조회 기능에서 사용된다. 5.2 검색을 위한 스펙 검색 조건이 고정되어 있고 단순하면 특정 조건으로 조회하는 기능을 만들면 된다. 다양한 검색 조건을 조합해야할 때 , 필요한 조합마다 find 메서드를 정의할 수도 있지만 조합이 증가할수록 정의해야할 find 메서드도 함께 증가한다. → 검색 조건을 다양한게 조합해야 할 때 사용할 수 있는 것이 스펙(Spectations)다. 스펙은 애그리거트..
4.1 JPA 를 이용한 리포지터리 구현 애그리거트를 어떤 저장소에 저장하느냐에 따라 리포지터리를 구현하는 방법이 다르다. 데이터 보관소로 RDBMS를 사용할 때, 객체 기반의 도메인 모델과 관계형 데이터 모델 간의 매핑을 처리하는 기술로 ORM 만한 것이 없다. 4.1.1 모듈 위치 리포지터리 인터페이스는 애그리거트와 같이 도메인 영역에 속하고, 리포지터리를 구현한 클래스는 인프라스트럭처에 속한다. 팀 표준에 따라 리포지터리 구현 클래스를 domain.impl과 같은 패키지에 위치시킬 수도 있는데 이것은 리포지터리 인터페이스와 구현체를 분리하기 위한 타협안 같은 것이지 좋은 설계 원칙을 따르는 것은 아니다. 가능하면 리포지터리 구현 클래스를 인프라스트럭처 영역에 위치시켜서 인프라스트럭처에 대한 의존을 ..
3.1 애그리거트 백 개 이상의 테이블을 한 장의 ERD에 모두 표시하면 개별 테이블 간의 관계를 파악하느라 큰 틀에서 데이터 구조를 이해하는 데 어려움을 겪게 되는 것처럼, 도메인 객체 모델이 복잡해지면 개별 구성요소 위주로 모델을 이해하게 되고 전반적인 구조나 큰 수준에서 도메인 간의 관계를 파악하기 어려워진다. 주요 도메인 요소 간의 관계를 파악하기 어렵다는 것은 코드를 변경하고 확장하는 것이 어려워진다는 것을 의미한다. 복잡한 도메인을 이해하고 관리하기 쉬운 단위로 만들려면 상위 수준에서 모델을 조망할 수 있는 방법이 필요한데, 그 방법이 애그리거트다 애그리거트는 모델을 이해하는 데 도움을 줄 뿐만 아니라 일관성을 관리하는 기준도 된다. 애그리거트를 사용하면 복잡한 도메인을 단순한 구조로 만들어주..
2.1 네 개의 영역 표현 영역은 사용자의 요청을 받아 응용 영역에 전달하고 응용 영역의 처리 결과를 다시 사용자에게 보여주는 역할을 한다 웹 애플리케이션에서 표현 영역의 사용자는 웹 브라우저를 사용하는 사람일 수도 있고 , 외부 시스템일 수도 있다 응용 서비스는 로직을 직접 수행하기보다는 도메인 모델에 로직 수행을 위임한다 도메인 영역은 도메인 모델을 구현하며 도메인 모델은 핵심 로직을 구현한다 인프라스트럭처 영역은 구현 기술에 대한 것을 다룬다 논리적인 개념을 표현하기보다는 실제 구현을 다룬다 도메인 영역, 응용 영역,표현 영역은 구현 기술을 사용한 코드를 직접 만들지 않는다. 대신 인프라스트럭처 영역에서 제공하는 기능을 사용해서 필요한 기능을 개발한다 2.2 계층 구조 아키텍처 전체적인 아키텍처는 ..