값 타입 - 기본 값 타입, 임베디드 타입(1)
"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."
www.inflearn.com/course/ORM-JPA-Basic#
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그
www.inflearn.com
JPA 는 데이터 타입을 최상위 레벨로 보았을 때, Entity 타입과 값 타입, 총 2가지로 분류한다.
- Entity 타입
@Entity 어노테이션으로 정의하는 객체로 데이터가 변해도 식별자로 지속해서 추적이 가능하다.
예시 : 회원 Entity 의 키나 나이 값을 변경해도 식별자(기본 키) 로 인식이 가능하다.
- 값 타입
int, Integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입(primitive type) 이나 객체(Object)로 식별자 없이 값만 있기 때문에 데이터를 변경 할 시 추적이 불가능하다.
예시 : 숫자 100 을 200 으로 변경하면 완전히 다른 값으로 대체된다.
* 값 타입은 크게 3가지로 다시 분류된다.
- 기본 값 타입 : 자바 기본 타입(primitive type), 래퍼 클래스(Wrapper class : Integer, Long), String
- 임베디드 타입(Embedded Type, 복합 값 타입) : JPA 에서 정의하여 사용할 수 있는 타입
예시 : x,y 좌표가 있다고 했을 때 그걸 묶어서 클래스로 사용하고 싶은 경우, 즉 포지션과 같은 속성을 하나로 묶어서 사용하고 싶을 때 사용할 수 있는 것이 임베디드 타입이다.
- 컬렉션 값 타입(Collection Value Type) : 임베디드 타입과 같이 JPA 에서 정의하여 사용할 수 있는 타입으로, 자바 컬렉션에 기본 값 타입이나 임베디드 타입을 넣을 수 있는 걸 컬렉션 값 타입이라고 한다.
* 우선 임베디드 타입에 대한 이해를 쉽게 하기 위해 기본 값 타입에 대한 것부터 먼저 알아보자.(자바를 배우기 시작하고 며칠 정도면 배울 수 있는 내용들이다.)
기본 값 타입
- 가장 중요한 특징으로 생명주기(Life Cycle) 를 Entity 에 의존한다는 것이 있다.
예시 : 회원을 삭제하면 이름, 나이 필드도 함께 삭제된다.
- 값 타입의 value 자체는 절대로 공유하면 안된다.
예시 : 회원 이름 변경 시 다른 회원의 이름도 함께 변경되면 안된다.(side - effect 효과)
* 참고로 자바의 기본 타입은 절대로 공유되지 않는다, 그렇기 때문에 값 타입을 사용하면 안전하게 side - effect 효과 없이 개발 할 수 있다.
아래의 코드를 살펴보자.
- ValueMain.java
public class ValueMain {
public static void main(String[] args){
int a = 10;
int b = a;
a = 20;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
코드를 위와 같이 작성했을 때 a 의 값을 중간에 바꿨다고 해서, 앞전에 a 의 값을 대입 받은 b 의 값이 달라지진 않는다.
즉, 기본 타입(primitive type)은 값을 공유하지 않는다는 뜻이다.
(애초에 변수 별로 메모리 또한 따로따로 할당받기 때문에 공유될 수 없다.)
그런데 Integer 와 같은 래퍼 클래스(Wrapper class) 의 경우는 다른 래퍼 클래스 변수에 값을 대입하게 되면 reference(참조) 를 가져가게 되어서 문제가 발생한다.
즉, 참조를 가져감으로서 값이 공유 된다는 소리이다.
- ValueMain.java
Integer a = new Integer(10);
Integer b = a;
// 이와 같은 경우 a의 값 자체가 넘어가는 것이 아니라 a 의 메모리 참조 값이 넘어간다.
// C언어의 포인터와 비슷한 주소 참조 개념(객체 reference)
// 만약 여기서 setValue 와 같은 메소드를 이용해 a 의 값을 변경해주면 b 의 값도 함께 변경되어 버린다.
// b 에 a 의 reference 가 넘어가서 같은 인스턴스를 공유하기 때문이다.
- Integer 같은 래퍼 클래스나 String 같은 특수한 클래스는 공유 가능한 객체이지만 값을 변경할 수 없다.
: 자바에서 클래스는 참조값을 공유하는 것을 막을 수 있는 방법이 없다. 그래서 아예 변경 자체를 아예 불가능하게 만들어서 side - effect 효과가 아예 발생하지 않게 만든다.
임베디드 타입(Embedded Type, 복합 값 타입)
- 우선 알아야 할 점으로, 임베디드 타입 역시 기본 값 타입이라는 것이다.
즉, 값이 변경되면 추적이 불가능하다.
- 새로운 값 타입을 직접 정의할 수 있다.
- 주로 기본 값 타입을 모아서 만들기 때문에 복합 값 타입이라고도 한다.
* 예제 코드에서 Member 클래스를 보면 회원 Entity 에서 근무 시작일 과 근무 종료일(startDate, endDate), 그리고 도시, 번지, 우편번호(city, street, zipcode) 와 같은 비슷한 속성들이 있는 것을 확인할 수 있는데 이들을 현재 시스템에서 공통으로 사용할 수 있지 않을까 라는 생각이 들 것이다.
회원 Entity 에서 비슷한 속성들을 묶어 보면 도메인 클래스에 있는 필드들을 좀 더 추상화해서 다음과 같이 쉬운 표현이 가능할 것이다.
"회원 Entity 는 이름, 근무 기간(Period), 집 주소(Address)를 가진다"
위의 추상화와 같이 비슷한 속성을 하나로 묶어 주는 것을 임베디드 타입이라고 한다.
위의 그림과 같이 추상화된 표현을 통해 Period(startDate, endDate) 와 Address(city, street, zipcode) 라는 임베디드 타입을 만들어 낼 수 있다.(쉽게 얘기하자면 클래스 2개를 뽑아낸것)
그런데 이것을 JPA 에서 어떻게 사용할 수 있을까?
이 다음에 이어지는 글에서 좀 더 자세히 알아보자.