목표
- Jpa Proxy가 무엇인지에 대해 이해한다.
- 어떤 상황에서 Proxy를 사용해야하는지 이해한다.
Jpa Proxy란?
Proxy
Proxy는 데이터베이스 조회를 미루는, Hibernate가 만든 실제 객체를 상속받아 만들어지는 가짜 객체이다. Proxy 객체는 target이라는 이름의 변수로 실제 객체의 참조를 보관하는데 Proxy 객체를 호출하면 Proxy객체는 실제 객체의 메소드를 호출한다.
DB에서 정보를 조회하고 실제 객체를 가져올때 em.find()를 사용하는 것처럼. Proxy 객체를 가져오고 싶을때는 em.getReference()를 사용해 Proxy객체를 가져올 수 있다. 그렇다면, Proxy객체의 동작 원리는 어떻게 되는 것일까? Proxy객체를 생성하고 데이터를 읽으려 하면 그때 DB에 조회 쿼리를 요청하고 target을 통해 실제 객체의 데이터를 가져온다.
위 그림과 같이 Client가 Proxy객체의 getName()을 호출하면 Proxy객체는 영속성 컨텍스트에 실제 객체 초기화를 요청하고 영속성 컨텍스트는 DB에 조회 쿼리를 요청한다. 그런 다음 영속성 컨텍스트에 실제 Entity가 올라오게 되고 Proxy객체는 target을 통해 실제 Entity에 접근해 데이터를 가져온다.
그렇다면, Proxy는 왜 써야할까? 간단한 예를 들어 쉽게 이해할 수 있다.
B와 연관관계를 가지고 있는 A라는 객체를 만들고 em.find()를 사용하게 되면 위와 같이 A를 조회할때 B도 같이 조회되는 모습을 볼 수 있다. 이러한 동작은 A와 B를 함께 필요로 하는 비즈니스 로직의 경우 문제가 되지 않는다. 하지만 A에 대한 정보만을 필요로 하는 비즈니스 로직의 경우 B를 같이 가져오는 것은 불필요하며 최적화가 필요하다. 이때, B를 가짜 객체인 Proxy객체로 가져와 쿼리를 최적화 할 수 있다.
프록시의 특징
1. 프록시 객체는 처음 사용할때 한번만 초기화된다.
2. 프록시 객체를 초기화 할때, 프록시 객체가 실제 엔티티로 바뀌는 것이 아니다. 초기화가 되면 프록시 객체를 통해 실제 엔티티에 접근 가능한 것이다.
3. 프록시 객체는 원본 엔티티를 상속받는다, 따라서 타입 체크시 주의해야한다. (== 비교 대신 instance of를 사용해야 한다.)
4. 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티를 반환한다.
5. 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제 발생.
[ 참고자료 ]
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard