<aside>
1️⃣ 설명
</aside>
- **
VO (Value Object)
**와 **DTO (Data Transfer Object)
**는 모두 Java 및 Spring과 같은 객체 지향 프로그래밍 및 프레임워크에서 데이터를 표현하고 전달하는 데 사용되는 설계 패턴이다.
<aside>
2️⃣ 두 패턴의 차이점
</aside>
- 불변성(Immutability):
- VO(Value Object):
- VO는 불변 객체이다. 즉, 일단 생성된 후에는 그 상태를 변경할 수 없다.
- VO는 일반적으로 속성을 가진 작은 객체로, 이들 속성은 객체가 생성될 때 설정되고 그 후에는 변경되지 않는다.
- 불변성은 VO의 중요한 특징 중 하나이며, 이는 복잡성을 줄이고 프로그램의 안정성을 향상시킨다.
- DTO(Data Transfer Object):
- DTO는 원칙적으로 불변성을 가져야하지만, 실제 사용시에는 상황에 따라 변경 가능성을 가질 수도 있다.
- DTO는 다른 계층 또는 서비스간의 통신에서 사용되는 객체로, 그 목적은 단순히 데이터를 한 데 묶어 전달하는 것이다. DTO가 변경 가능한 객체인지 불변한 객체인지는 그 사용 방법에 따라 달라질 수 있다. 일부 경우에는, 데이터를 생성한 후에 추가적인 변형이나 가공을 위해 DTO를 변경해야 할 수도 있다.
- 그러나 원칙적으로 DTO는 불변성을 가지는 것이 좋다. DTO는 데이터 전송의 목적으로 사용되기 때문에, 데이터 전송이 완료된 이후에는 원래의 상태가 유지되는 것이 일반적이다. 이렇게 함으로써, 데이터의 일관성이 유지되고 버그의 가능성이 줄어들기 때문이다.
- Java의 **
record
**는 불변성을 가진 데이터를 나타내는데 적합한 도구이다. 따라서, DTO를 정의하는 데 사용할 수 있다.
- 동등성(Equality):
- VO(Value Object):
- VO의 동등성은 모든 속성 값에 의해 결정된다. 즉, 두 VO가 동등하다는 것은 그들의 모든 속성 값이 동일하다는 것을 의미한다. 이런 의미에서 VO는 값에 의해 정의되므로 **
"Value Object"
**라고 불린다.
- DTO(Data Transfer Object):
- DTO의 동등성은 일반적으로 그것의 식별자(ID)나 일부 핵심 속성에 의해 결정된다. 이는 DTO가 데이터베이스의 레코드를 표현하는 경우가 많고, 이런 레코드는 고유한 ID를 갖는 경우가 일반적이기 때문이다.
- 사용 목적:
- VO(Value Object):
- VO는 비즈니스 로직을 수행하는 데 사용되는 정보를 캡슐화하는 데 사용된다. 예를 들어, "Money" 클래스는 금액과 통화를 나타내는 VO가 될 수 있다.
- DTO(Data Transfer Object):
- DTO는 서로 다른 계층(예: 표현 계층과 비즈니스 로직 계층) 또는 시스템 간에 데이터를 전송하는 데 사용된다. DTO는 서버와 클라이언트 간의 통신이나 데이터베이스의 레코드를 가져오는 등의 작업에 주로 사용된다.
<aside>
3️⃣ VO, DTO 예시를 통한 설명
</aside>
- ***VO (Value Object)는 '화폐'라고 생각할 수 있다.
- 예를 들어, 당신이 지갑에 가지고 있는 1000원 짜리 지폐 하나를 살펴보자.
이 지폐는 1000원의 가치를 가지고 있고, 이 가치는 변하지 않는다.
다른 1000원 짜리 지폐를 가지고 와서 비교하더라도, 가치는 동일하다.
즉, VO는 변하지 않는 값을 나타내며, 그 값이 같다면 동일한 객체로 볼 수 있는 것이다.
- ***DTO (Data Transfer Object)는 '학생의 성적표'라고 생각해 볼 수 있다.
- 학생의 성적표에는 학생의 이름, 과목별 점수 등 여러 정보가 들어있다.
성적표는 한 학기가 끝날 때마다, 즉 학생의 성적이 업데이트 될 때마다 그 내용이 바뀐다.
여기서 중요한 점은, 이름이 같은 학생의 성적표라면 동일한 성적표로 볼 수 있다는 것이다.
성적이 변하더라도 그것은 같은 학생의 성적표이기 때문이다.
- 따라서, VO는 값의 불변성에 초점을 맞추고, DTO는 데이터의 전달과 변경에 초점을 맞춘다. 이 둘은 각각의 역할에 맞게 사용되어야 한다.
<aside>
4️⃣ JPA에서는 어떤방식이 사용될까?
</aside>
JPA(Java Persistence API)와 같은 ORM(Object-Relational Mapping) 프레임워크를 사용할 때 일반적으로 DTO와 Entity 클래스가 주로 사용된다.
- Entity 클래스는 데이터베이스의 테이블을 표현하는 클래스로, 일반적으로 각 테이블의 각 행은 Entity 클래스의 인스턴스에 매핑된다.
- Entity 클래스의 인스턴스는 데이터베이스에서 가져온 데이터를 나타내므로, 이 데이터는 변경될 수 있다. 따라서 Entity 클래스는 일반적으로 VO보다는 DTO와 비슷한 특성을 가진다. 하지만 Entity 클래스는 일반적으로 비즈니스 로직을 포함하며, 이는 DTO와 차이를 가진다.
DTO(Data Transfer Object):
- 여러 계층(예: 표현 계층과 비즈니스 로직 계층) 또는 시스템 간에 데이터를 전송하는 데 사용된다.
- Entity 클래스의 인스턴스는 일반적으로 그대로 클라이언트에게 전달되지 않는다. 대신, Entity 클래스의 인스턴스에서 필요한 데이터를 가져와 DTO에 넣고, 이 DTO를 클라이언트에게 전달한다. 이 방법을 사용하면, 데이터베이스 구조의 세부 사항을 숨기고, 필요한 데이터만 클라이언트에게 제공할 수 있다.
- **
VO(Value Object)
**는 JPA 개발에서도 활용될 수 있지만, 일반적으로는 엔티티의 일부분을 나타내는데 사용되다.
- 예를 들어, '주소'라는 Value Object가 '도시', '도', '우편번호'라는 필드를 가질 수 있으며, 이는 'User' Entity의 일부로 사용될 수 있다.
- 결론적으로, JPA를 사용하는 개발 환경에서는 Entity 클래스와 DTO가 주로 사용되며, VO는 필요에 따라 특정 경우에 사용된다.
<aside>
5️⃣ 그럼 주로 DTO를 사용하고 VO는 사용하지않는것인가?
</aside>
- **
JPA
**와 **MyBatis
**와 같은 ORM(Object-Relational Mapping)
또는 SQL 매퍼
프레임워크에서는 데이터의 전달과 변환에 중점을 두기 때문에 주로 **DTO(Data Transfer Object)
**가 사용된다.
- 하지만 이는 **
'VO를 절대 사용하지 않는다'
**는 뜻은 아니다. 프로젝트의 특성, 도메인의 복잡성, 개발팀의 설계 전략에 따라 VO가 적용되는 경우도 많다.
- **
VO(Value Object)
는 특히 도메인 주도 설계(Domain Driven Design, DDD)
**에서 중요한 개념이다. **VO
**는 도메인에서 개념적으로 중요하거나 불변성을 가져야 하는 데이터를 모델링하는데 유용하다. 예를 들어, '주소'나 '화폐'와 같은 개념은 **VO
**로 표현되기 좋다. 이들은 본질적으로 값이 변하면 새로운 개체로 취급되는 특성을 가지고 있다.
- 따라서, **
JPA
**나 **MyBatis
**를 사용하는 경우에도 도메인 모델링이 필요하다면 **VO
**를 사용해야 할 수 있다. 반대로, 단순 CRUD(Create, Read, Update, Delete)
작업을 수행하는 애플리케이션에서는 **DTO
**만으로 충분할 수 있다.
- 결론적으로, **
VO
**와 DTO
모두 알고 있고 적절한 상황에 적절하게 사용하는 것이 중요하다. 둘 다 각각의 목적과 역할에 따라 활용된다.