728x90
반응형
프록시란?
프록시 : 실제 엔티티 객체 대신 생성되는 객체로, 엔티티의 데이터에 접근할 때까지 데이터 로딩을 지연시킵니다. 프록시 객체는 실제 엔티티 객체와 동일한 메서드와 속성을 가지며, JPA가 자동으로 생성하고 관리합니다. 좀 더 쉽게 설명하고자 하면 우리가 항상 Member을 조회할때 단순히 Member.getName만 알고싶은데 Member안에 Team까지 계속해서 로드할 필요가 없다. 이러한 불필요한 상황을 방지하고자 프록시를 사용한다.
여기서 프록시는 엔티티 클래스를 상속받아서 만들어진다. Hibernate가 내부의 프록시 라이브러리로 자동으로 상속해준다.
- 프록시 객체에 member.getName()을 호출해서 실제 데이터를 조회한다.
- 프록시 객체는 실제 엔티티가 생성되어 있지 않으면 영속성 컨텍스트에 실제 엔티티 생성을 요청하는데 이것을 초기화라 한다.
- 영속성 컨텍스트는 데이터베이스를 조회해서 실제 엔티티 객체를 생성한다.
- 프록시 객체는 생성된 실제 엔티티 객체의 참조를 Member target 멤버변수에 보관한다.
- 프록시 객체는 실제 엔티티 객체의 getName()을 호출해서 결과를 반환한다.
proxy target에 값이 없을때 초기화 요청을 하는 2번이다. 그리고 이 요청을 통해 진짜 객체를 proxy 객체의 target에 연결하는 과정을 프록시 객체의 초기화과정이라고 부릅니다.
프록시의 특징
- 프록시 객체는 처음 사용할 때 한 번만 초기화된다.
- 프록시 객체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 프록시 객체가 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.
- 프록시 객체는 원본 엔티티를 상속받은 객체이므로 타입 체크 시에 주의해서 사용해야 한다.
- 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 데이터베이스를 조회할 필요가 없으므로 em.getReference()를 호출해도 프록시가 아닌 실제 엔티티를 반환한다.
- 초기화는 영속성 컨텍스트의 도움을 받아야 가능하다. 따라서 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태의 프록시를 초기화하면 문제가 발생한다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
}
FetchType.LAZY는 우리가 앞서 설명한 프록시를 구현하는 방법이고, FetchType.EAGER은 바로바로 로딩하여 쿼리를 전송합니다. 지연로딩과 즉시로딩으로 불립니다.
정리하면 다음과 같습니다.
1. 즉시 로딩을 가급적 사용하지 말고, 지연 로딩을 권장
- 즉시 로딩 (EAGER)을 사용하면, 연관된 모든 엔티티가 한 번에 로딩됩니다. 이는 예상하지 못한 SQL 쿼리의 증가를 초래할 수 있습니다. 특히, 여러 관계가 즉시 로딩으로 설정된 경우 다수의 테이블이 조인되어 성능 저하를 유발할 수 있습니다.
- 지연 로딩 (LAZY)은 실제로 해당 연관 엔티티가 필요할 때만 데이터를 로딩하므로, 성능상의 이점을 제공합니다. 필요하지 않은 데이터를 미리 로딩하지 않아 불필요한 리소스 사용을 줄입니다.
2. 즉시 로딩과 N+1 문제
- 즉시 로딩은 JPQL(또는 Querydsl 등)을 사용하여 데이터를 조회할 때, N+1 문제를 일으킬 수 있습니다. 예를 들어, 하나의 부모 엔티티를 조회하는 쿼리(1개)와 그에 연관된 자식 엔티티를 각각 조회하는 추가적인 쿼리(N개)가 발생하여, 총 N+1개의 SQL 쿼리가 실행됩니다. 이는 대규모 데이터 조회 시 심각한 성능 문제를 초래할 수 있습니다.
3. X To One 관계의 기본값은 즉시 로딩이므로, 지연 로딩으로 설정 필요
- @ManyToOne 및 @OneToOne 관계의 기본 페치 전략은 즉시 로딩 (EAGER)입니다. 따라서, 이 관계에서는 반드시 fetch = FetchType.LAZY로 설정하여 지연 로딩을 적용하는 것이 권장됩니다. 이를 통해 불필요한 데이터 로딩을 방지하고 성능 최적화를 도모할 수 있습니다.
4. X To Many 관계의 기본값은 지연 로딩
- @OneToMany 및 @ManyToMany 관계는 기본적으로 지연 로딩 (LAZY)으로 설정되어 있습니다. 이는 다수의 연관된 엔티티를 기본적으로 지연 로딩하기 위해 설계된 것입니다. 따라서 별도의 설정 없이도 성능 이슈를 예방할 수 있습니다.
728x90
반응형
'백엔드' 카테고리의 다른 글
[Spring Boot] JPA 값 타입 (0) | 2024.09.02 |
---|---|
[Spring Boot] JPA 영속성 전이, 고아 객체 (0) | 2024.09.01 |
[Spring Boot] JPA 고급매핑 상속관계 매핑, @MappedSuperclass (1) | 2024.09.01 |
[Spring Boot] JPA 연관관계 매핑 (1) | 2024.09.01 |
[Spring Boot] @Bean, @Configuration, @Component (0) | 2024.08.30 |