궁금한 것

지연 로딩과 즉시 로딩의 차이

민석삼 2025. 5. 8. 11:04

즉시 로딩: 연관관계에서 1:N 관계에 있는 엔티티를(N쪽의 데이터를) 조회할 때, 거기에 매핑된 다른 엔티티도 한 번에 하나의 쿼리로 가져오는 방식

지연 로딩: DB가 아닌 프록시에서 데이터를 가져온다. 마찬가지로 N 쪽의 데이터를 조회할 때, 해당 데이터는 실제 DB쿼리로 가져오고 매핑된 다른 엔티티들은 프록시 객체로 함께 생성되어 메모리에 로딩됨. (프록시 객체는 즉시 생성되지만 그 프록시 내부의 실제 데이터는 아직 로딩되지 않음)

 

예를 들어보자...

@Entity
public class MemberPrefer {
    @ManyToOne(fetch = FetchType.LAZY)
    private Member member;
}

MemberPrefer이라는 객체에 N:1관계로 매핑된 객체 member

 

즉시로딩:

MemberPrefer를 조회하는 시점에 바로 Membber까지 불러오는 쿼리를 날려 한꺼번에 데이터를 불러옴

 

지연로딩:

처음 MemberPrefer을 DB에서 조회할 때, MemberPrefer 자체는 실제 DB 쿼리로 SELECT해 옴

그 안의 member는 실제 엔티티가 아니라 프록시 객체로 함께 생성되어 메모리에 로딩된다.

프록시 객체는 MemberPrefer을 DB에서 조회할 때 즉시 생성되지만, 프록시 내부의 실제 데이터는 아직 로딩되지 않음.

즉, 빈 껍데기로 MemberPrefer 데이터 안에 들어있다.

그리고 실제로 MemberPrefer에 연결된 member라는 객체를 조회할 때에야 DB에서 조회됨

 

*프록시 객체란? 

진짜 객체에 대한 접근을 제어하는 대리 객체

실제 엔티티의 가짜 버전, 실제 DB에서 데이터를 가져오기 전까지 대신 사용되는 객체

성능 최적화를 위해 당장 필요 없는 데이터를 나중에 불러오기 위해 껍데기만 만들어 놓는 것

위의 예시에서, 진짜 클래스(Member)를 상속한 서브클래스이며, 내부 DB에 접근하는 로직이 포함되어 있어 진짜 값이 필요할 때   DB를 자동 조회함

 

프록시에 대해 잘 몰라서..

더보기
더보기

지연 로딩을 위해 생성되는 Hibernate 프록시에만 DB 접근 로직이 포함되는 거고, 일반적인 다른 프록시 객체들에는 DB 접근 로직이 포함되지 않을 수도 있다.

 

1. Hibernate 프록시 (JPALazy Loading용)

  • 목적: 연관 엔티티를 늦게 조회하기 위해
  • 특징:
    • 진짜 엔티티 클래스를 상속한 서브클래스
    • 내부에 DB에서 실제 데이터를 조회하는 로직 포함
    • 필요할 때(getName() 같은 메서드 호출) DB 접근
  • 즉, 프록시 내부에 Session, EntityManager, 식별자(id) 정보가 있어서 DB 조회 가능
    이건 Hibernate@ManyToOne(fetch = FetchType.LAZY) 같은 설정을 보고 특수하게 만든 프록시

2. 일반 프록시 (예: Spring AOP 프록시, RPC 프록시 등)

  • 목적: DB 접근보단 다른 작업을 대신하거나, 기능을 감싸기 위함
  • 예시들:
    •  Spring AOP에서 트랜잭션 처리 프록시
    •  리모트 서비스 프록시 (예: gRPC, RMI 등)
    •  보안 체크, 로깅 기능 삽입용 프록시
  • 이들은 내부에 DB 접근 로직이 들어있지 않고
    대신 로깅, 보안, 네트워크 호출 등을 대신 처리하게 만들어짐

 

MemberPrefer prefer = memberPreferRepository.findById(1L).get();
Member m = prefer.getMember(); // 이때는 프록시 객체

MemberPrefer 객체를 조회하는 명령어만을 수행했을 때는 prefer이라는 객체의 member를 조회했을 때 프록시 객체가 들어 있을 것

String name = m.getName(); // 이 시점에서 진짜 SELECT 쿼리 날라감

실제로 MemberPrefer 객체 내의 member의 데이터를 조회할 때, 그제야 member를 가져오는 select 쿼리가 날아간다

 

 

지연 로딩을 사용하면 MemberPrefer를 조회하는 시점이 아닌 실제 Team 을 사용하는 시점에 쿼리가 나가도록 할 수 있다.

즉시 로딩의 경우, MemberPrefer과 연관된 Member가 1000개, 10000개라면?

MemberPrefer를 조회하는 쿼리를 하나 날렸을 뿐인데 Member를 조회하는 쿼리가 1000개, 10000개가 추가로 나감

참고 블로그

https://velog.io/@jinyeong-afk/%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EC%A6%89%EC%8B%9C-%EB%A1%9C%EB%94%A9%EA%B3%BC-%EC%A7%80%EC%97%B0-%EB%A1%9C%EB%94%A9%EC%9D%98-%EC%B0%A8