1.1 도메인이란?
온라인 서점을 이용할 때 검색을 통해 책 정보를 확인하고 목차와 서평을 살펴보며 책을 선택합니다. 장바구니에 담거나 쿠폰을 찾아 싸게 구매하며, 결제는 간편 결제 서비스나 외부 포인트를 이용합니다. 배송 추적 기능을 사용하여 언제 책을 받을 수 있는지 확인합니다.
개발자의 관점에서 온라인 서점 소프트웨어는 상품 조회, 구매, 결제, 배송 추적 등의 기능을 제공해야 하는 도메인으로 분류됩니다. 온라인 서점 도메인은 여러 하위 도메인으로 구성될 수 있습니다.
하위 도메인은 상호 연동되어 완전한 기능을 제공하며, 일부 기능은 외부 업체의 시스템을 활용할 수 있습니다. 예를 들어, 배송 도메인은 외부 배송 업체의 시스템을 사용하고 배송 추적 정보만 연동할 수 있습니다. 결제 시스템도 결제 대행업체를 활용하는 경우가 많습니다.
하위 도메인의 구성은 상황에 따라 다르며, 기업의 규모나 판매하는 상품의 특성에 따라 결정됩니다. 소규모 업체는 수작업으로 정산을 처리할 수도 있고, 대형 장비를 판매하는 기업은 단순한 주문 처리와 카탈로그 제공만으로 충분할 수 있습니다. 의류나 액세서리를 판매하는 업체는 카탈로그, 리뷰, 주문, 결제, 배송, 회원 기능 등이 필요할 것입니다.
1.2 도메인 전문가와 개발자 간 지식 공유
온라인 서점 개발에서 각 영역(온라인 홍보, 정산, 배송 등)은 해당 도메인의 전문가들로 구성되어 있습니다. 이들은 도메인 지식과 경험을 기반으로 원하는 기능을 요구합니다. 개발자는 이러한 요구사항을 분석하고 설계하여 코드를 작성하고 테스트한 후 배포합니다.
요구사항을 올바르게 이해하는 것은 매우 중요합니다. 잘못 이해하면 잘못된 기능을 만들게 되고, 수정하는 데 많은 시간과 노력이 소요됩니다. 요구사항을 정확히 이해하지 못하면 유용하지 않거나 쓸모없는 시스템을 만들게 될 수 있습니다.
요구사항을 올바르게 이해하기 위해 개발자와 전문가 간의 직접적인 대화가 필요합니다. 정보의 왜곡과 손실을 최소화하기 위해 개발자와 전문가 사이의 중간 전달자는 가능한 줄여야 합니다. 개발자와 관련 이해관계자들은 도메인 지식을 습득해야 합니다. 도메인 전문가, 관계자, 개발자가 동일한 지식을 공유하고 직접 소통할수록 원하는 제품을 개발하는 가능성이 높아집니다.
1.3 도메인 모델
도메인 모델은 특정 도메인을 개념적으로 표현한 것으로, 주문 도메인을 예로 들어보면 온라인 쇼핑몰에서 주문을 위해 상품 선택과 배송지 입력이 필요합니다. 선택한 상품 가격을 기반으로 총 지불 금액을 계산하고, 결제 수단을 선택합니다. 주문 이후에도 배송 전인 경우 배송지 주소를 변경하거나 주문을 취소할 수 있습니다. 이를 위한 주문 모델을 객체 모델로 구성하면 [그림 1.3]과 같습니다.
도메인 모델은 객체만을 사용하여 모델링하는 것에 한정되지 않습니다. 상태 다이어그램을 이용하여 주문의 상태 전이를 모델링할 수 도 있으며, [그림 1.4]를 보면 상품준비중상태에서 주문을 취소하면결제취소가함께이루어진다는것을알 수 있는 것처럼 도메인의 시나리오를 파악할 수 있습니다.
그 외에도 관계가 중요한 도메인이라면 그래프를 이용해서 도메인을 모델링 할 수 있으며, 계산 규칙이 중요하다면 수학 공식을 활용하여 도메인 모델을 만들 수 있습니다. 도메인 모델은 도메인 자체를 이해하기 위한 개념 모델입니다. 이를 이용하여 코드를 직접 작성하는 것은 아니기 때문에 구현 기술에 맞는 구현 모델이 별도로 필요합니다. 개념 모델과 구현 모델은 서로 다른 개념이지만, 구현 모델은 개념 모델을 최대한 따르도록 설계될 수 있습니다. 예를 들어, 객체 기반 모델을 기반으로 도메인을 표현했다면 객체 지향 언어를 사용하여 개념 모델에 가깝게 구현할 수 있습니다. 마찬가지로, 수학적인 모델을 사용한다면 함수를 활용하여 도메인 모델과 유사한 구현 모델을 만들 수 있습니다.
하위 도메인과 모델 도메인에 따라 용어의 의미가 결정되므로, 여러 하위 도메인을 하나의 다이어그램에 모델링하면 안 됩니다.
1.4 도메인 모델 패턴
일반적인 애플리케이션의 아키텍처 구성은 [표 1.1]처럼 네 개의 영역으로 구성됩니다.
영역 | 설명 |
사용자 인터페이스 또는 표현 | 사용자의 요청을 처리하고 사용자에게 정보를 보여준다. 여기서 사용자는 소프트웨어를 사용하는 사람뿐만 아니라 외부 시스템일 수도 있다. |
응용 | 사용자가 요청한 기능을 실행한다. 업무 로직을 직접 구현하지 않으며 도메인 계층을 조합해서 기능을 실행한다. |
도메인 | 시스템이 제공할 도메인 규칙을 구현한다. |
인프라스트럭처 | 데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다. |
도메인 계층은 도메인의 핵심 규칙을 구현합니다. 주문 도메인의 경우 출고 전에 배송지를 변경할 수 있다는 규칙과 주문 취소는 배송 전에만 할 수 있다는 규칙을 구현한 코드가 도메인 계층에 위치하게 됩니다. 이러한 도메인 규칙을 객체지향 기법으로 구현하는 패턴이 도메인 모델 패턴입니다.
"도메인 모델"이란 용어는 도메인 자체를 표현하는 개념적인 모델을 의미하지만, 도메인 계층을 구현할 때 사용하는 객체 모델을 언급할 때에도 '도메인 모델'이란 용어를 사용합니다. 이 책에서도 도메인 계층의 객체 모델을 표현할 때 '도메인 모델'이라고 표현하고 있습니다.
public class Order {
private OrderState state;
private ShippingInfo shippingInfo;
public void changeShippingInfo(ShippingInfo newShippingInfo) {
if (isShippingChangeable()) {
throw new IllegalStateException("Can't change shipping in " + state);
}
this.shippingInfo = newShippingInfo;
}
private boolean isShippingChangeable() {
return state == OrderState.PAYMENT_WAITING || state == OrderState.PREPARING;
}
public enum OrderState {
PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED;
}
}
위코드 처럼 핵심 규칙을 구현한 코드는 도메인 모델에만 위치하기 때문에 규칙이 바뀌거나 규칙을 확장해야 할 때 다른 코드에 영향을 덜 주고 변경 내역을 모델에 반영할 수 있게 됩니다.
개념 모델과 구현 모델
개념 모델은 문제를 분석한 결과물로, 데이터베이스, 트랜잭션 처리, 성능, 구현 기술 등을 고려하지 않고 도메인을 표현합니다. 따라서 실제 코드 작성 시에는 개념 모델을 그대로 사용할 수 없으며, 개념 모델을 구현 가능한 형태로 전환해야 합니다. 초기 개념 모델을 만들 때 완벽하게 도메인을 표현하는 모델을 만드는 것은 불가능하지만, 소프트웨어 개발 과정에서 도메인 지식이 쌓이고 발전함에 따라 모델을 보완하거나 변경해야 합니다. 따라서 처음부터 완벽한 개념 모델을 만들기보다는 개요 수준으로 작성하고, 구현 과정에서 점진적으로 개념 모델을 구현 모델로 발전시켜야 합니다.
1.5 도메인 모델 도출
제 아무리 뛰어난 개발자라 할지라도 도메인에 대한 이해 없이 코딩을 시작할 수는 없습니다. 도메인을 모델링할 때 기본이 되는 작업은 모델을 구성하는 핵심 구성 요소, 규칙, 기능을 찾는 것입니다. 이 과정은 요구사항에서 출발합니다.
책에서는 주문과 관련된 요구사항에서 도메인 모델을 점진적으로 만들어 나가는 것을 상세하게 설명하는데 읽어보는것을 권합니다.
1.6 엔티티와 밸류
도출한 모델은 크게 엔티티와 밸류로 구분 할 수 있습니다.
1.6.1 엔티티
엔티티의 가장 큰 특징은 식별자를 가진다는 것입니다. 각 엔티티 객체는 고유한 식별자를 갖고 있으며, 서로 다른 식별자를 가지게 됩니다. 예를 들어 주문 도메인에서 각 주문은 주문번호를 가지며, 이 주문번호는 각 주문마다 서로 다릅니다. 따라서 주문번호가 주문의 식별자가 됩니다.
1.6.2 엔티티의 식별자 생성
흔히 식별자는 다음 중 한 가지 방식으로 생성합니다:
- 특정 규칙에 따라 생성
- UUID나 Nano ID와 같은 고유 식별자 생성기 사용
- 값을 직접 입력
- 일련번호 사용 (시퀀스나 DB의 자동 증가 칼럼 사용)
1.6.3 밸류 타입
밸류 타입은 개념적으로 완전한 하나를 표현할 때 사용합니다.
// bad
public class ShippingInfo {
private String receiverName;
private String receiverphoneNumber; 받는사람
private String shippingAddress1;주소
private String shippingAddress2;
private String shippingZipcode;
... 생성자, get 메서드
}
// good
// receiver와 address의 밸류 타입을 사용함으로써 동일한 개념을 하나로 표현가능합니다.
public class ShippingInfo {
private Receiver receiver;
private Address address;
... 생성자, get 메서드
}
코드의 안정성을 위해 밸류 타입을 불변(immutable)으로 구현하는 것이 좋습니다.
1.6.4 엔티티 식별자와 밸류 타입
식별자는 단순한 문자열 이상으로 도메인에서 특별한 의미를 지니는 경우가 많습니다. 이러한 경우, 의미가 잘 드러나도록 식별자를 위한 값 타입을 사용할 수 있습니다.
public class Order {
// OrderNo 타입자체로id가주문번호임을알수있다.
private OrderNo id;
...
public OrderNo getId() {
return id;
}
}
1.6.5 도메인 모델에 set 메서드 넣지 않기
set 메서드는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 합니다.
습관적으로 작성한 set 메서드는 필드값만 변경하고 끝나기 때문에 상태 변경과 관련된 도메인 지식이 코드에서 사라지게 됩니다.
불변 밸류 타입을 사용하면 자연스럽게 밸류 타입에는 set 메서드를 구현하지 않습니다. set 메서드를 구현해야 할 특별한 이유가 없다면, 불변 타입의 장점을 살릴 수 있도록 밸류 타입은 불변으로 구현하는 것이 좋습니다.
1.7 도메인 용어와 유비쿼터스 언어
코드를 작성할 때 도메인에서 사용하는 용어는 매우 중요합니다. 도메인에서 사용하는 용어를 코드에 반영하지 않으면 해당 코드는 개발자에게 코드의 의미를 해석해야 하는 부담을 줍니다. 예를 들어 OrderState를 다음과 같이 구현했다고 가정해 봅시다.
public OrderState {
STEP1, STEP2, STEP3, STEP4, STEP5, STEP6
}
실제주문상태는결' 제대기중, '상품준비중, '출고완료됨' ,배송중, 배송완료됨, '주문취 소됨'인데이코드는개발자가전체상태를6단계로보고코드로표현한것이다. 이개발자는 Order 코드를다음과같이작성할가능성이높다.
public class Order {
public void changeShippingInfo (ShippingInfo newShippingInfo) {
verifyStep10rStep2();
setShippingInfo(newShippingInfo);
}
private void verifyStep10rStep2() {
if (state =! OrderState.STEP1 & state =! OrderState.STEP2)
throw new IllegalStateException("aleady shipped");
}
실제 주문 상태는 '결제대기중', '상품준비중', '출고완료됨', '배송중', '배송완료됨', '주문취소됨' 이지만 이 코드는 개발자가 전체 상태를 6단계로 보고 코드로 표현한 것입니다. 이 개발자는 Order 코드를 다음과 같이 작성할 가능성이 높습니다.
에릭 에반스는 도메인 주도 설계에서 언어의 중요함을 강조하기 위해 "유비쿼터스 언어(Ubiquitous Language)"라는 용어를 사용했습니다. 이는 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고, 이를 대화, 문서, 도메인 모델, 코드, 테스트 등 모든 곳에서 동일하게 사용한다는 것을 의미합니다. 이렇게 함으로써 소통과정에서 발생하는 용어의 모호함을 줄일 수 있으며, 개발자는 도메인과 코드 사이에서 불필요한 해석과정을 줄일 수 있습니다. 시간이 지남에 따라 도메인에 대한 이해가 높아지는데, 새롭게 이해한 내용을 잘 표현할 수 있는 용어를 찾아내고 이를 다시 공통의 언어로 만들어 함께 사용합니다. 새로 발견한 용어는 코드나 문서에도 반영하여 산출물에 최신 모델을 적용합니다.
그러니 도메인 용어에 알맞은 단어를 찾는 시간을 아까워하지 맙시다.
원본 책 링크
'독서 > 2024' 카테고리의 다른 글
[구글 엔지니어는 이렇게 일한다: 구글러가 전하는 문화, 프로세스, 도구의 모든것] CHAPTER 14 더 큰 테스트 - 요약 & 발제문 (0) | 2023.07.29 |
---|---|
[구글 엔지니어는 이렇게 일한다: 구글러가 전하는 문화, 프로세스, 도구의 모든것] CHAPTER 13 테스트 대역 - 요약 & 발제문 (0) | 2023.07.28 |
[설득의 법칙-사람의 마음을 끌어당기는 10가지 심리학] - PART3. 전략 (0) | 2023.06.18 |
[설득의 법칙-사람의 마음을 끌어당기는 10가지 심리학] - PART2. 감정 (1) | 2023.06.13 |
[설득의 법칙-사람의 마음을 끌어당기는 10가지 심리학] PART1. 논리 (1) | 2023.06.12 |