• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

값타입과 엔티티 차이 고민

21.08.31 22:18 작성 조회수 158

0

강의 39분10초에 "엔티티는 값을 마음껏 수정할 수 있다" 는 말씀에 이해를 못하고 있습니다.

아래에는 제가 정리한 값타입의 특징과, 한 예시에 대해서 값타입/엔티티를 적용했을 때 상황을 고려해봤습니다.

마지막에 내린 결론이 올바른지 궁금합니다.

[값 타입의 특징]

- 서로 다른 두 엔티티 Member A, B는 한 값타입객체를 공유하지 말 것

- 엔티티의 필드로서 값타입(Address)에 대하여 값타입의 필드(city)를 수정하고 싶을 땐, new Address(..)로 새로운 객체를 사용할 것

혹여나 공유하는 실수를 했을 때 컴파일러로 찾아내기 어렵다. 따라서 대응책으로 setter메소드 없는 불변객체로 설계한다.

(예시) 서로 다른 회원 A, B가 한 가족이라 같은 주소에 살고있다. 그런데 A가 독립해서 주소를 옮겼다.

1.값타입 경우)

- 두 회원이 동일한 Address 값타입의 인스턴스를 공유하지 않고 각 회원별로 Address인스턴스가 달라야함.

- 따라서, memberA.getAddress( ).setCity('xxx') 로 직접 수정해도 B의 address인스턴스에 부작용 없지만,

   코딩을 할 때 실수로 동일 Address객체를 공유하도록 코드를 작성 할 수 있기에, 이를 방지하기 위해 값타입에 setter메소드정      의 안함

- 즉, setCity( )메소드를 못 쓰니까 도시속성을 바꿀 수가 없음. 따라서 memberA.setAddres(new Address( ~~) )로 새 객체를  만들어 교체해줌

2.엔티티 경우)

- 엔티티의 본래 특성상 parent엔티티 A, B가 같은 child엔티티C를 공유가능함(예. 동아리A, B는 같은 학생C를 회원으로 받을 수 있음) 

- 그러나 위 (예시)의 비즈니스 특성상 엔티티도 공유하면 안됨(한 명이 이사한 주소로 다른 한 명도 주소가 변경되는 문제)

- 엔티티 또한 아래 코드와 같이 공유하게 되면 addEntity.setCity('성남', '분당구') 로 A, B모두 주소가 변경됨

AddressEntity addrEntity = new AddressEntity('서울', '강남구');
memberA.setAddressEntity( addrEntity );
memberB.setAddressEntity( addrEntity );
 
memberA.getAddress().setCity('성남', '분당구');

- 따라서, 엔티티의 경우도 setCity와 같은 setter메소드가 있으나 회원A의 address를 얻어와  개발자 마음껏 setter수정을 할 수 없을것 같다 !?

강의의 39분10초 설명 "엔티티는 값을 마음껏 수정할 수 있다"에 반하는 결론이라 어디가 틀렸는지 짚어주셨으면 좋겠습니다.

감사합니다.

답변 1

답변을 작성해보세요.

0

안녕하세요. ddoddo님

엔티티는 값을 마음껏 수정할 수 있습니다.

따라서 비즈니스 특성상 제약이 있다면 이 부분은 그렇게 안되도록 코드로 막아야 합니다.

반면에 값 타입은 값을 수정할 수 없도록 설계했기 때문에 이런 문제가 원천 발생하지 않습니다.

감사합니다.

선생님, 강의에서와 답변내용으로 '값객체와 달리 엔티티는 수정가능한 이유'에 대해 언급이 없으셔서 다시 한 번 질문드려도 될까요..?

아래는 수정가능한 이유에 대해 좀 더 고민을 해본 내용입니다.

단순히 엔티티에 setter메소드를  정의할 수 있어서 엔티티가 수정가능하다는 것과 별개로 다른 이유는 없을까?

값객체의 경우 setter메소드를 막아 수정불가능하게 만듬. 그 이유는 값객체가 개발실수로 공유되는 코드로 작성될 경우를 대비하기 위함.  (동일한 값객체를 공유하는)두 부모 엔티티에 동시에 영향주는 것을 주의해야함.

그러나, 일대다 연관관계로 설계를 하면 위와같은 문제가 발생할 일이 없음.

일대다 연관관계의 설계가  서로 다른 두 회원(일 쪽)이 동일한 주소엔티티(다 쪽)를 공유하는 것은 불가함을 보장해주기 때문에 주소엔티티를 member.getAddressList( ).get(0) 으로 얻어와 직접 setXXX('ooo')로 수정을 하는 것이 가능하다....

안녕하세요. ddoddo님

Q: 그러나, 일대다 연관관계로 설계를 하면 위와같은 문제가 발생할 일이 없음.

-> 지금은 문제가 없어 보이지만 다른곳에서 주소 엔티티를 참조하도록 설계가 추가 된다면 문제가 발생할 수 있습니다. 예를 들어서 team -> addressList를 참조할 수 있도록 설계가 추가되는 것이지요.

반면에 값 타입은 team -> address(값타입)로 참조가 향후 추가되어도 사이드 이펙트가 발생하지 않습니다.

여기서 핵심은 일대다, 다대일 같은 조건이 아닙니다.

참조를 통한 사이트 이펙트가 발생하는가 하지 않는가 입니다. 그리고 지금 뿐만 아니라 요건이 추가되었을 때도 함께 고려해야합니다.

감사합니다.

긴 질문글을 올리게 돼 죄송합니다.

그리고 명확한 설명에 감사드립니다.

이제야 이해가 됐습니다...ㅠㅠ

이해가 되셨다니 다행입니다^^