kotlin
[코틀린/kotlin] DTO와 VO의 차이
hrniin
2023. 11. 1. 21:10
728x90
DTO(Data Transfer Object)
- 로직을 가지고 있지 않으며, 오로지 데이터를 저장하고 다른 곳에 데이터를 전달하는 역할을 한다.
- getter와 setter만을 가지면 다른 함수는 가지지 않는다.
- (kotlin은 data class로 선언하면 getter, setter를 생성하지 않아도 된다.)
VO(Value Object)
- 값 자체를 표현하는 역할을 한다.
- DTO와 반대로 로직을 포함할 수 있다.
- 불변성을 가지는 데이터를 저장하기 때문에 setter를 가지지 않는다.
- 다른 메모리를 가지는 객체라도, 모든 속성 값이 같다면 같은 객체라고 판단한다.
- 객체를 생성하는 시점에 유효성 검사를 한다.
class User(private val name: String, private val age: Int)
예를 들어 name, age의 속성을 가지는 User 클래스가 있다고 가정하자.
val user1 = User("abc", 20)
val user2 = User("abc", 20)
print(user1 == user2) // true
print(user1 === user2) // false
name이 abc고 age가 20인 객체 두개가 있다.
각각 다른 메모리를 가지기 때문에 주소 값을 비교하는 === 연산자로 비교하면 false가 출력된다.
하지만 equals()를 호출하는 == 연산자로 비교하면 값이 동일하기 때문에 같은 객체로 취급되고, true가 출력된다.
data class User(private val name: String, private val age: Int)
class User(private val name: String, private val age: Int) {
override fun equals(other: Any?): Boolean {
val user = other as User
return this.name == user.name && this.age == user.age
}
override fun hashCode() = this.name.hashCode() + this.age.hashCode()
}
이러한 VO 특성을 만족시키기 위해 data class로 선언을 하거나,
equals(), hashCode()를 override 해서 프로퍼티 값 자체를 비교하도록 구현한다.
class User private constructor(private val name: String, private val age: Int) {
override fun equals(other: Any?): Boolean {
val user = other as User
return this.name == user.name && this.age == user.age
}
override fun hashCode() = this.name.hashCode() + this.age.hashCode()
companion object {
fun of(name: String, age: Int): User {
validateUser(name, age)
return User(name, age)
}
}
}
또한 VO에는 의미가 명확한 동작만을 가져야 한다. (무의미한 함수 override, getter 등 x)
객체 생성 시점에 유효성 검사를 한다는 특성이 있다.
이를 만족하기 위해 생성자를 private으로 두고 정적 메소드 패턴으로 객체를 생성하는 것이 일반적이다.
정리
DTO | VO | |
목적 | 데이터 전달 | 값 표현 |
동등성 | 값이 같아도 같은 객체 x | 값이 같으면 같은 객체 |
가변성 | setter 존재 시 가변 setter 미존재시 불변 |
불변 |
로직 | getter/setter 외의 로직을 포함 x | 로직을 포함 |
참고
https://bibi6666667.tistory.com/241
https://maenco.tistory.com/entry/Java-DTO%EC%99%80-VO%EC%9D%98-%EC%B0%A8%EC%9D%B4
728x90