Home 프록시
Post
Cancel

프록시

프록시

  • 엔티티를 조회할 때 연관된 엔티티들이 항상 사용되는 것은 아니다.
  • JPA는 이런 문제를 해결하려고 엔티티가 실제 사용될 때까지 데이터베이스 조회를 지연하는 방법을 제공하는데 이를 지연 로딩이라고 한다.
  • 지연 로딩 기능을 사용하려면 실제 엔티티 객체 대신에 데이터베이스를 지연할 수 있는 가짜 객체가 필요한데 이를 프록시 객체라고 한다.

프록시 동작

  • 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶으면 em.getReference() 메서드를 사용하면 된다.
  • 이 메소드를 호출할 때 JPA는 데이터베이스를 조회하지 않고 실제 엔티티 객체도 생성하지 않는다.
  • 대신 데이터베이스에 접근을 위임한 프록시 객체를 반환한다.

  1. 프록시 객체에 member.getName()을 호출해서 실제 데이터를 조회
  2. 프록시 객체는 실제 엔티티가 생성되어 있지 않으면 영속성 컨텍스트에 실제 엔티티 생성을 요청하는데 이를 초기화라 한다.
  3. 영속성 컨텍스트는 데이터베이스를 조회해서 실제 엔티티 객체를 생성
  4. 프록시 객체는 생성된 실제 엔티티 객체의 참조를 Member target 맴버변수에 보관
  5. 프록시 객체는 실제 엔티티 객체의 getName() 을 호출해서 결과를 반환

프록시 특징

  • 프록시 객체는 처음 사용할 때 한번만 초기화된다.
  • 프록시 객체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다.
    • 프록시 객체가 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.
  • 프록시 객체는 원본 엔티티를 상속받은 객체이므로 타입 체크 시 주의해야함.
  • 영속성 컨텍스트에 찾는 엔티티가 존재하면 getTeference()를 호출해도 실제 엔티티를 반환
  • 초기화는 영속성 컨텍스트의 도움을 받아야 가능한데 도움을 받을 수 없는 준영속 상태의 프록시를 초기화시 LazyInitializationException 예외 발생
    • 예시 : em.close() 메소드로 영속성 컨트스트를 종료하고 프록시를 초기화하면 예외가 발생

프록시와 식별자

  • 엔티티를 프록시로 조회할 때 식별자(PK) 값을 파라미터로 전달하는데 프록시 객체는 이 식별자 값을 보관한다.
1
2
Team team=em.getReference(Team.class,"team"); //식별자 보관
  team.getId(); //초기화되지 않음
  • 위의 경우는 @Access(AccessType.PROPERTY)에만 적용된다.
    • 만약 AccessType.FIELD로 한다면 getId()메소드가 id만 조회하는 메소드인지 알지 못하므로 프록시를 초기화한다.

프록시 확인

  • JPA가 제공하는 PersistenceUnitUtil.isLoaded(Object entity) 메소드를 사용하면 프록시 인스턴스의 초기화 여부를 확인할 수 있다.

프록시와 즉시 로딩, 지연 로딩

  • 처음부터 연관된 엔티티를 모두 영속성 컨특스트에 올려두는 것은 현실적이지 않고, 필요할 때마다 SQL을 실행해서 연관된 엔티티를 지연 로딩하는 것도 최적화 관점에서 보면 꼭 좋지많은 않다.
  • 항상 같이 쓴다면 즉시 로딩으로 SQL 조인을 사용해서 조회하는 것이 더 효율적이다.
This post is licensed under CC BY 4.0 by the author.