지금을 사는 사람

[Spring] Spring Data JPA의 동작 방식과 프록시 객체 본문

Spring

[Spring] Spring Data JPA의 동작 방식과 프록시 객체

지금회 2024. 1. 15. 18:41
728x90

Spring Data JPA는 자바 표준인 JPA(Java Persistence API)를 기반으로 한 데이터 액세스 계층을 제공하는 스프링 프레임워크의 일부입니다. Spring Data JPA는 JPA를 더 쉽게 사용할 수 있도록 도와주는 도구 및 기능을 제공합니다.

Spring Data JPA의 동작 방식:

  1. Entity 클래스 정의: 데이터베이스의 테이블과 매핑될 엔터티 클래스를 정의합니다. 이 클래스는 JPA 애노테이션을 사용하여 엔터티와 관계를 매핑합니다.
  2. import javax.persistence.Entity; import javax.persistence.Id; @Entity public class MyEntity { @Id private Long id; // 다른 필드들... }
  3. Repository 인터페이스 생성: CrudRepositoryJpaRepository 등의 Spring Data JPA에서 제공하는 인터페이스를 상속하여 리포지토리 인터페이스를 생성합니다.
  4. import org.springframework.data.repository.CrudRepository; public interface MyEntityRepository extends CrudRepository<MyEntity, Long> { // 여기에 사용자 정의 메서드 추가 가능 }
  5. 프록시 객체 생성: Spring Data JPA는 MyEntityRepository 인터페이스에 대한 구현을 자동으로 생성하고, 이를 프록시 객체로 감싸서 스프링 애플리케이션 컨텍스트에 빈으로 등록합니다.
  6. 메서드 호출 처리: 개발자가 MyEntityRepository를 주입받아 사용할 때, 실제로는 해당 리포지토리의 프록시 객체를 주입받게 됩니다. 메서드를 호출할 때 프록시 객체는 호출된 메서드에 대한 구현체를 찾아 실행합니다.

프록시 객체(Proxy Object):

프록시 객체는 다른 객체를 대신해서 특정 동작을 수행하는 객체입니다. Spring Data JPA에서는 인터페이스에 대한 구현을 런타임에 동적으로 생성하여 이를 프록시 객체로 사용합니다.

프록시 객체의 주요 역할은 다음과 같습니다:

  • 실제 객체의 호출을 전담: 프록시 객체는 실제 객체의 호출을 전담하여 호출 전후에 추가적인 로직을 수행할 수 있습니다.
  • 지연 로딩(Lazy Loading): JPA에서는 프록시 객체를 사용하여 연관된 엔터티를 지연 로딩할 수 있습니다. 필요한 시점에 연관된 엔터티를 로딩하여 성능을 최적화할 수 있습니다.

Spring Data JPA가 생성한 프록시 객체는 리포지토리 인터페이스의 메서드를 호출할 때 적절한 JPA 쿼리를 생성하고 실행하여 데이터베이스와 상호 작용합니다.

Q1: 프록시 객체의 지연 로딩은 어떻게 동작하는지 자세히 설명할 수 있을까요?
Q2: Spring Data JPA에서 프록시 객체를 커스터마이징하거나 확인하는 방법이 있을까요?
Q3: 프록시 객체가 실제 객체의 호출을 전담하는 과정에서 발생할 수 있는 주요 이슈는 무엇인가요?

지연 로딩(Lazy Loading)과 프록시 객체의 동작:

  1. 지연 로딩 개념: 지연 로딩은 연관된 엔터티를 실제로 사용하는 시점까지 로딩을 미루는 방식입니다. 이는 연관된 엔터티의 데이터를 필요한 시점에 로딩하여 성능을 최적화할 수 있게 해줍니다.
  2. 프록시 객체와 지연 로딩의 연계: Spring Data JPA는 프록시 객체를 사용하여 지연 로딩을 구현합니다. 예를 들어, 엔터티 Parent가 자식 엔터티 Child와 일대다 관계일 때, 다음과 같은 코드를 고려해봅시다:
  3. @Entity public class Parent { @Id private Long id; @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY) private List<Child> children; // 다른 필드들... } @Entity public class Child { @Id private Long id; @ManyToOne @JoinColumn(name = "parent_id") private Parent parent; // 다른 필드들... }
  4. 프록시 객체 생성 및 호출 시 동작:
    • Parent를 조회할 때 children 필드는 프록시 객체로 대체됩니다.
    • children에 실제로 접근할 때(예: parent.getChildren().size()), JPA는 실제 데이터베이스에서 연관된 엔터티를 로딩합니다.
    • 이로써 children이 실제로 사용되는 시점에 데이터베이스 쿼리가 실행되어 성능을 향상시킵니다.
  5. 주의사항과 이슈:
    • 지연 로딩을 남용하면 N+1 쿼리 문제가 발생할 수 있으므로 사용 상황을 신중하게 고려해야 합니다.
    • 트랜잭션 컨텍스트에서 외부로 나갈 때 지연 로딩을 사용하는 경우, 영속성 컨텍스트가 닫혀서 LazyInitializationException이 발생할 수 있습니다.
728x90

'Spring' 카테고리의 다른 글

[Spring] return redirect:/주소, view이름 차이  (0) 2024.01.16