Jun's note

[JPA] 프록시(Proxy), 지연로딩(LAZY)와 즉시로딩(EAGER) 본문

Programming/JPA

[JPA] 프록시(Proxy), 지연로딩(LAZY)와 즉시로딩(EAGER)

junning 2022. 1. 23. 19:04
728x90

프록시와 지연로딩이 서로 연관있기때문에 프록시, 지연로딩, 즉시로딩에 대해 정리해보겠다.

 

먼저 프록시가 나오게된 상황을 생각해보자.

(상황)

예를 들어, Member와 Team이 서로 연관되어있다. Member를 조회할때 Team을 항상 조회해야할까?

이 둘을 같이 조회해야되면 같이 조회하면되지만, 그렇지 않을때도 있다. 필요하지도 않는데 항상 같이 조회하면 성능이 저하될 수도 있다.

이럴땐 어떻게 해야하나?

 

(답은)

필요할때만 해당 엔티티를 조회하면 된다.(즉시로딩) 

 

(이 상황에 대해 더 쉽게 생각해보면, 게시물을 조회할때 댓글창을 클릭하지도 않았는데 댓글도 같이 조회되어야하는가? 성능문제와 관련있기 때문에 이 문제에 있어 생각해봐야한다)

즉시로딩에서 실제 엔티티안에는 프록시라는 가짜 엔티티가 있다!

 

 

1. 프록시 (Proxy)

쉽게 말하면 가짜 엔티티이다.

엔티티를 실제 사용하는 시점까지 DB 조회를 미루고싶을때 사용한다.

  • 사용 방법
    • EntityManager.getReference() 메소드를 사용하면 프록시객체를 호출한다.
    • 이 메소드를 호출하면, 실제 엔티티 객체를 만들지 않고 + DB에 조회하지 않는다.
  • 특징
    • 실제 엔티티 클래스를 상속받는다.
    • 실제 클래스와 겉모양이 같다.
    • 프록시 객체는 실제 객체의 참조(target)을 보관한다.
    • 프록시 객체를 호출하면 실제 객체의 메소드를 호출한다.
  • '프록시 객체의 초기화' 과정
    • 프록시 객체 메소드를 호출했을때, 영속성 컨텍스트에 실제 엔티티가 없을 경우 DB에서 조회한다.
    • 프록시 객체는 무조건 target을 통해 값을 얻는다. target에 값이 없으면 DB 조회를 하고, target에 값이 있으면 프록시 객체가 아닌 실제 객체를 반환한다.
    • getId(식별자)를 구할때에는 프록시 객체로 구할 수 있다. 
      1. 1. 프록시 객체 메소드가 호출되어, 프록시 객체가 가르키는 실제 객체(target)이 없을 경우(null) (실제객체는 영속성 컨텍스트안에 존재)
      2. 2. 초기화 요청 (target이 null이면 영속성 컨텍스트에도 존재하지 않음)
      3. 3. DB를 조회하여 영속성 컨텍스트에 저장
      4. 4. 영속성 컨텍스트에 있는 실제 엔티티를 가져온다. (프록시 객체 target에 실제 엔티티 매핑)
      5. 5. 프록시 객체의 target을 통해 원하는 값을 가져온다.

프록시 객체의 초기화

  • 프록시 객체 사용시 주의사항 (예외)
    • 프록시 객체를 초기화 할때 영속성 컨텍스트의 도움을 받아야 가능하다.
    • 영속성 컨텍스트의 도움을 받을 수 없는 상황(준영속)에는 프록시를 초기화하면 문제 발생하다. (org.hibernate.LazyInitializationException 예외)

2. 지연로딩(LAZY)

  • 필요한 엔티티만 조회한다. (DB에서)
  • 실무에서는 지연로딩을 지향해야한다.
  • @OneToMany, @ManyToMany 은 지연로딩을 기본 전략으로 사용한다.

 

3. 즉시로딩(EAGER)

  • 어떤 한 엔티티를 조회할때, 그와 연관된 모든 엔티티를 다 조회한다.
  • 단점: 필요이상으로 모든 엔티티를 조회하기 때문에 성능이 저하될 수도 있고, 어떻게 join되는지 자세히 알 수 없기때문에 즉시로딩을 사용하는 것은 매우 위험하다.
  • @ManyToOne , @OneToOne 은 즉시로딩을 기본 전략으로 사용하고 있기 때문에 지연로딩을 명시해줘야한다.
    • 사용 방법: @ManyToOne(fetch = FetchType.LAZY)

 

정리하면,

- 실무에서 지연로딩을 사용해야한다. 그런데 즉시로딩을 구해야하는 경우가 있으면 "지연로딩+join fetch"로 구현

- 지연로딩- 가끔 사용될때, 즉시로딩- 함께 자주 사용될때

 

 


참고
강의 : www.inflearn.com/course/ORM-JPA-Basic
서적 : <자바 ORM 표준 JPA프로그래밍> 김영한
Comments