[JPA] 쓸려면 알아야할 기본 용어
JPA(Java Persistence API)의 영속성은 데이터를 오랫동안 저장하기 위한 기능을 의미합니다.
이는 데이터베이스와 애플리케이션 사이에서 객체를 저장하고 관리하는 역할을 합니다.
JPA의 영속성을 이해하기 위해서는 우선 영속성 컨텍스트(Persistence Context)라는 개념을 알아야 합니다.
영속성 컨텍스트는 엔티티를 영구 저장하는 환경을 말하며, 엔티티 매니저(Entity Manager)를 통해 접근하고 관리합니다.
JPA의 영속성 컨텍스트에서는 엔티티의 생명주기(Lifecycle)에 따라 4가지 상태를 가집니다.
비영속(new/transient): 영속성 컨텍스트와 전혀 관계가 없는 상태
영속(managed): 영속성 컨텍스트에 저장된 상태
준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태
삭제(removed): 삭제된 상태
매니저를 통해 엔티티를 영속성 컨텍스트에 저장하면, 해당 엔티티는 영속 상태가 됩니다.
이후 엔티티의 데이터가 변경되면 이 변화를 추적하여 데이터베이스에 자동으로 반영하는 더티 체킹(Dirty Checking) 기능이 작동합니다.
컨텍스트 내에서는 같은 엔티티에 대해 동일성을 보장합니다.
JPA 영속성과 관련해 사용되는 기술들은 다음과 같습니다
Hibernate: JPA는 표준 명세이며, 이를 구현한 것이 Hibernate라고 볼 수 있습니다. Hibernate는 JPA의 표준 스펙을 따르며, 그 이외에도 추가적인 기능을 제공합니다.
Spring Data JPA: Spring Data JPA는 JPA를 더 쉽고 편리하게 사용하도록 도와주는 Spring 모듈입니다. 기본 제공되는 CRUD 메소드 외에도, 메소드 이름만으로 조회 쿼리를 생성해주는 기능 등을 제공합니다.
QueryDSL: 타입 안전성을 제공하는 동적 쿼리 생성 라이브러리입니다. 복잡한 쿼리를 Java 코드로 안전하게 작성할 수 있게 도와줍니다.
MyBatis: SQL 매핑 프레임워크로, SQL과 프로그래밍 코드를 분리하여 관리할 수 있게 도와줍니다. JPA와 같이 ORM을 사용하지 않고, 직접적으로 SQL을 다루고자 할 때 사용됩니다.
이 외에도 Eclipselink, Toplink 등 다양한 JPA 구현체가 존재하며, 각자의 특징과 장단점을 가지고 있습니다. 사용하는 환경과 요구사항에 따라 적합한 기술을 선택하여 사용하면 됩니다.
JPA에서 프록시(proxy)는 entity에 대한 가벼운 대체 객체를 의미합니다.
프록시 객체는 실제 엔티티가 아니라 해당 엔티티를 위한 가상 객체로,
실제 엔티티의 데이터를 모두 로드하지 않고 필요한 시점에 데이터를 로드합니다.
이를 지연 로딩(Lazy Loading)이라고 합니다.
프록시 객체는 실제 엔티티 객체와 같은 데이터베이스 ID를 가지며,
접근 시에만 데이터베이스로부터 실제 데이터를 로드합니다.
이렇게 하면 불필요한 데이터 로드를 줄이고 성능을 향상시킬 수 있습니다
프록시 객체 생성 JPA는 엔티티 매니저의 find 메서드 대신 getReference 메서드를 사용하여 프록시 객체를 생성합니다.
이 프록시 객체는 실제 엔티티와 동일한 데이터베이스 ID를 가지지만, 실제 엔티티의 데이터는 로드하지 않습니다.
프록시 객체 초기화: 프록시 객체에 처음으로 접근하면, JPA는 데이터베이스에서 실제 엔티티의 데이터를 로드하여 프록시 객체를 초기화합니다. 프록시 초기화라고 합니다. 프록시 객체 사용 프록시 객체가 초기화되면, 프록시 객체와 실제 엔티티 객체는 동일하게 동작합니다. 따라서 프록시 객체를 통해 실제 엔티티의 데이터를 사용할 수 있습니다. 프록시 객체는 지연 로딩(Lazy Loading) 개념을 구현하는 데 사용됩니다. 즉, 실제 엔티티의 데이터가 필요한 시점에만 데이터베이스에서 데이터를 로드하여 성능을 향상시키는 역할을 합니다.
JPA 프록시는 주로 지연 로딩(Lazy Loading) 개념을 구현하는데 유용합니다.
지연 로딩이란, 데이터가 실제로 사용될 때까지 로드를 연기하는 방법으로,
불필요한 데이터 로드를 줄이고 성능을 향상시키는데 도움이 됩니다.
다음과 같은 상황에서 프록시를 사용하면 유용합니다
관계된 엔티티가 많은 경우 연관된 엔티티가 많은 경우,
모든 엔티티를 즉시 로드(Eager Loading)하는 것은 성능에 부정적인 영향을 미칠 수 있습니다.
이때 프록시를 사용하면, 실제로 필요한 엔티티만 로드하므로 성능을 향상시킬 수 있습니다.
자주 사용되지 않는
데이터를 다루는 경우 일부 데이터는 자주 사용되지 않을 수 있습니다. 이런 경우에 프록시를 사용하면,
데이터가 실제로 필요한 시점에만 로드되므로 불필요한 데이터 로드를 줄일 수 있습니다.
대량의 데이터를 다루는 경우 대량의 데이터를 한 번에 로드하는 것은 메모리 사용량을 크게 늘릴 수 있습니다.
프록시를 사용하면, 필요한 데이터만 로드하여 메모리 사용량을 줄일 수 있습니다.
하지만 프록시를 사용할 때는 주의할 점도 있습니다.
프록시 객체가 초기화되지 않은 상태에서 데이터를 사용하려고 하면, Hibernate는 'LazyInitializationException'을 던질 수 있습니다.
따라서 프록시 객체를 올바르게 관리하고 사용하는 것이 중요합니다.