IT/JPA

[JPA] - 영속성 컨텍스트 (Persistence Context)

justdo2t 2024. 12. 13. 15:23

영속성 컨텍스트란?

JPA에서 영속성 컨텍스트는 엔티티 객체를 영속 상태(Persistent State)로 유지하고, 데이터베이스와 동기화를 담당한다. 이를 통해 데이터베이스 작업을 효율적으로 처리하고, 개발자가 직접 SQL을 작성하지 않아도 된다.

 

영속성 컨텍스트의 주요 역할

  • 엔티티 관리: 엔티티의 생명주기를 관리한다. (비영속, 영속, 준영속, 삭제)
  • 변경 감지: 엔티티 객체의 상태 변경을 감지하고, 필요한 경우 데이터베이스에 자동으로 반영한다.
  • 캐싱: 동일한 엔티티를 여러 번 조회해도 동일한 인스턴스를 반환하여, 성능을 최적화한다.
  • 트랜잭션과의 연계: 트랜잭션 범위 내에서만 유효하며, 트랜잭션 종료 시 데이터를 플러시(Flush)하여 데이터베이스와 동기화한다.

 

영속성 컨텍스트의 동작 원리

  JPA는 EntityManager를 통해 영속성 컨텍스트를 제어한다. 영속성 컨텍스트의 동작은 다음과 같은 단계를 통해 이루어진다.

 

  1. 비영속 상태(Transient State)
    • 새로 생성된 객체로, 아직 영속성 컨텍스트에 포함되지 않은 상태다. 즉, 영속성 컨텍스트와 전혀 관계가 없는 상태이다.
    User user = new User(); 
    user.setName("John"); // 아직 영속성 컨텍스트에 포함되지 않음
  2. 영속 상태(Persistent State)
    • 영속성 컨텍스트에 저장되어 관리되는 상태다.
    • EntityManager.persist()를 호출하거나, 데이터베이스에서 조회된 객체는 영속 상태(1차 캐시)가 된다.
    • 트랜잭션커밋 시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날아간다.
    em.persist(user); // 영속성 컨텍스트에 user가 포함됨
     
  3. 준영속 상태(Detached State)
    • 영속성 컨텍스트에서 저장되었다가 분리된 상태로, 더 이상 JPA가 관리하지 않는다.
    • 예: EntityManager.clear()EntityManager.detach()를 호출한 경우.
    em.detach(user); // user는 더 이상 영속성 컨텍스트에서 관리되지 않음
     
  4. 삭제 상태(Removed State)
    • 엔티티가 삭제 요청된 상태다. 데이터베이스에서 해당 데이터는 실제로 삭제된다.
    em.remove(user); // user는 데이터베이스에서 삭제됨
     
     

영속성 컨텍스트의 주요 특징

  1. 1차 캐시 (First-Level Cache)
    • 영속성 컨텍스트는 동일한 트랜잭션 내에서 엔티티를 1차 캐시에 저장한다.
      • 만약, 1차 캐시에 찾는 데이터가 없다면 DB에서 해당 데이터를 가져와 1차 캐시에 저장한 후, 1차 캐시에서 해당 데이터를 반환한다.
    • 동일한 엔티티를 반복 조회해도 항상 같은 객체를 반환한다.
    • 1차 캐시는 전역적이지 않으며 해당되는 스레드 한개에 매핑된다. 즉, 1차 캐시는 공유되지 않는 캐시이다.
    User user1 = em.find(User.class, 1L); 
    User user2 = em.find(User.class, 1L); 
    System.out.println(user1 == user2); // true
     
     
  2. 변경 감지 (Dirty Checking) 
    • 엔티티의 필드 값이 변경되면 트랜잭션 커밋 시점에 자동으로 UPDATE 쿼리를 실행한다.
    User user = em.find(User.class, 1L);
    user.setName("Updated Name"); // 변경 감지 
    em.flush(); // 데이터베이스에 변경 사항 반영

     

    자세한 내용은 https://codingdoit.tistory.com/24 에서 확인할 수 있다.
     
     
  3. 지연 로딩 (Lazy Loading)
    • 엔티티의 연관 관계를 필요한 시점까지 로딩하지 않고, 실제 사용 시점에 데이터를 가져온다. 자세한 내용은 https://codingdoit.tistory.com/25 에서 확인할 수 있다.
  4. 동일성 보장
    • 영속성 컨텍스트는 동일한 엔티티를 여러 번 조회할 때 항상 동일한 객체를 반환한다.

 

영속성 컨텍스트의 장점

  • 성능 최적화
    • 데이터베이스와의 불필요한 통신을 줄이고, 캐시를 통해 성능을 향상시킨다.
  • 코드 단순화
    • JPA가 상태 변화를 자동으로 감지하고 반영하므로, 개발자가 직접 SQL을 작성할 필요가 없다.
  • 동일성 보장
    • 동일한 엔티티를 여러 번 조회해도 같은 객체를 반환하여, 데이터 정합성을 유지한다.

 

영속성 컨텍스트 사용 시 주의할 점

  1. 메모리 관리
    • 영속성 컨텍스트는 메모리를 사용하므로, 너무 많은 엔티티를 한 번에 관리하면 메모리 문제가 발생할 수 있다.
    • EntityManager.clear()를 통해 주기적으로 컨텍스트를 비울 수 있다.
  2. 변경 감지 오버헤드
    • 변경 감지 기능은 모든 엔티티를 검사하므로, 너무 많은 엔티티를 관리하면 성능 저하가 발생할 수 있다.

 

영속성 컨텍스트와 트랜잭션

 

 영속성 컨텍스트는 트랜잭션 범위 내에서 동작한다. 트랜잭션이 종료되면 영속성 컨텍스트의 변경 사항이 데이터베이스에 반영되고, 이후 영속성 컨텍스트는 더 이상 유효하지 않다.

EntityTransaction tx = em.getTransaction(); tx.begin(); // 트랜잭션 시작
User user = em.find(User.class, 1L);
user.setName("New Name"); 
tx.commit(); // 변경 사항이 데이터베이스에 반영됨