인프런 커뮤니티 질문&답변

SangJun An님의 프로필 이미지
SangJun An

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

값 타입과 불변 객체

임베디드 타입의 setter 메소드를 수정해도 될까요?

해결된 질문

작성

·

159

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]
안녕하세요.
 
java에서 객체를 복사할 때 값이 아니라 주소를 복사해서 참조하기때문에 발생하는 문제를 방지하기 위해 약간의 불편함을 감수하고 임베디드 타입 객체를 불변객체로 만든다고 이해했습니다.
 
그렇다면 임베디드 타입 객체를 불변객체로 사용하는 것 대신에 Member 객체 안에서 임베디드 타입을 저장하는 setter 메소드를 수정(마치 연관관계 편의 메소드처럼)해서 항상 새로운 객체를 만들도록 사용해도 괜찮을까요?
public void setHomeAddress(Address homeAddress) {
this.homeAddress = new Address(homeAddress.getCity()
, homeAddress.getStreet()
, homeAddress.getZipcode());
}
 
그러면 Address 임베디드 타입 내에 필드값이 많을때 조금 더 편리하지 않을까 생각되어서 여쭤봅니다.
Address homeAddress1 = new Address("city", "street", "zipcode");

Member member1 = new Member();
member1.setUsername("HelloJpa1");
member1.setHomeAddress(homeAddress1);

Member member2 = new Member();
member2.setUsername("HelloJpa2");
member2.setHomeAddress(homeAddress1);

em.persist(member1);
em.persist(member2);

homeAddress1.setCity("newCity"); //city에서 newCity로 변경.
member2.setHomeAddress(homeAddress1);
 

답변 1

0

안녕하세요. SangJun An님, 공식 서포터즈 David입니다.

불변객체를 사용하지 않는다면 굳이 Address를 Member 내부에서 새롭게 생성할 필요는 없어보입니다. 내부에서 생성하더라도 Member.getAddress()로 가져온 Address 객체는 상태가 변경 가능할테니까요.

불변객체를 쓰는 이유는 편리하기 위함이 아니라 객체가 생성된 이후 상태 변경을 막고자 함입니다:)

감사합니다.

SangJun An님의 프로필 이미지
SangJun An
질문자

안녕하세요. 답변 감사드립니다.

 

제가 궁금한 점은 임베디드 타입의 객체 하나를 여러 Entity에서 사용할때 객체의 레퍼런스를 참조하면서 생기는 사이드 이펙트를 방지하기 위한 방법으로 불변객체를 사용하는 것 말고 다른 방법이 있는지 고민해보았습니다.

 

예를 들어 Address homeAddress1 임베디드 타입이 Member member1과 Member member2 Entity에 둘 다 사용되는 경우 member1의 주소 Address 객체를 가져와서 변경 시 member2의 Address도 변경되는 사이드 이펙트가 발생합니다.

이런 사이드이펙트 문제를 방지하기 위해 임베디드 타입 객체를 불변으로 사용했는데요. 저는 불변객체 사용 대신에 setAddress를 호출할 때 항상 새로운 Address를 만들어서 할당하여 서로 다른 Entity가 동일한 주소를 가지는 임베디드 타입의 객체를 참조하지 못하도록 방지하는 방법을 고민해보았습니다.

 

그러면 Member.getAddress() 로 가져온 임베디드 타입은 다른 Entity 객체에서 참조하고 있는 Address 객체와는 다르기 때문에 Address의 값을 바꾸어도 하나의 Entity에만 변경을 취하기 때문에 다른 Entity 객체가 영향을 받지 않아서 괜찮지않을까 생각해봤습니다.

 

Java에서 객체를 레퍼런스로 참조하는 방식으로 발생한 사이드 이펙트 방지하기 위해 불변 객체를 사용하는 이유만 있다면 다른 방식도 가능할꺼라고 생각했습니다. 혹시 Entity에 포함된 임베디드 타입 객체를 수정하는 것이 bad practice라는 다른 이유가 있을까요?

그러면 Member.getAddress() 로 가져온 임베디드 타입은 다른 Entity 객체에서 참조하고 있는 Address 객체와는 다르기 때문에 Address의 값을 바꾸어도 하나의 Entity에만 변경을 취하기 때문에 다른 Entity 객체가 영향을 받지 않아서 괜찮지않을까 생각해봤습니다.

=> 제 개인적인 생각을 말씀드리자면 말씀하신대로 하셔도 됩니다. 그렇게 변경이 발생했을 때 다른 객체에 영향을 주지 않게끔 할 수도 있죠. 다만, 저라면 변경의 여지를 주지 않는 편을 택할 것 같습니다. 그러면 굳이 Address가 다른 이유에 의해 변경되는 것을 고려할 필요도 없으니깐요.

SangJun An님의 프로필 이미지
SangJun An

작성한 질문수

질문하기