본문 바로가기
Spring/JPA

즉시로딩 지연로딩

by YoonJong 2022. 9. 27.
728x90

즉시로딩과 지연로딩에 관련해서, JPA 강의에서는 프록시와 마찬가지로 첫 시작을 아래와같은 질문으로 시작한다.

Member를 조회할때 Team을 함꼐 조회해야할까?

비즈니스 로직에 따라 다르겠지만, 보통은 항상 함께 조회하지 않고 필요할때만 조회하기를 원할 거라 생각한다.

 

 

이 주제의 핵심은, 즉시로딩을 사용하지 않는다 라고 정리할 수 있다

왜 사용하지 않을지 알아보자.

 

 - 가급적 지연로딩만 사용하기

 - 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생한다.

 - 즉시 로딩은 JPQL 에서 N + 1 문제를 일으킨다.

  * 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오는 현상

 

+ 아주아주 간단한 프로젝트에서는 즉시로딩을 사용해도 된다


 

 

ManytoOneOnetoOne의 기본전략은 EAGER(즉시로딩) 으로 되어있으며,

OnetoMany 와 ManytoMany(사용X) 의 기본전략은 LAZY(지연로딩)으로 되어있다.

 

아래예제로 즉시로딩(EAGER)일때 쿼리가 어떻게 나가는지 알아보자

 

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    @Column(name = "username")
    private String name;

	// 기본전략은 EAGER
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
    ...
    ...

 

Member 를 생성해서 저장했으며, 찾는 동작을 해보았다.


// Member  생성
Member member = new Member();
member.setName("즉시로딩Test");

// Member 영속성 저장
em.persist(member);

// 쿼리를 보기 위함
em.flush();
em.clear();

// Member 찾아보기
Member findMember = em.find(Member.class, member.getId());

tx.commit();

쿼리를 보면 Team 까지 함께 조회되는 것을 볼 수 있다.

Hibernate: 
    select
        member0_.member_id as member_i1_6_0_,
        member0_.city as city2_6_0_,
        member0_.street as street3_6_0_,
        member0_.zipcode as zipcode4_6_0_,
        member0_.username as username5_6_0_,
        member0_.team_id as team_id6_6_0_,
        team1_.team_id as team_id1_11_1_,
        team1_.insert_member as insert_m2_11_1_,
        team1_.createdDate as createdD3_11_1_,
        team1_.update_member as update_m4_11_1_,
        team1_.modifiedDate as modified5_11_1_,
        team1_.name as name6_11_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.team_id=team1_.team_id 
    where
        member0_.member_id=?

 


로딩 전략을 지연로딩으로 설정했다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    @Column(name = "username")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

똑같이 Member 생성 및 조회 시 아래와 같이 Team 은 조회하지 않는 것을 볼 수 있다.

Hibernate: 
    select
        member0_.member_id as member_i1_6_0_,
        member0_.city as city2_6_0_,
        member0_.street as street3_6_0_,
        member0_.zipcode as zipcode4_6_0_,
        member0_.username as username5_6_0_,
        member0_.team_id as team_id6_6_0_ 
    from
        Member member0_ 
    where
        member0_.member_id=?

 

 

참고

https://programmer93.tistory.com/83

 

JPA N+1 문제 해결 방법 및 실무 적용 팁 - 삽질중인 개발자

- JPA N+1 문제 및 해결 방법 - JPA를 사용하다 보면 의도하지 않았지만 여러 번의 select 문이 순식간에 여러 개가 나가는 현상을 본 적이 있을 것이다. 이러한 현상을 N+1문제라고 부른다. 해당 포스

programmer93.tistory.com

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

728x90

댓글