JPA

값 타입 - 기본 값 타입, 임베디드 타입(1)

방구석 대학생 2020. 10. 21. 20:19

"인프런 - 자바 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 에서 어떻게 사용할 수 있을까?

이 다음에 이어지는 글에서 좀 더 자세히 알아보자.