25.01.22 TIL 즉시로딩, 지연로딩

신성훈·2025년 1월 22일
0

TIL

목록 보기
124/162

1. 즉시 로딩(Eager Loading)

즉시 로딩엔티티가 조회될 때 연관된 엔티티를 즉시 함께 로딩하는 방식입니다.
데이터베이스에서 한 번의 쿼리를 실행하거나, 연관 엔티티를 추가적으로 조회하는 쿼리를 실행하여 연관 데이터를 가져옵니다.

특징

  • 연관 엔티티를 즉시 사용할 수 있다.
  • 불필요한 데이터를 미리 로딩할 가능성이 있다.
  • N+1 문제를 유발할 가능성이 높다.

예시

@Entity
public class Order {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER) // 즉시 로딩 설정
    private Customer customer; // 연관 엔티티
}

쿼리 동작

SELECT * FROM order o
JOIN customer c ON o.customer_id = c.id; -- 연관된 고객 데이터를 즉시 로딩

2. 지연 로딩(Lazy Loading)

지연 로딩엔티티를 실제로 사용할 때 연관된 데이터를 가져오는 방식입니다.
프록시 객체를 사용하여 필요한 시점에 데이터베이스에서 추가 쿼리를 실행합니다.

특징

  • 초기 데이터 로딩 시 불필요한 데이터를 가져오지 않아 효율적이다.
  • 연관 데이터를 사용할 때 추가적인 쿼리가 실행된다.
  • LazyInitializationException이 발생할 수 있으므로 주의가 필요함.

예시

@Entity
public class Order {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩 설정
    private Customer customer; // 연관 엔티티
}

쿼리 동작

-- Order 조회 시
SELECT * FROM order;

-- Customer가 실제로 사용될 때 추가 쿼리 실행
SELECT * FROM customer WHERE id = ?;

3. 즉시 로딩과 지연 로딩의 비교

구분즉시 로딩 (Eager Loading)지연 로딩 (Lazy Loading)
특징연관 엔티티를 즉시 로드실제로 사용할 때 데이터 로드
장점연관 데이터의 즉시 접근 가능초기 로딩 속도 빠르고 불필요한 로딩 방지 가능
단점불필요한 데이터 로드 가능성, N+1 문제 발생 가능LazyInitializationException 위험
사용 시점연관 데이터가 항상 필요할 경우 사용연관 데이터가 선택적으로 필요할 경우 사용

4. N+1 문제

설명

즉시 로딩을 사용하면, 주 쿼리 1번 + 연관 엔티티를 가져오는 추가 쿼리 N번이 실행될 수 있습니다.

예시

List<Order> orders = orderRepository.findAll(); // 즉시 로딩
for (Order order : orders) {
    System.out.println(order.getCustomer().getName());
}

쿼리 실행

  1. Orders 조회 쿼리 실행: SELECT * FROM orders;
  2. 각 Order마다 Customer 조회:
    SELECT * FROM customer WHERE id = ?;

5. 즉시 로딩과 지연 로딩 사용 시 주의사항

  1. 즉시 로딩

    • 항상 필요한 연관 데이터를 미리 로드해야 하는 경우 적합
    • 하지만 연관 데이터가 많거나 깊이가 깊으면 성능 문제가 발생할 수 있다.
  2. 지연 로딩

    • 필요할 때만 데이터를 로드하므로 초기 로딩 성능이 중요할 때 적합
    • 트랜잭션 범위를 벗어난 상태에서 Lazy 데이터 접근 시 LazyInitializationException이 발생할 수 있다. 방지하기 위해 Fetch Join 또는 EntityGraph를 사용할 수 있다.

Fetch Join 예시

@Query("SELECT o FROM Order o JOIN FETCH o.customer WHERE o.id = :id")
Order findOrderWithCustomer(@Param("id") Long id);

6. 마무리

즉시 로딩과 지연 로딩은 JPA의 강력한 기능이지만 사용에 따른 트레이드오프를 잘 이해해야 합니다.
N+1 문제와 LazyInitializationException은 성능 최적화를 위해 반드시 고려해야 할 사항입니다.
프로젝트 상황에 맞게 로딩 전략을 선택하며, 필요 시 Fetch Join 등을 활용하여 효율적인 데이터 처리를 설계하는 것이 중요함을 느꼈습니다.

profile
조급해하지 말고, 흐름을 만들고, 기록하면서 쌓아가자.

0개의 댓글