Java

JPA FetchType.EAGER와 LAZY의 차이 알아보기

누구세연 2024. 11. 22. 21:49

JPA를 사용할 때 @OneToMany, @ManyToOne 등 연관 관계를 매핑할 때 종종 등장하는 옵션이 있습니다. 바로 FetchType.EAGERFetchType.LAZY입니다. 이 두 옵션은 연관된 엔티티 데이터를 언제 로딩할지를 결정하며, 올바르게 설정하지 않으면 성능 문제를 일으킬 수 있습니다. 이번 글에서는 두 FetchType의 차이와 실무에서의 사용법을 다뤄보겠습니다.
 

FetchType이란?

FetchType은 JPA에서 엔티티의 연관된 데이터를 가져오는 방식을 정의합니다.

기본적으로 JPA는 두 가지 FetchType을 제공합니다:

  • EAGER (즉시 로딩)
  • LAZY (지연 로딩)

FetchType.EAGER (즉시 로딩)

  • 즉시 로딩은 엔티티를 조회할 때 연관된 엔티티 데이터도 즉시 가져옵니다.
  • 예를 들어 A 엔티티가 B 엔티티와 연관되어 있다면, A를 조회할 때 자동으로 B도 조회됩니다.
@Entity
public class A {
    @ManyToOne(fetch = FetchType.EAGER)
    private B b;
}

실행 시 SQL

SELECT * FROM A;
SELECT * FROM B WHERE B.ID = ...; -- 연관된 B도 즉시 로딩

장점

  • 연관된 데이터를 항상 사용한다면 편리합니다.
  • 쿼리 횟수가 줄어드는 경우도 있습니다.

단점

  • 필요하지 않은 데이터를 가져오면서 불필요한 리소스가 낭비될 수 있습니다.
  • N+1 문제를 유발할 가능성이 큽니다.

 

2. FetchType.LAZY (지연 로딩)

  • 지연 로딩은 연관된 데이터를 실제로 접근할 때까지 가져오지 않습니다.
  • 기본적으로 프록시 객체를 반환하며, 해당 객체에 접근하는 순간 쿼리가 실행됩니다.
@Entity
public class A {
    @ManyToOne(fetch = FetchType.LAZY)
    private B b;
}

실행 시 SQL

SELECT * FROM A; -- B에 대한 쿼리는 실행되지 않음

`A.getB()`를 호출하면 그때서야 연관된 B를 조회합니다.

SELECT * FROM B WHERE B.ID = ...;

 

장점

  • 초기 로딩 시간이 줄어듭니다.
  • 필요할 때만 데이터를 가져와 효율적입니다.

단점

  • 예상치 못한 시점에 추가 쿼리가 발생할 수 있습니다.
  • Hibernate의 LazyInitializationException을 주의해야 합니다.

 

EAGER vs LAZY의 비교

특징 FetchType.EAGER FetchType.LAZY
데이터 로딩 시점 엔티티 조회 시 즉시 로딩 연관 엔티티 접근 시 로딩
장점 간단한 코드, 연관 데이터 즉시 사용 가능 초기 로딩 시간 단축, 불필요한 데이터 배제
단점 불필요한 데이터 로딩, N+1 문제 발생 가능 LazyInitializationException 위험
사용 사례 데이터가 항상 필요한 경우 연관 데이터가 가끔 필요한 경우

 

 

실무에서의 FetchType 설정 팁

  1. 기본 값 이해하기
    • @ManyToOne, @OneToOne의 기본 FetchType은 EAGER입니다.
    • @OneToMany, @ManyToMany의 기본 FetchType은 LAZY입니다.
    • 기본 값을 변경하지 않아도 되는 경우가 많지만, 필요에 따라 설정을 명시적으로 변경하세요.
  2. Lazy 로딩을 기본으로 사용
    • 대부분의 경우 연관 데이터를 즉시 로딩하지 않아도 됩니다.
    • Lazy 로딩을 사용하고, 필요 시 join fetch 또는 **EntityGraph**를 활용해 데이터를 한 번에 로딩하세요.
  3. N+1 문제에 주의
    • Lazy 로딩을 사용할 때, 연관 데이터를 반복적으로 접근하면 N+1 문제가 발생할 수 있습니다.
      이를 방지하기 위해 JPQL의 fetch join이나 Hibernate batch size 설정을 활용하세요.

 

💡JPA에서 FetchType.EAGER와 LAZY는 데이터 로딩 방식을 결정하는 중요한 설정입니다.
EAGER는 간편하지만, 성능 문제를 초래할 수 있습니다.
LAZY는 효율적이지만, 예기치 않은 쿼리와 LazyInitializationException에 주의해야 합니다.
실무에서는 기본적으로 LAZY를 선택하고, 필요한 경우 명시적으로 조정하는 전략을 추천합니다.
FetchType 설정을 올바르게 이해하고 적용하여 더 안정적이고 효율적인 애플리케이션을 만들어 보세요👀