본문 바로가기
JAVA/JPA

인프런 JPA 8화 프록시와 연관관계 관리 "김영한 강사" -PlusUltraCode-

by PlusUltraCode 2024. 7. 23.
 

프록시(Proxy)란 무엇인가?

프록시는 하이버네이트가 만든 가짜 클래스입니다. 실제 엔티티 클래스의 형태를 그대로 가지고 있으며, 이론상으로는 실제 클래스와 구분하지 않고 사용할 수 있습니다.

프록시의 특징

  1. 형태 동일성: 실제 클래스를 상속 받아서 만들어졌기 때문에 형태가 실제 클래스와 똑같습니다.
  2. 사용의 투명성: 이론상 실제 클래스와 구분하지 않고 사용할 수 있습니다.

프록시의 동작 매커니즘

 
Member member = em.getReference(Member.class, "id1");

위 코드가 실행되면, 프록시에 의해 가짜 객체가 만들어집니다. 만약 member.getName() 메서드를 호출하면, 프록시 객체는 영속성 컨텍스트에게 초기화를 요청합니다. 그 후, 데이터베이스 조회를 통해 받은 값을 실제 엔티티를 생성하여 반환합니다.

프록시의 특징

  1. 한 번만 초기화: 프록시는 반드시 한 번만 초기화됩니다.
  2. 초기화 후 접근: 프록시 객체를 초기화할 때 실제 엔티티로 바뀌는 것이 아니라, 초기화된 프록시 객체를 통해 엔티티에 접근할 수 있습니다.

따라서, 비교할 때는 반드시 instanceof를 사용해야 합니다. JPA에서는 동일성 비교(==)가 가능하므로 프록시와 실제 객체의 순서는 상관없습니다.

즉시 로딩(Eager Loading) vs 지연 로딩(Lazy Loading)

지연 로딩

 
@ManyToOne(fetch = FetchType.LAZY) private Team team;
  • 특징: 지연 로딩을 사용하면 Member 객체가 생성될 때 team 정보는 데이터베이스에서 가져오지 않습니다. team 정보가 필요한 순간에 데이터베이스 쿼리를 실행하여 가져옵니다.
  • 장점: 필요할 때만 데이터를 가져오므로 성능에 유리합니다.

즉시 로딩

 
@ManyToOne(fetch = FetchType.EAGER) private Team team;
  • 특징: 즉시 로딩을 사용하면 Member 객체가 생성될 때 team 정보를 즉시 데이터베이스에서 가져옵니다.
  • 단점: 모든 데이터를 미리 가져오기 때문에 필요 없는 데이터를 불필요하게 조회할 수 있습니다.

실무 권장 사항

  • 즉시 로딩 사용 금지: 실무에서는 즉시 로딩을 사용하지 말고 반드시 지연 로딩만 사용해야 합니다.
  • 이유: N+1 문제 발생 가능성 때문입니다. 예를 들어, select m from Member m 쿼리가 실행되면, 기본 쿼리 1개와 각 멤버의 팀 정보를 가져오는 추가 쿼리가 실행되어 총 11개의 쿼리가 나갈 수 있습니다. 원하는 것은 10개의 배열이지만, 실제로는 11개의 쿼리가 실행됩니다.

Cascade란 무엇인가?

  • 영속화 전이(Cascade): 부모와 자식 엔티티가 있을 때, 부모 엔티티만 영속화하면 자식 엔티티도 자동으로 영속화되는 기능입니다.
  • 고아 객체(Orphan): 부모 엔티티와의 연관관계가 끊어진 자식 엔티티를 자동으로 삭제합니다.

이러한 기능들은 엔티티 간의 관계를 관리하고, 데이터베이스와의 상호작용을 최적화하는 데 중요한 역할을 합니다.