본문 바로가기

개발중/Java Persistence API (JPA)

JPA - 즉시 로딩과 지연 로딩

728x90
반응형


즉시 로딩과 지연 로딩

프록시 객체는 주로 연관된 엔티티를 지연 로딩 할 때 사용한다.

 

Member member = em.find( Member.class, "binsoo" )

 

- 객체 그래프 탐색

Team ream = member.getTeam()

 

- 팀 엔티티 사용

team.getName()

 

회원 엔티티를 조회할 때 연관된 팀 엔티티도 함께 DB 에서 조회하는 것이 좋을까 ?

아니면 회원 엔티티만 조회해두고 팀 엔티티는 실제 사용하는 시점에 DB 에서 조회하는 것이 좋을까 ?

 

  • 즉시 로딩 - EAGER LOADING
    • 엔티티를 조회할 때 연관된 엔티티도 함께 조회한다.
    • 하이버네이트는 가능하면 SQL 조인을 사용해서 한 번에 조회한다.
    • 설정 방법
      • @ManyToOne( fetch = FetchType.EAGER )
  • 지연 로딩 - LAZY LOADING
    • 연관된 엔티티를 실제 사용할 때 조회한다.
    • 연관된 엔티티를 프록시로 조회한다. 프록시를 실제 사용할 때 초기화 하면서 DB 를 조회한다.
    • 설정 방법
      • @ManyToOne( fetch = FetchType.LAZY)

 

처음부터 연관된 엔티티를 모두 영속성 컨텍스트에 올려두는 것은 현실적이지 않고,

필요할 때마다 SQL 을 실행시켜 연관된 엔티티를 지연 로딩 하는 것도 퇴적화 관점에서 보면 꼭 좋은 것은 아니다.

 

예를 들어서 대부분의 애플리케이션 로직에서 회원과 팀 엔티티를 같이 사용한다면

SQL 조인을 사용해서 회원과 팀 엔티티를 한번에 조회하는 것이 효율적이다.

 

결국 연관된 엔티티를 즉시 로딩하는 것이 좋은지는 상황에 따라 다르다.

 

 

JPA 의 기본 패치 전략

  • @ManyToOne / @OneToOne
    • 즉시 로딩
  • @OneToMany / @ManyToMany
    • 지연 로딩

JPA 의 기본 패치 전략은 연관된 엔티티가 하나면 즉시 로딩을, 컬렉션이면 지연 로딩을 사용한다.

 

컬렉션을 로딩하는 것은 비용이 너무 많이 들고 잘못하면 너무 많은 데이터를 로딩할 수 있기 때문이다.

예를 들어 특정 회원이 연관된 컬렉션에 데이터를 수만건 등록 했는데

설정한 패티 전략이 즉시 로딩이면 해당 회원을 로딩하는 순간 수만건의 데이터도 함께 로딩이 된다.

 

반면에 연관된 엔티티가 하나면 즉시 로딩해도 큰 문제가 발생하지 않는다.

 

추천하는 방법은 모든 연관관계에 자연 로딩을 사용하는 것이다.

 

그리고 애플리케이션 개발이 어느 정도 완료 단계에 있을 때 실제 사용하는 상황을 보고

꼭 필요한 곳에만 즉시 로딩을 사용하도록 최적화 하면 된다.

 

참고로 SQL 문을 직접 사용하면 이런 유연한 최적화가 어렵다.

예를 들어 SQL 로 각각의 테이블을 조회해서 처리하다가 조인으로 한번에 조회하도록 변경하면

많은 SQL 과 애플리케이션 코드를 수정해야 한다.


 

728x90
반응형