VO (Value Object) 정리

Jeongkuk Seo
sjk5766
Published in
4 min readJan 10, 2023

인터넷에 VO를 정리한 많은 글이 있지만 굳이 포스팅을 하는 이유는 최근 받은 리뷰 과정에서 VO를 제대로 몰랐기에 정리하고자 합니다.

그랬다.. VO가 값 그 자체를 나타내는 객체로 알고 있었지만 정작 그 특징을 제대로 알지 못했다.

VO는 크게 3가지 특징을 갖는다.

  1. 불변성
    Value Object는 불변하다. 즉 수정자(setter)가 없다.
    불변하기 때문에 존재하는 장점은 참조를 통해 공유해도 이로 인한 Side Effect가 없다.
  2. 값 동등성
    두 Value Object가 동일한 값을 가진다면 둘은 동등하다. 이를 위해 equals와 hashcode 메소드를 재 정의한다.
  3. 자가 유효성 검증
    Value Object는 유효한 값으로만 생성된다. 즉 아래와 같은 Age VO가 있을 때 생성된 모든 Age 값 객체는 0 이상을 보장할 수 있다.
@Embeddable
public class Age {
private int value;

protected Age() {}

public Age(int value) {
validate(value);
this.value = value;
}

public void validate(int value) {
if (value < 0) {
// 예외 발생
}
}
}

VO 사용시 장점

3번 자가 유효성 검증에서 알 수 있듯이 객체에 제약사항을 둘 수 있으며 VO 자체로 좀 더 객체지향적인 프로그래밍을 할 수 있다.

또한 Entity가 유효성 검증 코드로 거대해지는 것을 완화할 수 있다. 아래 Human 이란 엔티티가 있고 name, age 컬럼이 있다고 가정하자. 이 때 name과 age에 유효성을 검증하는 코드가 있다.

@Entity
public class Human {
private String name;
private int age;

public Human(String name, int age) {
if (name.isEmpty()) {
// name 에러
}

if (age < 0) {
// age 에러
}

this.name = name;
this.age = age;
}
}

만약 Human 엔티티에 컬럼이 추가되고 유효성 검증이 필요한 경우 이를 검증하는 코드들이 늘어날 것이다.

하지만 name과 age를 각각 값 객체로 만들고 거기서 유효성 검증을 한다면 Human 엔티티는 각 컬럼에 대한 유효성 검사를 하는 책임을 덜 수 있다.

@Entity
public class Human {
private Name name; // Name Value Object 내부에 빈 값에 대한 유효성 검증
private Age age; // Age Value Object 내부에 0 보다 작은 값에 대한 유효성 검증

public Human(Name name, Age age) {
this.name = name;
this.age = age;
}
}

VO Getter 메소드 명

사람마다 취향 차이는 있겠지만 Value Object의 getter 메소드명이 get 보다는 value 라는 이름이 개인적으로 더 적절하다고 생각한다.

public class Age {
private int value;

protected Age() {}

public Age(int value) {
this.value = value;
}

public int value() {
return value;
}
}

레퍼런스

https://medium.com/@nicolopigna/value-objects-like-a-pro-f1bfc1548c72

--

--