엔티티(entity)와 값 객체(value object)에 대해서

최지환·2022년 5월 23일
1

객체지향

목록 보기
3/3
post-thumbnail

vo 와 엔티티에 대해

vo와 entity에 대해서 정말 많이 헷갈려 했다. 그래서 이번에 정리를 하려고 한다.

처음 vo 에 대해 접하고 이를 코드에 적용하려 했을 때는 막연하게 ‘vo로 객체를 만드는 것은 절대적으로 좋은 거다’ 그리고 ‘vo로 객체를 만드려면 불변 객체로 만들고 equals와 hashCode를 재정의를 해주면 된다.’ 라고 생각했다.
이렇게 개념을 이해하려 하지 않고 외운 내용(내 마음대로 vo라고 생각한 개념)을 코드에 적용해 왔다.
그러다 보니 후에 엔티티라는 개념을 접했을 때, 정말 혼동을 많이 했다.

가변적인 것은 모두 엔티티고, 그렇지 않으면 모두 vo 객체인가? 라는 생각 부터 시작해서,
vo는 불변이기 때문에 좋은 거고 엔티티는 가변 객체라 나쁜건가? 라는 생각도 하였다.
또한 현실 세계에서 객체 지향 세계로 옮긴 특정 클래스가 엔티티로써 쓰여야하는지 vo로써 쓰여야하는지 명확하게 구분을 하지 못했다.

코드에 내가 안다고 생각한 잘 모르는 개념을 적용하려다 보니, 혼동이 너무 많았다. 따라서 이번에 확실하게 이 개념을 잡고 싶어 정리를 해두려고 한다.


우선 vo 와 entity의 개념에 대해 알아보기 전에 짚고 넘어가야 할 개념이 있다.

바로 identifier equalitystructural equality 이다.

Identifier Equality

  • 클래스 내부에 식별자(id) 필드를 갖고 있다.
  • 객체의 동등 여부를 id로 구별 한다.
    • 예시)
      군인 → 같은 계급, 같은 이름, 같은 성별인 군인이 서로 같은 군인은 아니다.
      군번이라는 고유 번호(id)를 통해 서로 구별 할 수 있다.

Structural Equality

  • 클래스 내부의 필드(멤버)가 모두 같다면, 두 객체는 같다.
    • 예시)
      음료수 → 음료수 라는 객체가 있고, 이 객체는 필드로 내용물포장 방식을 갖고 있다고 생각해보자.
      그렇다면 음료수를 비교 할 때 음료수 안의 내용물과, 음료수의 포장 방식이 같으면 같은 객체이다.
      만약 내용물이 콜라이고 으로 포장된 음료수 A와같은 내용물인 콜라를 가지고 있고, 으로 되어 있는 음료수 객체 B는 같은 음료수라고 생각 할 수 있다.

이렇게 객체를 나누는 두가지 관점에 대해 알아 보았다.
그렇다면 이제 vo와 entity에 대해 알아보자!


Vo(Value Object) - 값 객체

vo(Value Object)는 값으로서 쓰일 수 있는 객체이다. vo는 해당 객체의 주소 값이 달라도 (Structural Equality,구조적 동등성)이 같으면 동일하다고 생각 할 수 있다.

만약 고유 번호(프로그래밍 세계에선 저장 된 메모리 주소)가 서로 다른 50000원 짜리 지폐 2장이 있는 경우, 이 두장의 고유 번호는 서로 다르지만 50000원 이라는 은 동일 하다.

vo는 값 자체의 비교를 위해서 equals() 와 hashCode()를 재정의 해줘야 한다

  • 서로 고유 번호가 다른 50000원 짜리는 같은 오만원 짜리로 인식 할 수 있도록 해주기 위해 재정의 한다.→ Structural Equality으로 비교하기 위해

Entity

Entitiy는 Id로 구분 된다(Identifier Equality). 따라서 고유한 식별자가 존재한다. 또한 대부분 가변적이며, 수명이 존재한다.
→ 엔티티 고유의 라이프 사이클이 존재한다!

만약 이름이 홍길동이고 계급이 상병인 군인이 있다. 어느날 후임이 었던 동명이인의 일병 홍길동이 진급을 해서 상병 홍길동이 되었다. 이때 이둘은 이름과 계급 모두 같다. 그렇다면 이 두명은 같은 군인인가?
아니다.
군번이라는 Id를 통해서 이 두명이 서로 다른 군인이라는 것을 구별 할 수 있다.
따라서 Entity는 Identifier Equality 으로 객체를 비교한다.

→ 그렇기 때문에, 식별자를 기준으로 equals() 와 hashCode()를 재정의 해줘야한다.


수명의 관점으로 보는 vo와 Entity

entity는 수명이 있다.

  • 객체가 어떻게 변화했는지, 어떤 상태인지에 대한 기록들을 가진다.

Value Object는 수명이 없다.

  • 쉽게 생성 및 삭제 가능
  • 수명이 없기 때문에 언제든지, 값 객체를 생성하여 대체 가능
    → 은행에서 50000원을 잠시 빌리고, 다른 50000원으로 갚아도 문제가 없다.
    - 은행에서는 50000원을 Structural Equality으로 판단하고 같은 50000원이라고 판단한다. → 이는 vo의 대체 가능성을 의미한다.
  • vo는 독립적으로 존재 할 수 없다.
    • 항상 entity에 속해서 존재한다.
    • vo는 값을 표현한다. 이러한 값을 가지고 있는 entity의 문맥안에서만 의미를 가진다.

불변성

value Object는 불변(Immutable)이어야만 한다!

  • value Object는 말 그대로 객체이다. 따라서 값을 변경 할 때에는 새로운 값 객체로 갈아 끼워주면 된다.
  • value Object를 변형 시킨다면, 값 객체는 Life Cycle을 가지게 된다.
    • 값 객체가 고유의 Life Cycle을 가지게 되면, 객체는 고유의 식별자를 가져야 하게 되고 이는 value object의 정의와 멀어지게 된다. → 따라서 vo는 불변적이어야 Life Cycle을 가지지 않게 되고, 이는 어느 상태의 순간 (값)이라는 것을 의미한다.
  • 어떤 객체를 불변으로 만들지 못하면, 그 객체는 vo로서도 사용 될 수 없다.

Entity는 대부분 가변(Mutable)이다.

  • 특정 vo들을 필드로 가지는 entity가 있는 경우, 해당 entity의 Life Cycle의 따라서 vo들은 새로운 vo로 바뀌게(대체) 될 수 있다. 따라서 Entity는 대부분 가변적이다.

그렇다면 도메인 모델을 설계할 때, 어떻게 VO 객체인지 판별하나?

  • 특정 객체를 같은 속성으로 이루어진 다른 객체로 대체 할 수 있으면 Value Object라고 볼 수 있음.
    • 아메리카노와 아이스를 가지고 있는 음료 객체 A가 있다. 만약 아메리카노와 아이스를 가지고 있는 다른 음료 객체B로 A를 대체 할 수 있다면, 음료 객체는 VO로서 사용되도록 설계 할 수 있다.

0개의 댓글