즉시 로딩은 엔티티를 조회할 때 연관된 엔티티도 함께 로딩하는 방식이고, 지연 로딩은 실제로 연관관계에 접근하는 시점까지 조회를 미루는 방식입니다.
지연 로딩에서는 연관 엔티티 자리에 프록시 객체나 컬렉션 래퍼를 두고, 실제 데이터를 사용하는 시점에 SQL을 실행합니다. 따라서 사용하지 않는 연관 데이터의 조회를 피할 수 있지만, 반복문에서 하나씩 접근하면 N+1 문제가 발생할 수 있고 영속성 컨텍스트가 종료된 뒤 접근하면 LazyInitializationException이 발생할 수 있습니다.
JPA의 기본 FetchType은 @ManyToOne, @OneToOne 같은 ToOne 관계가 EAGER이고, @OneToMany, @ManyToMany 같은 ToMany 관계가 LAZY입니다. 하지만 즉시 로딩은 예상하지 못한 쿼리와 N+1 문제를 만들 수 있으므로 실무에서는 연관관계를 가급적 LAZY로 설정하고, 필요한 조회에서만 Fetch Join이나 EntityGraph로 함께 가져오는 방식을 주로 사용합니다.
LAZY로 설정하면 연관 엔티티는 언제 조회되나요?
프록시의 실제 필드나 지연 로딩 컬렉션을 처음 사용하는 시점에 조회됩니다. 단, 해당 연관관계가 이미 영속성 컨텍스트에 있거나 쿼리에서 Fetch Join된 경우에는 추가 SQL 없이 사용할 수 있습니다.
LazyInitializationException은 왜 발생하나요?초기화되지 않은 지연 로딩 연관관계에 영속성 컨텍스트가 종료된 뒤 접근했기 때문입니다. 트랜잭션 안에서 필요한 데이터를 조회하거나 Fetch Join, EntityGraph, DTO 조회를 사용하여 서비스 계층에서 필요한 로딩을 마쳐야 합니다.
모든 연관관계를 LAZY로 설정하면 성능 문제가 해결되나요?
아닙니다. 불필요한 조회는 줄일 수 있지만 필요한 연관관계를 여러 번 개별 조회하면 N+1 문제가 생깁니다. LAZY를 기본 전략으로 사용하되 각 조회 요구사항에 맞게 Fetch Join이나 Batch Fetching을 적용해야 합니다.