jingyulog

Value Object 본문

Tech/DDD

Value Object

jingyulog 2025. 10. 4. 15:35

개요

Value Object란 도메인 모델에서 식별자가 필요하지 않고, 속성 및 값으로 구별되는 오브젝트를 말하는데, 대표적으로 Integer, Decimal, Date, Long 등이 있다.

특징

  1. 엔티티가 너무 많은 책임을 가지는 것을 방지하게 하여, 특정 속성 관련 행위를 분리해서 엔티티를 더 집중된 상태로 유지하게 한다.
  2. 원시 타입(예: int, long 등)보다 도메인 개념을 더 명시적으로 나타내서 모델의 명확성을 높인다.
  3. 생성 이후에 상태가 변하지 않고, 변경이 필요하면 새로운 객체로 교체한다. (불변성 - immutable)
  4. 풍부한 기능을 가진다.
  5. 자체 유효성 검사도 가능하다.
  6. 값 비교는 == 대신에 equals()로 비교한다. 이때, 값이 같으면 같은 객체로 간주한다.
  7. 동등성 기준으로 비교하기 때문에 equals()와 hashCode()를 반드시 Override 해야한다.

예시

대표적인 예시

java.time.LocalDate // 날짜를 값으로 표현
java.time.LocalDateTime // 날짜 + 시간 값 표현
java.math.BigDecimal // 정말한 숫자 표현
java.awt.Point // 좌표(x, y) 값 표현
java.util.UUID
java.net.URL // 인터넷 주소 표현

커스터마이징

import java.util.regex.Pattern;

public record Email(String address) {
    private static final Pattern EMAIL_PATTERN =
            Pattern.compile("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");

    public Email {
        if (!EMAIL_PATTERN.matcher(address).matches()) {
            throw new IllegalArgumentException("이메일 형식이 바르지 않습니다: " + address);
        }
    }
}

public final class Money {
    private final int amount;
    private final String currency;

    public Money(int amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }

    public int getAmount() { return amount; }
    public String getCurrency() { return currency; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Money)) return false;
        Money money = (Money) o;
        return amount == money.amount &&
               currency.equals(money.currency);
    }

    @Override
    public int hashCode() {
        return Objects.hash(amount, currency);
    }
}