Proxy
왜 사용하나????????
사용 주요 목적은 데이터베이스 조회를 최적화하고 성능을 향상시킵니다
엔티티 간의 연관 관계가 있을 때, 항상 모든 연관된 엔티티를 함께 조회하는 것은 필요하지 않을 수 있습니다. 이로 인해 불필요한 데이터베이스 조회가 발생할 수 있습니다. 이러한 상황에서 실제로 해당 연관된 엔티티가 필요한 시점에 데이터베이스 조회를 지연시키기 위해 프록시를 사용할 수 있습니다.
프록시는 실제 엔티티 객체를 대신하여 엔티티에 접근할 수 있는 가짜 객체입니다. 이 가짜 객체는 실제 데이터를 가지고 있지 않고, 대신 실제 데이터가 필요한 시점에 데이터베이스에서 데이터를 로딩합니다. 이를 통해 불 필요한 데이터 로딩을 피하고, 필요한 시점에서만 데이터를 가져와 사용할 수 있습니다. 따라서 프록시 객체는 실제 엔티티 객체를 대신하여 연관된 엔티티에 대한 접근을 지연시키는 역할을 합니다. 이를 통해 애플리케이션의 성능을 최적화하고, 필요한 데이터만을 필요한 시점에 가져와 사용할 수 있게 합니다.
Basic Proxy
Porxy JPA에서는 em.find 말고도 em.getReference라는 참조를 가져오는 메서드를 제공해 줍니다. 여기서 em.find는 데이터베이스를 통해 실제 엔티티 객체를 바로 조회하는 것이고 em.getReference는 데이터베이스 조회를 미루는 가짜 엔티티 객체로 DB에 쿼리는 출력하지 않지만 객체가 조회되는 것을 의미합니다
Proxy 초기화
member.getName()과 같은 프록시 객체의 메서드 호출시, 프록시는 실제 데이터 필요성을 감지하고 초기화를 시작합니다. 이 과정에서 실제 엔티티가 아직 생성되어 있지 않으면 영속성 컨텍스트에 실제 엔티티 생성을 요청하며 이를 Initialization이라고 합니다. 그 후 영속성 컨텍스트는 데이터베이스로부터 해당 엔티티의 데이터를 조회하여 필요한 정보를 가져와 실제 엔티티 객체를 생성합니다. 이렇게 생성된 실제 엔티티 객체를 프록시는 참조(프록시 객체는 실제 엔티티 객체를 생성하는 과정에서, 실제 엔티티 객체의 참조를 내부에 보관합니다)로 보관합니다.
프록시 객체는 이제 생성된 실제 엔티티 객체의 getName() 메서드를 호출하여 결과를 반환합니다. 이 과정에서 프록시는 실제 엔티티에 대한 접근을 통해 원하는 작업을 수행하게 됩니다. 이렇게 프록시는 필요한 시점에 실제 엔티티를 생성하고 그 후 실제 엔티티를 활용하여 작업을 수행하는 구조입니다.
Proxy 특징
프록시 객체는 처음 사용할 때 한 번만 초기화됩니다. 이때 초기화되는 것은 프록시 객체 자체가 아니라 실제 엔티티의 데이터를 가져와서 채워넣는 것입니다. 이러한 초기 과정에서 프록시 객체를 통해 실제 엔티티에 접근할 수 있게 됩니다. 또한 실제 엔티티를 상속받은 객체이므로 타입 체크 시 주의가 필요합니다. 프록시와 실제 엔티티는 같은 타입이지만, 프록시인지 실제 엔티티인지 구분하여 사용해야 합니다. 프록시 인지 확인 하기 위해서는 보통 instanceOf를 사용하거나 Hibernate.isInitialized()메서드 등을 활용하면 프록시와 실제 엔티티를 올바르게 다룰 수 있습니다.
Proxy 코드
import javax.persistence.*;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
// Getters and setters
}
// 프록시 예제
public class ProxyExample {
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("Your_Persistence_Unit_Name");
EntityManager entityManager = entityManagerFactory.createEntityManager();
// 프록시로 로딩할 Book 엔티티 생성
Book proxyBook = entityManager.getReference(Book.class, 1L);
// 프록시 객체를 통해 실제 엔티티 접근 (실제로 데이터 로딩)
// 이때 실제 엔티티가 로딩되며, 프록시가 실제 엔티티로 대체되는 것은 아니다.
System.out.println("Proxy Book Title: " + proxyBook.getTitle());
entityManager.close();
entityManagerFactory.close();
}
}
Book 엔티티를 가정하고 EntityManager를 사용하여 프록시 객체를 얻어오고, 프록시 객체를 통해 실제 엔티티에 접근하는 방법이며 Hibernate의 getReference 메서드를 사용하여 프록시를 가져오고 실제로 엔티티 필드에 접근하여 데이터 가져오는 것을 확인할 수 있습니다.
'Spring(Boot & FrameWork)' 카테고리의 다른 글
지연로딩, 즉시로딩 (0) | 2023.12.26 |
---|---|
@OneToOne/ @ManyToMany (0) | 2023.12.21 |
@ManyToOne / @OneToMany (0) | 2023.12.20 |