지연 로딩과 즉시 로딩

연수김·2023년 3월 14일
0

jpa

목록 보기
1/1

JPA에서는 즉시 로딩과 지연 로딩을 지원하며, 이 두 가지 방식은 데이터를 가져오는 시점에 차이가 있다.

즉시 로딩 (Eager Loading)

즉시 로딩은 연관 관계를 맺고 있는 모든 객체를 한 번에 가져오는 방식이다.
예를 들어, 게시판과 댓글 테이블이 있다고 가정하고 게시판과 댓글은 One-to-Many 관계를 맺고있다. 즉시 로딩을 사용하면, 게시판을 가져올 때 해당 게시판과 연관된 모든 댓글도 함께 가져오게 된다.

즉시 로딩은 객체 그래프를 한 번에 가져오기 때문에 성능상 이점이 있다. 하지만, 연관된 객체들이 많은 경우에는 많은 양의 데이터를 가져오기 때문에 성능이 저하될 수 있다. 또한, 불필요한 데이터까지 함게 가져오기 때문에 메모리 사용량이 증가할 수 있다.

엔티티안에서 즉시 로딩은 다음과 같이 사용할 수 있다.

@Entity
public class Comment {
    
    @ManyToOne(fetch = FetchType.EAGER)
    private Board board;
    
    ...
}

지연 로딩 (Lazy Loading)

지연 로딩은 객체를 가져오는 시점을 지연시키는 방식이다.
예를 들어, 위에서 언급한 게시판과 댓글의 관계에서 게시판을 가져올 때, 댓글은 가져오지 않고 나중에 필요한 시점에 가져오는 방식이다.

지연 로딩은 필요한 시점에만 데이터를 가져오기 때문에 메모리 사용량이 줄고, 불필요한 데이터를 가져오지 않아 성능이 향상될 수 있다. 하지만, 연관된 객체를 가져오는 과정에서 예외가 발생할 수 있다. 연관된 객체를 가져오는 시점이 지연되기 때문에, 해당 객체가 삭제되었거나 null인 경우가 있을 수 있다. 이러한 경우에는 예외 처리가 필요하다.

엔티티안에서 지연 로딩은 다음과 같이 사용할 수 있다.

@Entity
public class Board {
    
    @OneToMany(mappedBy = "board", fetch = FetchType.LAZY)
    private List<Comment> comments;
    
    ...
}

언제 어떤 방식을 사용해야 할까??

즉시 로딩 : 연관된 객체들이 많이 사용되는 경우
지연 로딩 : 연관된 객체들이 자주 사용되지 않는 경우나, 대규모 데이터를 다룰 때 사용

어떤 방식을 사용할 지는 상황에 따라 달라질 수 있다. JPA에서는 이 외에도 다양한 로딩 전략을 제공하고 있다. 로딩 전략을 선택할 때는 성능적인 측면 뿐만 아니라, 애플리케이션의 요구사항에 따라 적절하게 선택해야한다.

프로젝트 적용

다음은 현재 진행하고 있는 프로젝트에서 지도화면이다.

왼쪽의 냉장고 리스트를 가져올 때 냉장고와 Many-to-One관계를 갖고있는 기부(음식)과 메세지에 대해서는 가져올 필요가 없다. 때문에 음식과 메세지에 지연 로딩을 적용하여 성능을 개선할 수 있을 것으로 보인다.

Give.java

package com.example.test.give;
import com.example.test.food.Food;
import com.example.test.fridge.Fridge;
import com.example.test.member.Member;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

@Entity
@Getter
@Setter
public class Give {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "GIVE_ID")
    private Long id;
    private LocalDateTime giveTime;
    @ManyToOne
    @JoinColumn(name = "MEMBER_ID")
    private Member giver;
    @OneToOne
    @JoinColumn(name = "FOOD_ID")
    private Food food;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FRIDGE_ID")
    private Fridge fridge;

    private Boolean isReserved;

    public Give(LocalDateTime giveTime, Member giver, Food food, Fridge fridge){
        this.giveTime = giveTime;
        this.giver = giver;
        this.food = food;
        this.fridge = fridge;
        this.isReserved = false;
    }
    public Give() {}
}

MessageV2.java

package com.example.test.messageV2;

import com.example.test.food.Food;
import com.example.test.fridge.Fridge;
import com.example.test.give.Give;
import com.example.test.member.Member;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;

@Entity
@Getter
@AllArgsConstructor
public class MessageV2 {
   @Id @Column(name = "MESSAGEV2_ID")
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   @ManyToOne
   @JoinColumn(name = "GIVE_ID")
   private Give give;
   private LocalDateTime sendTime;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "FRIDGE_ID")
   private Fridge fridge;
   @ManyToOne
   @JoinColumn(name = "SENDER_ID")
   private Member sender;
   @Setter
   @ManyToOne
   @JoinColumn(name = "RECEIVER_ID")
   private Member receiver;
   private String message;

   public MessageV2(Give give, Fridge fridge ,LocalDateTime sendTime, Member sender, Member receiver, String message){
       this.give = give;
       this.fridge = fridge;
       this.sendTime = sendTime;
       this.sender = sender;
       this.receiver = receiver;
       this.message = message;
   }
   public MessageV2(Give give, Fridge fridge, LocalDateTime sendTime, Member sender, String message){
       this.give = give;
       this.fridge = fridge;
       this.sendTime = sendTime;
       this.sender = sender;
       this.message = message;
   }

   public MessageV2() {}
}
profile
연수돼지

0개의 댓글