Value Object에 대한 고민

블로그·2025년 11월 23일

들어가며

최근 회사에서 주소와 같은 값을 여러 애그리거트 안에서 쓰는 상황이 생겼다.
사실 급하게 구현해야 했고, 그냥 공통 VO처럼 만들어서 쓰자고 했지만 마음 한켠에는 ‘이게 맞는 걸까?’라는 의문이 남았다.


VO란 무엇일까

내가 VO를 이해한 방식은 이렇다.
VO는 단순히 데이터를 담는 객체가 아니라, 특정 도메인에서 의미 있는 값을 캡슐화한 것이다.

  • 불변성을 가진다
  • 값으로 동등성을 판단한다
  • 도메인 규칙을 포함할 수 있다

즉, VO는 “이 애그리거트 안에서 이런 의미를 가진 값”이어야 한다는 생각이 있다.
그런데 회사에서 내가 만든 주소 VO는 여러 애그리거트에서 그대로 쓰였다.
배송 주소, 청구 주소, 회원 주소 등… 사실 조금씩 의미가 다를 수도 있는 값들이다.


이상하다고 느낀 이유

내가 이상하게 느낀 이유는 명확하다.
VO가 도메인 의미를 담는 객체라면, 애그리거트마다 조금씩 다르게 정의되는 게 자연스럽지 않을까?
그런데 여러 애그리거트가 같은 VO를 공유하면,

  • 도메인 의미가 희석되지 않을까
  • 애그리거트마다 다른 규칙을 적용해야 할 때는 어떻게 할까

이런 고민이 꼬리를 물었다.


현실과 이상 사이

그럼에도 불구하고, 현실적으로 보면 공통 VO를 쓰는 것이 편한 면도 있다.

  • 구조가 단순하면 반복 구현을 피할 수 있다
  • 변동 사항이 생겨도 한 곳만 바꾸면 된다

하지만 여기서 나는 또 다른 질문이 생긴다.

  • “단순 구조만 담는 VO라면 정말 VO라고 부를 수 있을까?”
  • “도메인 규칙을 담지 않는 VO는 그냥 DTO와 다른 점이 무엇일까?”
  • “공통 VO를 쓰면서 애그리거트별 규칙은 어디서 관리해야 할까?”

나의 고민 방식

그래서 나는 결정을 바로 내리지 않았다.
대신 이런 방식으로 생각을 정리했다.

  1. VO를 정의할 때 도메인 의미를 명확히 한다
  2. 만약 여러 애그리거트에서 똑같이 쓰고 싶다면, 값 구조만 담는 최소 VO인지 검토한다
  3. 애그리거트별 규칙이 필요하면, 확장 VO를 만들지 아니면 서비스 레이어에서 처리할지 고민한다

결국 결론은 미뤄두고, “이 VO가 도메인 의미를 제대로 담고 있는가?”를 계속 질문하며 고민하는 과정이 중요하다고 느꼈다.


정리하며

이번 경험을 통해 알게 된 것은, VO를 다룰 때는 답을 찾는 것보다 질문을 정리하는 과정이 더 중요하다는 점이다.

  • 공통 VO를 써야 하는 상황,
  • 애그리거트별 규칙을 어디에 두어야 하는가,
  • VO와 DTO의 경계

이런 고민들을 글로 남기면서, 나중에 다시 돌아봐도 내가 어떤 사고 과정을 거쳤는지 기록으로 남길 수 있다는 점이 마음에 들었다.

0개의 댓글