테이블과 매핑되는 엔티티를 정의할 때는 Id 값이 필수로 들어갑니다. 우리는 주로 Long 타입으로 정의를 하곤 합니다.
근데 왜 Wrapper 타입인 Long을 사용하는 걸까요? Primitive 타입인 long 도 있는데, 이것을 사용하면 안 되는 걸까요?
분명히 어떤 이유가 있을 겁니다. 그러려면 우선 Primitive와 Wrapper의 차이점 부터 알아보아야겠습니다.
Primitive Type vs. Reference Type
우선 자바의 변수 타입에는 기본형(Primitive Type)과 참조형(Reference Type)이 있습니다.
int age = 3; // 기본형
Point p1 = new Point(5, 4); // 참조형
두 개의 차이점은, 기본형은 변수의 값을 그대로 저장하지만 참조형은 해당 객체의 주솟값을 저장한다는 것입니다.
참조형은 객체를 다루고, 기본형은 그렇지 않다 라는 것을 알고 넘어가면 되겠습니다.
나는 기본형으로 컬렉션을 만들고 싶은데...
제가 알고 당신이 알고 우리 모두가 알다시피 Java는 객체지향 언어입니다. 그래서 그런지 컬렉션의 타입에 객체를 다루지 않는 Primitive Type을 넣을 수가 없습니다.
하지만 저는 int타입 컬렉션을 만들고 싶은데요... 하시는 분들을 위해 Java가 마련한 것이 바로 Wrapper 클래스입니다.
Wrapper 클래스는 단어 뜻 그대로(wrap: 감싸다) 기본형을 객체로 한 번 감싼 클래스입니다. 때문에 기본형을 객체로 다룰 수 있게 되어 컬렉션 타입에도 쓸 수 있습니다.
Wrapper 클래스는 본래의 Primitive Type과 유사한 단어를 사용하였기 때문에 영어를 읽을 줄 안다는 가정 하에, 해당 Wrapper의 본래 Primitive Type을 추적하는 것은 어렵지 않을 것입니다. 그러나 저는 친절하기 때문에 한 번 보여드리고 넘어가겠습니다.
Primitive Data Type | Wrapper Class |
double | Double |
float | Float |
long | Long |
int | Integer |
short | Short |
byte | Byte |
char | Character |
boolean | Boolean |
그렇다면 왜 Entity Id에는 Wrapper Class를 사용하는 거야?
여기서 Wrapper Class와 Primitive Data Type의 차이점이 나옵니다. 바로 Wrapper는 객체를 다루기 때문에, null 값을 사용할 수 있기 때문입니다.
Primitive Data Type은 기본 값이 0이기 때문에, long의 값이 0이라면 실제로 id 값이 0인 건지 아니면 값이 없는 건지 구분하기가 어렵습니다. 그러나 Wrapper Class인 Long을 쓰면 null을 사용할 수 있기 때문에 id 값이 없는 것을 확실히 구분할 수 있을 것입니다.
실제로 JPA 공식 문서에서도 Wrapper 타입을 권장하고 있습니다.
그러면 모든 타입을 Wrapper Class로 쓰면 좋겠네! 당장 바꿔야지!
라고 생각하면 위험합니다. 사실 모든 것에는 trade-off가 있죠. Wrapper Class는 Primitive 타입보다 비용이 더 비쌉니다.
Wrapper Class는 결국 객체를 생성하는 것인데, 해당 과정이 Primitive Type보다 메모리 측면에서 비효율적이기 때문에 각각의 장단점이 있다고 보시면 됩니다. 괜히 척척박사님들이 Primitive Type을 만드신 게 아니겠죠(...)
평소에는 Primtivie Type을 쓰고, 객체가 필요하거나 null 값을 반환할 필요가 있는 경우에는 Wrapper Class를 선택하면 되겠습니다.
'Java & Spring Boot' 카테고리의 다른 글
DTO와 VO의 차이를 알아보자 (0) | 2022.09.18 |
---|---|
Java Stream과 for문은 무엇이 다를까? (0) | 2022.08.18 |
Java를 버전 별로 비교해보자 (0) | 2022.08.01 |
SOLID 원칙을 이해하기 쉽게 알아보자 (0) | 2022.06.22 |
Gradle의 여러가지 의존성 옵션 (0) | 2022.06.05 |