*개요
Entity와 Value Object는 DDD(Domain-Driven Design)에서 주로 사용하는 용어입니다. 데이터 모델링을 할 때 어떤 것을 Entity로 할지, Value Object로 할지 고민이 필요한데 차이점을 알아보겠습니다.
1. 동등성(equality) 관점
- Reference equality(참조 동등성)
만약 2개의 객체가 메모리에 같은 주소를 참조하면 동등하다는 의미입니다
object object1 = new object();
object object2 = object1;
bool areEqual = object.ReferenceEquals(object1, object2); // returns true
- Identifier equality(식별자 동등성)
식별자 동등성은 id 필드를 가진 클래스들이 같은 참조자를 가진다면 동등하다는 의미입니다.
- structural equality(구조 동등성)
- 구조 동등성은 모든 멤버 변수가 같다면 동등하다는 의미입니다.
entitiy와 value object의 가장 큰 차이점은 객체들을 비교하는 방식입니다. eneity는 Identifier equality(식별자 동등성)이고 value object는 tructural equality(구조 동등성) 입니다. 즉, entity는 고유한 식별자가 있지만 value object는 없습니다.
다시 말해 value object는 식별자 필드가 없으며, 만약에 2개의 객체의 필드 값이 모두 동일하다면 2개를 동등하다고, 같다고 생각할 수 있습니다. 반면, 2개의 entity가 필드 값이 모두 같지만 식별자인 id 필드가 다르다면, 동등하지 않습니다.
2. 생명주기
entity는 생명주기가 있어 변경이 가능하고 이력을 관리합니다. 그러나 value object는 생명주기가 없어서 생성과 삭제가 쉬우며 서로 교환가능합니다.
value object는 스스로 생명주기를 가지고 유지될 수 없으며 무조건 특정 entity에 속해야 합니다. 특정 entity에 속해야만 데이터로서 자신의 역할을 수행하며 문맥을 가집니다.
예를 들어 돈에 관해서 "얼마입니까?"는 어떠한 의미도 문맥도 없지만, "철수가 가지고 있는 돈은 얼마입니까?" 혹은 "우리가 가진 모든 돈은 얼마입니까?"처럼 사람(entity)에 돈(value object)을 활용했을 때 역할을 수행하고 문맥을 가집니다. value object는 독립적으로 영속성을 가지지 않고 특정 entity에 속해있을 때만 영속성을 가집니다.
3. 불변성(immutability)
value object는 불변성입니다. 불변성은 변하지 않는다는 뜻인데 즉, 어떤 객체의 특정 값을 바꿔야 한다면 값만 변경하는 것이 아니라 아예 새로운 객체를 만듭니다. entity는 특정 값을 수정할 수 있는 가변성입니다.
만약 value object가 가변성이라면 특정 값을 바꿀 수 있게 되고 고유한 식별성이 생기고 생명주기를 가져버립니다. 이는 DDD의 개념과 모순됩니다. value object는 특정 상태의 순간을 저장하는 스냅샷 그 자체입니다. 절대 변경이 되어서는 안 되며 불변성을 지키지 않는다면 value object라고 할 수 없습니다.
4. 도메인 모델에서 value object 구분법
도메인 모델은 프로젝트 성격에 따라서 entity가 될 수도 value object가 될 수도 있습니다. 모든 상황에서 동일한 기준으로 entity와 value object를 나눌 수 없습니다. 통상적으로 '돈'은 value object로서 동등성을 가지고 교환 가능한 것으로 생각하지만, 현금 흐름을 추적하는 소프트웨어를 만든다면 모든 청구서를 고유한 값으로 봐야 합니다. 이 경우, 돈은 value object가 아닌 entity가 됩니다.
명확한 기준은 없지만 구분하는 2가지 방법이 있습니다.
- 만약 하나의 객체를 같은 특성 값을 가진 다른 객체로 대체할 수 있다면 value object에 적합합니다.
일반적으로 '돈'이 그렇습니다. 오늘 내가 가진 1달러는 어제 내가 가지고 있던 혹은 다른 사람이 가지고 있는 1달러와 동일합니다. 이 1달러는 서로 교체가 가능하다면 value object에 적합합니다.
- value object를 integer에 비유하는 것입니다.
integer 5가 다른 메서드에서 사용했던 5와 동일한지 아닌지 신경을 쓰나요? 그렇지 않다면, 애플리케이션 내의 모든 5는 어떻게 생성되었는지 상관없이 모두 같은 5이고 value object입니다. 이 개념을 도메인으로 확장해 도메인을 integer처럼 취급할 수 있다면 value object에 적합합니다.
5. 데이터베이스에 value object 저장하기
아래에 도메인 모델 Person(entity)와 Address(value object) 2개가 있습니다. 데이터베이스로 어떻게 표현할 수 있을까요?
단순한 방법은 각각 테이블을 만드는 것입니다.
이는 2가지 문제가 있습니다.
첫 번째로, Address 테이블이 식별자를 가집니다. 두 번째로, value object와 entity가 분리됩니다. Address는 동등성을 가지는 value object임에도 불구하고 Person entity에 속하지 않고 독립적으로 존재합니다.
해결책은 Address에 있는 필드들을 Person에 넣는 것입니다.
Address는 식별자가 더 이상 없으며 Person entity에 생명주기가 완전히 의존합니다. 이전에 언급한 integer와 value object 관계를 생각해 봅시다. integer를 위해서 테이블을 별도로 만들어야 할까요? 단지 자신을 사용할 table에 integer를 넣어주면 됩니다, 굳이 value object를 위해서 별도의 테이블을 만들 필요 없이 entity의 테이블에 넣어주면 됩니다.
6. entity 대신 value object를 고려할 것
value object는 불변이며 entity보다 훨씬 가벼워 생성과 삭제가 쉽습니다. 이상적으로 대부분의 비즈니스 로직을 value object로 만들어야 합니다. entity는 value object를 감싸는 래퍼의 역할을 하고 고수준의 기능을 담당합니다.
주의할 것은, 처음에 entity라고 생각했던 것이 실제는 value object일 수도 있습니다. 예를 들어, 처음에 Address 클래스는 entity라고 생각하여 id 필드를 만들고 테이블을 분리했다고 합시다. 나중에 다시 봤을 때, 주소는 실제로 고유한 식별자를 가지지 않고 동등하게 교환될 수 있다는 사실을 깨닫습니다. 이런 경우, 도메인 모델 리팩토링을 망설이지 말고 entity를 value object로 변경하면 됩니다
참고
Entity vs Value Object: the ultimate list of differences · Enterprise Craftsmanship
'학습 > Java' 카테고리의 다른 글
Generics의 Wildcards(와일드카드) (0) | 2024.03.07 |
---|---|
Value Object 패턴 (0) | 2023.07.07 |
스프링 AOP (1) - 동적 프록시 (0) | 2023.01.11 |
mutable vs immutable (0) | 2022.11.01 |
StringBuffer vs StringBuilder (0) | 2022.11.01 |