값 타입과 불변 객체
Last updated
Was this helpful?
Last updated
Was this helpful?
값 타입은 복잡한 객체를 단순화하기 위해 만든 개념이다.
따라서 값 타입을 단순하고 안전하게 다룰 수 있어야 한다.
임베디드 타입 등 값 타입을 여러 Entity에서 공유하면 위험하다.
회원 1과 회원 2가 같은 city를 갖고 있을 때 회원 1의 city를 바꾸면 회원 2의 city도 바뀐다.
일단 같은 주소를 회원 1, 2에게 넣어준다.
그리고 나서 회원 1의 주소를 바꾼다면?
업데이트 쿼리가 두 번 나간 것을 볼 수 있다.
실제 데이터도 회원 1, 2 모두가 바뀌었다. 이런 버그는 찾기가 굉장히 어렵다.
값 타입의 실제 인스턴스 값을 공유하는 것은 매우 위험하다.
일부러 데이터를 공유해서 사용하고 싶다면 임베디드 타입이 아니라 Entity로 만들어서 공유해야 한다.
대신, 값(인스턴스)를 복사해서 사용해야 한다.
값을 복사해서 사용해야 의도대로 데이터가 돌아간다.
항상 값을 복사해서 사용하면 공유 참조 때문에 발생하는 부작용을 피할 수 있다.
그런데 임베디드 타입 등 직접 정의한 타입은 자바 기본 타입이 아니라 객체 타입이다.
primitive 같은 값 타입은 =
으로 할당해도 복사해서 들어가서 두 변수를 한 번에 수정하는 사이드 이펙트가 발생하지 않는다.
객체 타입은 참조 값을 직접 가지므로 둘 다 값이 바뀌는 사이드 이펙트를 막을 방법이 없다.
즉, 객체의 공유 참조는 피할 수 없다.
만약 실수로 복사한 값 대신 이전 값을 집어넣는다면, 컴파일 단계에서 이 문제를 짚어낼 수 없다.
기본 타입은 값을 복사하기 때문에 문제가 없지만, 객체 타입은 참조를 전달하기 때문에 변경하면 둘 다 반영되는 부작용이 발생한다.
생성 시점 이후 절대 값을 변경할 수 없는 객체
Integer, String은 자바가 제공하는 대표적인 불변 객체다.
생성자로만 값을 설정하고 수정자(setter)를 만들지 않으면 된다.
객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단할 수 있다.
값 타입은 불변 객체로 설계해야 한다.
값을 바꾸고 싶다면 새롭게 객체를 생성해서 넣어주어야 한다.