티스토리 뷰

Java

DDD#01. Domain Object

LichKing 2017. 7. 23. 14:25

요즘 최범균님의 DDD start! 라는 책을 보며 DDD(Domain Driven Design)에 대해 입문하고있다. 책을 보며 공부한 내용을 정리하는 포스팅이다.


아마 이번 포스팅은 얼마전 작성한 DTO와 VO 포스팅과 유사한 내용이 상당히 많을 것 같다. 얼마전 잡은 개념이라 책보면서 이해하기에도 어려운부분이 없어서 다행이었다.


1. Domain

개발을 하다보면 도메인이라는 단어를 참 많이 듣게된다. 특히 '도메인 객체' 란 표현으로 접하게되는데 도메인 객체란 내가 개발하고자 하는 영역을 분석하고, 그 분석의 결과로 도출된 객체들을 일컫는다. 예를들어 쇼핑몰을 만든다고 하자. 쇼핑몰의 주된 기능은 상품 구매일것이다. 상품구매의 순서는 보통 이렇다.


* 상품을 등록한다.

* 회원이 상품을 구매한다.

* 하나의 구매에 여러상품을 구매할 수 있다.


이를 토대로 이런 ERD를 도출할 수 있다.

 

 

클래스 다이어그램도 도출할 수 있다.

 

 


이렇게 도출되는 객체들이 도메인 객체가 된다.


이런 도출은 어디까지나 설계의 영역이기때문에 해당 도메인의 특수성에 따라 얼마든 달라질 수 있다. 가령 예를들어 동일한 상품을 2개 샀을때 purchaseDetail에 count라는 필드를 두고 개수를 증가시키는 식으로 구성할 수도 있을것이고, 동일한 상품이라고 하더라도 별개의 purchaseDetail을 더 생성하는식으로 구성할수도 있을 것이다.


도메인 객체는 다시 Entity와 Value Object로 나뉘게 된다.


2. Entity

도메인 못지않게, 아니 어쩌면 도메인보다 더 많이 들었을 단어다. 전공자라면 학교에서부터 엔티티라는 단어는 많이 들어봤을것이다. 다만 주로 엔티티란 단어를 사용하던 분야는 Database일 것이다. 하지만 엔티티는 Dabatase에 국한된 용어는 아니며, 객체지향 세계에서도 사용된다.


엔티티의 가장 큰 특징은 식별자를 갖는 것이다. 즉 식별자 외의 상태가 변경된다고해서 그 객체가 그 객체가 아닌 것이 아니라는 의미다. 위 객체에서 Purchase는 주문 객체다. 주문 객체는 id 필드를 식별자로 갖고있으며, 주문을 취소하거나 주문 내용을 변경한다고해서 다른 주문이 되지는 않는다.


Database의 데이터와 매우 유사하다고 생각할수도 있다. DB 역시 기본키라고 부르는 식별자를 갖고있으며 update로 값을 변경한다고해서 다른 데이터가 되지는 않는다. 다만 DB의 데이터와 다른점은 객체지향의 엔티티는 행위를 갖고있다는 것이다. DB는 그저 값들만 들고있는 구조체에 불과하지만 객체는 상태와 행위를 갖고있기때문에 자신의 데이터를 가지고 필요한 행위를 구현할 수 있다. 보통 이 차이를 잘 이해하지 못한 개발자들이 Transaction Script 라 불리는 객체는 값만 들고있고 모든 로직을 Service Layer에서 처리하는 형태로 코드를 작성하게된다.


class Purchase{
private List<PuchaseDetail> puchaseDetails;

public long getTotalAmount(){
return this.puchaseDetails
.stream()
.mapToLong(PuchaseDetail::getPrice)
.sum();
}
}

주문 객체가 자신의 주문 총액을 스스로 계산한다.


3. VO(Value Object)

엔티티 객체가 식별자를 갖고있는게 특징이라면 VO는 식별자가 없이 그저 값만 들고있는것이 특징이다. Member 클래스가 있고 휴대전화 번호를 각각의 필드에 저장하고있다고 생각해보자. 이런 클래스를 보는건 어렵지않다.


class Member{
private String name;
private MobileCarrier mobileCarrier;
private String phone1;
private String phone2;
private String phone3;
}

enum MobileCarrier{
SKT, KT, LGU
}


지금이야 휴대전화 관련 필드를 제외하고는 name 필드밖에 없지만 보통 Member 클래스에는 이외에도 많은 필드를 갖고있게된다. 그리고 Member 클래스에서 휴대전화 관련 행위(메서드)를 추가하게되면 저 필드들은 항상 같이 사용될것이다. 그렇다면 차라리 저 필드들만 따로 클래스 분리를 하는게 훨씬 가독성을 향상시키고 응집력이 올라갈 것이다.


class Member{
private String name;
private PhoneNumber phoneNumber;
}

class PhoneNumber{
private MobileCarrier mobileCarrier;
private String phone1;
private String phone2;
private String phone3;
}

enum MobileCarrier{
SKT, KT, LGU
}


정말 현업에서 사용할 코드라면 저 phone1, 2, 3 변수도 좀 손봐야겠지만... 여튼 클래스 분리만으로 저 필드들이 뭘 의미하는지 더 명확해졌고, 타입 안정성까지 확보했다.


엔티티의 경우엔 식별자로 객체를 구분하기때문에 상태가 변경된다고해서 다른 객체가 되는것은 아니지만 VO의 경우엔 식별자가 없으므로 상태가 변경되면 그냥 다른 객체가 되게된다. PhoneNumber 객체는 통신사가 바뀌거나 휴대전화 번호가 바뀌게되면 그 자체로 그냥 다른 객체가 되버린다는 것이다. 때문에 확실히 다른 객체임을 보장하기위해 보통 VO는 불변(Immutable) 객체로 만들게된다.


엔티티 객체의 경우엔 DB의 데이터와 많은 부분에서 비슷했지만 VO는 DB와 비교시엔 매우 난감해지게된다. 기본적으로 식별자가 없기때문에 DB와는 어울리지 않는다. 때문에 DB에 값을 넣을때는 기존처럼 엔티티에 분할하여 넣거나, 억지로 식별자를 부여하여 넣게된다. 보통 전자를 많이 사용하게된다.


참고서적

* DDD start!

'Java' 카테고리의 다른 글

Test#02. Groovy로 테스트하기  (0) 2017.08.20
Test#01. jUnit으로 테스트하기  (0) 2017.08.18
다형성 연습하기  (0) 2017.07.08
Garbage Collector  (0) 2017.07.05
DTO와 VO  (8) 2017.07.01
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함