ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] 즉시(Eager) 로딩 과 지연(Lazy) 로딩
    Spring JPA 2024. 8. 11. 21:54

    Spring jpa 에서 연관관계 매핑을 할때 설정하는 문제이다 

    JPA 에서 데이터를 조회 할때 eager loading(즉시 로딩), lazy loading(지연 로딩) 으로 하는 두가지 방식이 있다

    이 두개의 차이점은 한개의 테이블을 조회할때 그 테이블에 연관된 테이블까지 불러오냐 안 불러오냐의 차이점이다

     

    여기서 즉시 로딩(eager)은 연관된 데이터까지 한 번에 불러오고

    지연 로딩(lazy)은 필요한 시점에 연관된 데이터를 불러온다

     

    어떻게 설정을 하냐?

    @Entity
    @Setter
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(name = "post")
    public class Post {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "post_id")
        private Long postId;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "user_id")
        private User user;
    
        @Column(name = "title")
        private String title;
    
        @Column(name = "content")
        private String content;
    
    }

     

    일단, 해당하는 테이블의 연관관계 1:N, N:1, 1:1 등등을 설정해주고 fetch  타입을 지정해준다

     

    Fetch Type 이란?

     

    JPA가 하나의 Entity를 조회할 때 연관관계에 있는 객체들을 어떻게 가져올 것이냐를 나타내는 설정값이다

     

    여기에서 JPA는 ORM 기술이다

    사용자가 쿼리를 직접 작성하지 않고 JPQL을 이용하여 쿼리문을 생성하기 때문에 

    객체와 필드를 보고 쿼리를 생성한다

     

     

    즉시 로딩 

    • 데이터를 조회할 때 연관된 모든 객체의 데이터까지 한번에 불러오는 것
    •  @xxToxx(fetch = FetchType.EAGER)
    @Entity
    @Getter
    @Setter
    @Table(name = "category")
    @NoArgsConstructor
    public class Category {
    
        @Id
        @Column(name = "category_id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "parent_category_id")
        private Category parentCategory;
    
        @Column(name = "category_name")
        private String name;
    
        public Category(Category parentCategory, String name) {
            this.parentCategory = parentCategory;
            this.name = name;
        }
    }

     

    이렇게 category라는 entity가 있고 부모 카테고리와 N:1의 관계를 가지고 있다고 보자 

    category 한개를 조회할 때 어떤 쿼리가 만들어질까 ?

    Hibernate: 
    select c1_0.category_id,c1_0.category_name,pc1_0.category_id,pc1_0.category_name,pc1_0.parent_category_id 
    	from category c1_0 
    left join category pc1_0 on pc1_0.category_id=c1_0.parent_category_id 
    where c1_0.category_id=?

    위와 같이 즉시 로딩을 사용하게 되면 category를 조회할때 부모 카테고리 까지 불러오는 쿼리를 작성하여 한꺼번에 데이터를 불러온다

     

     

    지연 로딩 

    • 필요한 시점에 연관된 객체의 데이터를 불러온다
    • @xxToxx(fetch = FetchType.LAZY)

    위에 있는 Category entity에서 FetchType 을 Lazy로 바꾼다면 어떤 쿼리가 만들어질까?

    Hibernate: 
    select c1_0.category_id,c1_0.category_name,c1_0.parent_category_id 
    	from category c1_0 
    where c1_0.category_id=?

    위와 같이 부모 카테고리의 데이터까지는 불러오지 않는다 

    즉, 지연 로딩을 사용하면 연관된 데이터는 사용하는 시점에 쿼리가 나가도록 할 수 있다 


     

    어떤 사람들은 "어차피 가져와야 하는 데이터면 EAGER가 좋지 않냐?"라고 말하기도 한다

    그러나, EAGER 로딩을 무조건적으로 사용하는 것은 바람직하지 않다

     

    EAGER 로딩은 연관된 모든 데이터를 한 번에 가져오므로, 불필요한 데이터가 함께 로딩되어 성능 문제를 야기할 수 있다

     

    만약 특정한 경우, 예를 들어 카테고리와 부모 카테고리가 항상 함께 사용되는 상황이라면, EAGER로 설정하여 데이터를 함께 조회하는 것이 합리적일 수 있다

     

    그러나 해당 엔티티를 조회할 때 연관된 데이터가 당장 필요하지 않거나, 특정 시점에만 필요한 경우라면 LAZY 로딩을 사용하는 것이 좋다 이 경우에는 필요한 시점에 별도의 쿼리를 작성하여 데이터를 가져오는 것이 성능 면에서 더 유리하다

Designed by Tistory.