JPA

8장 프록시와 연관관계 관리

iksadnorth 2023. 8. 31. 23:57

해당 게시물은 책 '자바 ORM 표준 프로그래밍'을 읽고 작성했습니다.

👣 개요

해당 게시물은 프록시를 이용해서 객체의 그래프 탐색에서 지연 로딩을 하는 방법에 대해 서술할 것이다.

 

👣 프록시

연관된 엔티티를 조회하는 방법은 2가지가 있다.
즉시 로딩 : 원래 엔티티를 조회할 때, DB에서 같이 불러오는 방법
지연 로딩 : 원래 엔티티는 엔티티대로 조회하고 연관된 엔티티를 호출할 때,
그때서야 DB에서 추가적으로 로드하는 방법

지연로딩을 실현시키기 위해 연관된 엔티티를 담는 필드에 실제 엔티티를 대입하는 것이 아니라
가짜 객체를 담고 해당 객체를 호출할 때, DB에서 조회하도록 설정한다. 이것을 프록시 객체라고 한다.

// 실제 객체 호출
Member member = em.find(Member.class, 1L);

// Proxy 객체 호출
Member member = em.getReference(Member.class, 1L);

위 코드를 보면 find() 메서드는 영속성 컨텍스트에 1L의 ID가 없으면 즉시 DB에서 조회한다.
하지만 getReference() 메서드는 1L의 ID의 프록시 객체를 전달할 뿐 실제로 DB에서 조회하지 않는다.
오직 member 객체의 속성을 호출할 때, DB를 조회한다.

이 프록시의 원리는 아래와 같다.

실제 getReference() 메서드의 결과값은 내부에 Member target값이 null이었다가 내부 속성을
호출하면 그 때서야 DB를 조회한다. 한번 초기화된 객체는 target에 저장되어 이후에는 조회된 값을 사용하게 된다.
다만 프록시 객체는 getId() 메서드, 즉 ID값을 요구하는 메서드를 호출해도 초기화시키지는 않는다.

👣 JPA의 조인 전략

JPA는 연관관계를 정의하는 FK의 필드가 Null인 경우를 대비해서
주로 외부 조인을 통해 DB를 조회한다.
하지만 이런 방법은 성능을 악화시키는 요인 중 하나다.

만약 FK의 필드가 Not Null 조건이 붙는다면
JPA는 맘편히 내부 조인으로 DB를 조회한다.
이는 외부 조인에 비해 성능이 좋기 때문에 되도록
FK를 정의하는 @JoinColumn(nullable = false)를 이용해서 성능을 높여야 한다.
혹은 @ManyToOne(optional = false)를 이용해서 Not Null 조건을 붙일 수 있다.

 

👣 프록시 컬렉션 래퍼

JPA에서는 Collection 타입에 대해서도 지연 로딩을 지원하고 있다.
예를 들어, List<User> 타입의 필드를 userList라고 가정할 때,
entity.getUserList()를 호출했다고 해서 그 즉시 DB 조회를 하는 것이 아니다.
entity.getUserList().get(0)과 같이 내부 요소에 접근하려 할 때, 
DB 조회를 하는 것이다.

이것을 가능하게 해주는 것이 PersistentBag다.
이것도 마찬가지로 프록시 객체이며, 위에서 설명한 것과 같이 요소에 접근을 시도하면
DB 조회를 시도한다.

 

'JPA' 카테고리의 다른 글

10장 객체지향 쿼리 언어  (0) 2023.09.04
9장 값 타입  (0) 2023.09.03
7장 고급 매핑  (0) 2023.08.31
6장 다양한 연관관계 매핑  (0) 2023.08.31
5장 연관관계 매핑 기초  (0) 2023.08.30