FetchType.EAGER(즉시 로딩) vs FetchType.LAZY(지연 로딩)

젼이·2024년 10월 29일

@ManyToOne의 fetch 속성은 JPA에서 다대일 관계를 설정할 때, 연관된 엔티티를 언제 로드할지를 결정하는 중요한 설정이다.

FetchType.EAGER: 즉시 로딩

FetchType.LAZY: 지연 로딩





FetchType.EAGER(즉시 로딩)

@ManyToOne(fetch = FetchType.EAGER)
private Building building;

특징:

  • 즉시 로딩은 연관된 엔티티를 항상 즉시 함께 조회한다.
  • 부모 엔티티가 로드될 때, 연관된 자식 엔티티도 즉시 조회된다.
  • 한 번의 쿼리로 해결되지 않으면 N+1 문제가 발생할 수 있다.
    - 예: 부모 엔티티를 조회하는 쿼리 1개 + 자식 엔티티를 각각 로드하는 쿼리가 N개 더 실행


예시:

SELECT * FROM detection WHERE id = 1;
SELECT * FROM building WHERE id = 10; -- 즉시 로딩된 연관 데이터

사용 상황:

  • 연관된 엔티티가 반드시 사용될 것이 확실한 경우.
  • 객체 탐색이 자주 일어나는 상황(예: 로딩을 기다리지 않고 즉시 필요할 때).

단점:

  • 불필요한 데이터를 미리 로드할 수 있어 성능에 영향을 미칠 수 있다.




FetchType.LAZY (지연 로딩)

@ManyToOne(fetch = FetchType.LAZY)
private Building building;

특징:

  • 지연 로딩은 연관된 엔티티를 필요한 시점에만 로드한다,
  • 부모 엔티티가 로드될 때는 프록시 객체를 사용해 연관된 엔티티의 로딩을 지연시킨다.
  • 연관된 엔티티에 접근할 때 데이터베이스 쿼리가 실행된다.


예시:

Detection detection = detectionRepository.findById(1L).get();
Building building = detection.getBuilding(); // 이때 쿼리 실행
SELECT * FROM detection WHERE id = 1;
-- building에 접근 시점에 실행
SELECT * FROM building WHERE id = 10;

사용 상황:

  • 연관된 엔티티를 매번 사용하지 않을 때.
  • 성능 최적화가 필요한 경우, 필요할 때만 데이터를 가져오기 위해 사용한다.

단점:

  • 지연된 시점에 쿼리가 실행되기 때문에 의도치 않게 N+1 문제가 발생할 수 있다.
  • 프록시 객체로 인해 LazyInitializationException이 발생할 수 있다. (트랜잭션 범위 밖에서 접근할 때)




정리: 언제 EAGER와 LAZY를 사용할까?

  • FetchType.EAGER: 연관된 엔티티를 즉시 사용해야 하거나, 연관 데이터가 항상 필요할 때 사용한다.
  • FetchType.LAZY: 성능 최적화가 필요하고, 연관 데이터가 항상 사용하지 않을 경우 사용한다.

Tip. 실무에서는 기본적으로 LAZY를 사용하고, 필요한 경우에만 EAGER을 사용하는 것이 좋다고 한다.

profile
신입 개발자 임니당 : > (2025.02.05~)

0개의 댓글