즉시 로딩과 지연 로딩
프록시 객체는 주로 연관된 엔티티를 지연 로딩할 때 사용한다
즉시 로딩
엔티티를 조회할 때 연관된 엔티티도 함께 조회한다
예로 들어 회원 조회 시 연관된 팀도 함께 조회한다
@ManyToOne(fetch=FetchType.EAGER)을 이용해 즉시 로딩을 사용할 수 있다
대부분의 JPA 구현체는 즉시 로딩을 최적화하기 위해 가능하면 조인 쿼리를 사용해 조회한다
즉시 로딩 실행 시 JPA가 내부 조인이 아닌 외부 조인을 사용한다
외래 키에 null 값을 포함하는 경우 내부 조인을 하면 외래 키가 null인 데이터를 조회할 수 없다
이런 상황을 대비해 JPA는 외부 조인을 사용한다
하지만 외래 키가 not null인 경우 내부 조인을 사용해도 된다
내부 조인을 사용하는 것이 성능 최적화에 더 유리하다
JPA에게 이런 사실을 알려줘야 내부 조인을 사용할 수 있다
@JoinColumn(name=”TEAM_ID”, nullable=false)
지연 로딩
연관된 엔티티를 실제 사용할 때 조회한다
@ManyToOne(fetch=FetchType.LAZY)를 이용해 지연 로딩을 사용할 수 있다
회원을 조회하면 팀은 조회하지 않고 팀 멤버변수에 프록시 객체를 넣어둔다
실제 팀을 사용할 때 데이터베이스에서 조회해 프록시 객체를 초기화한다
조회 대상이 영속성 컨텍스트에 있는 경우 프록시 객체를 사용할 이유가 없으므로 실제 객체를 사용한다
즉시 로딩, 지연 로딩 정리
매번 즉시 로딩을 하는 것도 매번 지연 로딩을 하는 것도 최적화 관점에서는 좋지 않다
상황에 따라 적절한 방법을 선택해 사용해야 한다
지연 로딩 활용
@Entity
public class Member {
@Id
private String id;
private String username;
private Integer age;
@ManyToOne(fetch=FetchType.EAGER)
private Team team;
@OneToMany(mappedBy="member", fetch=FetchType.LAZY)
private List<Order> order;
//Getter Setter ...
}
함께 자주 사용하는 회원과 팀의 연관관계는 즉시 로딩으로 설정했다
함께 가끔 사용하는 회원과 주문내역의 연관관계는 지연 로딩으로 설정했다
프록시와 컬렉션 래퍼
하이버네이트는 엔티티를 영속 상태로 만들 때 엔티티에 컬렉션이 있으면 컬렉션을 추적하고 관리할 목적으로 원본 컬렉션을 하이버네이트가 제공하는 내장 컬렉션으로 변경하는데 이를 컬렉션 래퍼라고 한다 (PersistentBag)
엔티티를 지연 로딩하면 프록시 객체로 수행하지만 컬렉션의 경우에는 컬렉션 래퍼가 지연 로딩을 처리해준다
member.getOrders()와 같이 컬렉션 자체를 조회할 때 컬렉션은 초기화되지 않는다
member.getOrders().get(0)과 같이 컬렉션에서 실제 데이터를 조회할 때 데이터베이스를 조회해 초기화한다
JPA 기본 패치 전략
fetch 속성의 기본 설정값
- @ManyToOne, @OneToOne: 즉시 로딩
- @OneToMany, @ManyToMany: 지연 로딩
연관된 엔티티가 하나면 즉시 로딩을 컬렉션이면 지연 로딩을 사용한다
컬렉션은 로딩시 비용이 많이 들고 잘못하면 너무 많은 데이터를 로딩할 수 있다
모든 연관관계에서 지연 로딩을 사용하는 것을 추천한다
개발 완료 단계에서 꼭 필요한 곳에만 즉시 로딩을 사용해 최적화한다
컬렉션에 FetchType.EAGER 사용 시 주의점
컬렉션을 하나 이상 즉시 로딩하는 것은 권장하지 않는다
일대다 조인 시 결과 데이터는 다 쪽에 있는 수만큼 증가하므로 너무 많은 데이터를 메모리에 올려 애플리케이션 성능이 저하될 수 있다
컬렉션 즉시 로딩은 항상 외부 조인을 사용한다
예를 들어 회원이 한 명도 없는 팀을 내부 조인하면 팀을 조회할 수 없는 문제가 발생한다
데이터베이스 제약 조건으로 이런 상황을 막을 수 없으므로 JPA는 즉시 로딩 시 항상 외부 조인을 사용한다
@ManyToOne, @OneToOne
- (optional=false) : 내부 조인
- (optional=true) : 외부 조인
@OneToMany, @ManyToMany
- (optional=false) : 외부 조인
- (optional=true) : 외부 조인
'스터디 > JPA' 카테고리의 다른 글
값 타입 - (1) (0) | 2025.02.14 |
---|---|
프록시와 연관관계 정리 - (3) (1) | 2025.02.14 |
프록시와 연관관계 정리 - (1) (0) | 2025.02.13 |
고급 매핑 - (3) (0) | 2025.02.12 |
고급 매핑 - (2) (0) | 2025.02.12 |