오봉이와 함께하는 개발 블로그

JPA - 값 타입과 불변 객체 본문

BE/JPA

JPA - 값 타입과 불변 객체

오봉봉이 2022. 6. 29. 01:47
728x90

값 타입과 불변 객체

값 타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념이다.
따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.

값 타입 공유 참조

임베디드 타입 같은 값 타입을 여러 엔티티에서 공유할 수는 있지만 공유하면 위험하다.


다음과 같이 있을 때 OldCity를 NewCity로 변경하면 회원1과 회원2 모두 NewCity로 값이 바뀌게 된다.

Address address = new Address("city", "address", "10000");

Member member1 = new Member();
member1.setName("member1");
member1.setHomeAddress(address);
em.persist(member1);

Member member2 = new Member();
member2.setName("member2");
member2.setHomeAddress(address);
em.persist(member2);

위 코드는 member1이나 member2나 컬럼에 모두 같은 값이 들어간다.

어느날 member1만 컬럼 값을 수정하고 싶어서

member1.getHomeAddress().setCity("newCity");

위 코드를 실행해서 member1의 값만 바뀌는 것을 원했지만, member2도 똑같이 newCity라는 값으로 업데이트 되었다.

이럴 때는 어떻게 해결해야 할까?

값 타입 복사

값 타입의 실제 인스턴스인 값을 공유하는 것은 위험하기 때문에 값(인스턴스)를 복사해서 사용하자.

Address address = new Address("city", "address", "10000");

Member member1 = new Member();
member1.setName("member1");
member1.setHomeAddress(address);
em.persist(member1);

Address copyAddress = new Address(address.getCity(), address.getStreet(), address.getZipcode())

Member member2 = new Member();
member2.setName("member2");
member2.setHomeAddress(copyAddress);
em.persist(member2);

member1.getHomeAddress().setCity("newCity");

이렇게 실행하면 member1의 값만 바뀌게 된다.

하지만, 실수로 copyAddress를 사용하지 않고 그대로 address를 사용했을 때 컴파일러 단계에서 오류를 띄워줄 수 있는 방법이 있을까?
-> 없다.

객체 타입의 한계

  • 항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있다.
  • 문제는 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입이 아니라 객체 타입이다.
  • 자바 기본 타입에 값을 대입하면 값을 복사한다.
  • 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.
  • 객체의 공유 참조는 피할 수 없다.
int a = 10;
int b = a; // 기본 타입은 값을 복사
b = 4;
// a = 10, b = 4
Address a = new Address("old");
Address b = a; // 객체 타입은 참조를 전달
b.setCity("new");
// a.city = new, b.city = new

불변 객체

  • 객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단할 수 있다.
  • 값 타입은 불변 객체(immutable object)로 설계해야함
    • 불변 객체 : 생성 시점 이후 절대 값을 변경할 수 없는 객체
    • 생성자로만 값을 설정하고 수정자(Setter)를 만들지 않거나 private로 만들면 된다.
    • 참고로 Integer, String은 자바가 제공하는 대표적인 불변 객체다.

불변이라는 제약으로 부작용이라는 큰 재앙을 막을 수 있게 됐다!

수정은 어떻게?

생성자를 통해서만 값을 세팅할 수 있기 때문에 통으로 갈아내야 한다.

Address address = new Address("city", "address", "10000");

Member member1 = new Member();
member1.setName("member1");
member1.setHomeAddress(address);
em.persist(member1);

Address newAddress = new Address("newCity", address.getStreet(), address.getZipcode());
member.setHomeAddress(newAddress);
출처 : 인프런 김영한 지식공유자님의 스프링 부트와 JPA 실무 완전 정복 로드맵 강의
728x90

'BE > JPA' 카테고리의 다른 글

JPA - 값 타입 컬렉션  (0) 2022.06.29
JPA - 값 타입의 비교  (0) 2022.06.29
JPA - 임베디드 타입  (0) 2022.06.29
JPA - 기본값 타입  (0) 2022.06.29
JPA - 실전 예제 5 - 연관관계 관리  (0) 2022.06.28
Comments