흰 스타렉스에서 내가 내리지

프록시와 즉시로딩/지연로딩 본문

JPA

프록시와 즉시로딩/지연로딩

주씨. 2024. 4. 8. 20:54
728x90

# 프록시

# 1
Member member = memberRepository.findById(1L).or(...);

System.out.println(member.getTeam());

# 2
Member member = memberRepository.findById(1L).or(...);

System.out.println(member.getUsername());

 

# 1 에서는, 회원은 물론이고, 회원과 연관된 팀의 이름도 출력한다.

# 2 에서는, 회원 엔티티만 사용하고 팀 엔티티는 전혀 사용하지 않는다.

 

# 2에서 회원 엔티티만 사용하므로, 그와 연관된 팀 엔티티까지 DB 에서 함께 조회해 두는 것은 비효율적이다.

 

JPA 는 실제 사용될 때까지 데이터베이스 조회를 지연하는 방법을 제공하는데, 이것을 지연 로딩이라 한다.

 

지연 로딩을 사용하려면, 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 피룡한데, 이것을 프록시 객체라 한다.

 

 

# 프록시 기초

  • 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶으면 getReferenceById() 를 사용한다.
  • 이 메소드를 호출할 때, JPA 는 DB 를 조회하지 않고, DB 접근을 위임한 프록시 객체를 반환한다.

 

* 프록시 특징

  • 프록시 클래스는 실제 클래스를 상속 받아서 만들어진다.
  • 프록시 객체는 실제 객체에 대한 참조 (target)를 보관한다. 
  • 그리고 프록시 객체의 메소드를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다. 
  • 프록시 객체는 처음 사용할 떄 한 번만 초기화 된다.
  • 프록시 객체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 프록시 객체가 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.

 

-- 프록시 클래스 예상 코드

class MemberProxy extends Member {
	Member target = null;
    
    public String getName(){
    	if (target == null) {
        	// 2. 초기화 요청
            // 3. DB 조회
            // 4. 실제 엔티티 생성 및 참조 보관
            
            this.target = ...;
        }
        
        // 5. target.getName();
        return target.getName();
    }
}

 

 

# 프록시와 식별자

  • 엔티티를 프록시로 조회할 떄, 식별자(PK) 값을 파라미터로 전달하는데 프록시 객체는 이 식별자 값을 보관한다.
  • 프록시 객체는 식별자 값을 가지고 있으므로 식별자 값을 조회하는 team.getId() 를 호출해도 프록시를 초기화하지 않는다.
  • 연관관계를 설정할 떄는 식별자 값만 사용하므로 프록시를 사용하면 데이터베이스 접근 횟수를 줄일 수 있다.

 

 

# 즉시로딩과 지연로딩

  • 프록시 객체는 주로 연관된 엔티티를 지연 로딩할 떄 사용한다.

 

# 즉시 로딩

- 엔티티를 조회할 떄 연관된 엔티티도 함께 조회한다.

- @ManyToOne(fetch = FetchType.EAGER)

 

# 지연 로딩

- 연관된 엔티티를 실제 사용할 때 조회한다.

- @ManyToOne(fetch = FetchType.LAZY)

 

 

# JPA 기본 페치 전략

  • @ManyToOne, @OneToOne: 즉시 로딩 (FetchType.EAGER)
  • @OneToMany, @ManyToMany: 지연 로딩 (FetchType.LAZY)

연관된 엔티티가 하나면 즉시 로딩을, 컬렉션이면 지연 로딩을 사용한다. 

컬렉션을 로딩하는 것은 비용이 많이 들고 잘못하면 너무 많은 데이터를 로딩할 수 있기 때문이다. 

 

일단 모든 연관관계에 지연로딩을 사용하는 것이 좋다. 

그리고 애플리케이션 개발이 어느 정도 완료단계에 왔을 때 실제 사용하는 상황을 보고 꼭 필요한 곳에만 즉시 로딩을 사용하도록 최적화하면 된다. 

'JPA' 카테고리의 다른 글

TypeQuery 와 Query  (0) 2024.04.13
고아 객체  (0) 2024.04.10
일대일 식별 관계  (0) 2024.04.04
복합 키 : 비식별 관계 매핑  (1) 2024.04.04
식별 관계 vs 비식별 관계  (0) 2024.04.04