DOing
Domain, Entity, Value(Object) 본문
Spring 프로젝트 중에 Domain, Entity, VO(value object)라는 용어들이 반복적으로 등장하지만, 정작 이들의 차이를 모르고 있다는 생각이들었다. 이에 관련되어 더 공부하고자 DDD START 도메인 주도 설계(최범균 저)의 책을 읽고 정리하였다.
💡 도메인(Domain)
온라인서점 사이트에서 책을 조회하고 구매한다고 가정하자. 개발자 입장에서 온라인서점은 구현해야할 소프트웨어의 대상이 된다. 온라인서점 소프트웨어는 상품의 조회, 구매, 결제등의 기능을 제공해야한다. 이때 온라인 서점은 소프트웨어로 해결하고자하는 문제 영역, 즉 도메인(domain)에 해당된다.
한 도메인은 다시 하위 도메인으로 나눌 수 있다. 예를 들어 '온라인 서점' 도메인은 다시 주문, 결제, 배송같은 하위 도메인을 가진다.
💡 도메인 모델
도메인 모델에는 다양한 정의가 존재하는데 기본적으로 도메인 모델은 특정 도메인을 개념적으로 표현한 것이다.
도메인 모델을 표현할 때 클래스 다이어그램이나 상태 다이어그램과 같은 UML기법만 사용해야하는 것은 아니다. 그래프나 수학공식을 활용해서 도메인 모델을 만들수도 있따. 도메인을 이해하는데 표현 방식이 무엇인지는 중요하지 않다. 도메인 모델은 기본적으로 도메인 자체를 이해하기 휘한 개념모델이다. 개념모델을 사용해서 바로 코드로 작성할 수 있는 것은 아니기 때문에 구현기술에 맞는 구현 모델이 필요하다.
개념모델과 구현모델은 서로다른 것이지만 구현모델이 개념모델을 최대한 따르도록 할 수는 있다. 예를 들어 객체 기반모델로 도메인을 표현했다면 객체지향 언어를 이용해 개념모델에 가깝게 구현할 수 있다. 만약 수학적인 모델을 사용한다면 함수를 이용해 도메인 모델과 유사한 구현모델을 만들 수 있다.
💡 도메인 모델 도출
도메인에 대한 이해가 없이는 코딩을 시작할 수는 없다. 요구사항을 분석한 것을 바탕으로 기획서, 유스케이스, 사용자 스토리를 통해 도메인을 이해하고 이를 바탕으로 도메인 모델 초안을 만들어야 비로소 코드를 작성할 수있다. 즉 도메인 모델(객체)은 내가 개발하고자 하는 영역을 분석하고, 그 분석의 결과로 도출된 모델(객체)라고도 할 수 있다.
이렇게 도출한 도메인 모델은 크게 Entity와 Value로 구분할 수 있다.
💡 Entity
엔티티의 가장 큰 특징은 식별자를 가진다는 것이다. 즉, 식별자 외 데이터가 변경된다고 해서 그 객체가 다른 객체가 되는 것은 아니다. 예를 들어 Purchase은 주문id를 식별자로 가진다고 하자. Purchase에서 주문상태를 변경한다고 다른 주문이 되지는 않는다.
만약 데이터베이스에 대해서 배웠다면 이미 엔티티에 대해서 들어보았을 것이다. 아마 이때문에 테이블과 엔티티를 헷갈릴 수도 있다. 엔티티는 테이블과 달리 데이터베이스나 SQL상 실제로 존재하는 것이 아닌, 일종의 개념이다. 반면 테이블은 데이터베이스나 SQL에 실제로 존재하며 물리적인 구조를 지니고 있다. 엔티티는 논리 모델에서 사용되며, 테이블은 물리 모델에서 사용된다.
Entity는 실체, 객체라는 의미를 담고 있으며 업무에 필요하고 유용한 정보를 저장하고 관리하기 위한 집합적인 것이라고 할 수 있다. 데이터베이스에 권위자들은 Entity에 대해 다음과 같이 정의하였다.
- 변별할 수 있는 사물 (Peter Chen, 1976)
- 정보를 저장할 수 있는 어떤것 (James Martin, 1989)
- 정보를 저장할 수 있는 사람, 장소, 물건, 사건 그리고 개념 등(Thomas Bruce, 1992)
💡 Value
Value는 식별자를 가지지 않으며 값 그자체이다. 엔티티의 경우에는 식별자로 구분되기 때문에 식별자를 제외한 데이터가 변경된다고 다른 객체가 되는 것은 아니라고 했다. 하지만 Value의 경우엔 식별자가 없으므로 하나의 데이터라도 변경되면 그냥 다른 객체가 된다. 때문에 같은 객체임을 확실하게 보장하기 위해 Value 타입 불변(immutable)으로 구현하는 것이 좋다. 이를 위해 값은 생성자를 통해서만 받고 setter는 아예 구현하지 않는다. 만약 기존 객체의 데이터를 변경하고 싶다면 변경한 데이터로 아예 새로운 객체를 만든다.
엔티티 객체는 DB의 테이블과 대응될 수 있었지만, Value는 기본적으로 식별자가 없어 대응될 수 없다.
💡 MyBatis의 VO(Value Object)와 JPA의 Entity
지금까지 Domain, Entity, Value에 대해서 알아보았다.
Spring에 MyBatis를 쓰는 경우에는 주로 VO(ValueObject)라고 표현하고, JPA를 쓰는 경우에는 Entity라고 표현한다.
그 이유는 JPA는 ORM이고 MyBatis는 SQL-Mapper이기 때문이다. ORM은 SQL문이 아닌 RDB 객체를 자바 객체로 매핑한다. 객체간 관계, 식별자를 가질 수 있다. 반면 SQL-Mapper는 SQL문으로 RDB에 접근하고 데이터를 객체로 매핑한다. 객체간 관계나 식별자는 가질 수 없다.
때문에 JPA에서는 식별자를 가지는 Entity, MyBatis에서는 값 객체를 의미하는 VO라는 명칭을 사용한다. 간혹 DTO(Data Transfer Object)라고 하는 사람들도 있는데, DTO와 VO는 분명한 차이가 있다. 이는 다음에 포스팅으로 더 자세히 다루겠다.
[ Entity 예시 ]
Springboot-JPA를 사용해서 진행했었던 프로젝트의 코드 일부를 발췌했다.
domain폴더안에 Posts.java라는 파일로 작성하였다.
@Entity
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author){
this.title = title;
this.content = content;
this.author = author;
}
public void update(String title, String content) {
this.title = title;
this.content = content;
}
}
[ VO 예시 ]
Spring-Mybatis를 사용해서 진행했던 프로젝트의 코드 일부를 발췌하였다.
domain폴더안에 Product.java라는 파일로 작성하였다.
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ProductVO {
private Long product_id;
private String product_title;
private int product_price;
private Date product_regDate;
private String product_description;
private String product_information;
}
출처:
DDD START 도메인 주도 설계(최범균 저)
'Spring' 카테고리의 다른 글
[Spring] POJO란? (1) | 2021.05.29 |
---|---|
[Spring] Spring Framework의 정의와 목적 (0) | 2021.05.29 |
Spring ShoppingMall 팀프로젝트 회고 (1) | 2021.05.17 |
[Maven] Maven에 대해 알고 사용해보자 (0) | 2021.05.08 |
[Spring Security] UserDetailsService를 이용한 인증 (0) | 2021.04.28 |