JPA의 영속성 컨텍스트(Persistence Context)와 엔티티 매니저(EntityManager)

송현진·2025년 6월 5일
0

Jpa

목록 보기
11/11

엔티티 매니저 팩토리와 엔티티 매니저(Entity Manager Factory & Entity Manager)

Entity Manager Factory

EntityManager 인스턴스를 생성하는 팩토리 인터페이스로 JPA 구현체(Hibernate 등)에 의해 생성된다.
그림에서도 볼 수 있듯이 이 팩토리를 통해 여러 개의 EntityManager 인스턴스가 생성된다.

Entity Manager

엔티티 저장, 조회, 수정, 삭제 등 엔티티에 대한 모든 작업을 수행하는 핵심 객체다.
실제로는 이 EntityManager가 내부적으로 영속성 컨텍스트(Persistence Context)를 관리하고 그 컨텍스트를 통해 엔티티의 상태를 추적한다.

언제 EntityManager와 Persistence Context는 1:1이고, 언제 1:N 관계일까?

Jakarta Persistence 3.2 명세의 '7.1 Persistence Context' 절에 따르면, EntityManager는 관리 방식에 따라 크게 두 가지로 나뉜다: 컨테이너 관리형애플리케이션 관리형.

컨테이너 관리형(Container-managed EntityManager)

대상 환경: Jakarta EE 환경

Jakarta EE 애플리케이션에서는 @PersistenceContext를 통해 EntityManager를 의존성 주입받는다. 이 경우, 트랜잭션 범위에 따라 하나의 영속성 컨텍스트가 여러 컴포넌트에 주입된 EntityManager 인스턴스에 의해 공유된다.
즉, 하나의 Persistence Context가 여러 컴포넌트에 주입된 EntityManager 인스턴스 간에 공유되므로 1:N 관계가 성립할 수 있다.

@PersistenceContext
private EntityManager entityManager;

애플리케이션 관리형(Application-managed EntityManager)

대상 환경: Java SE, Jakarta EE Application Client(Container) 또는 독립형 Jakarta EE 컴포넌트

이 경우 EntityManagerFactory를 통해 개발자가 명시적으로 EntityManager를 생성하고 생명주기를 직접 관리한다. 이렇게 생성된 EntityManager는 각기 고유한 Persistence Context를 갖기 때문에 EntityManager와 Persistence Context는 1:1 관계로 유지된다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("unitName");
EntityManager em = emf.createEntityManager();

요약하면 Jakarta EE 환경에서는 트랜잭션 범위 내에서 하나의 Persistence Context를 여러 컴포넌트 간 공유하는 1:N 구조가 가능하지만 Java SE 및 Application Client 환경에서는 항상 1:1 관계만 허용된다.

영속성 컨텍스트(Persistence Context)란?

엔티티를 영구 저장하는 환경 또는 엔티티 객체들을 관리하는 메모리 상의 저장소이다. 이는 애플리케이션과 데이터베이스 사이에서 엔티티 객체를 관리하며 엔티티의 상태를 추적하고 변경 사항을 감지하여 데이터베이스에 반영하는 역할을 합니다.

주요 특징

  • 1차 캐시: 영속성 컨텍스트는 엔티티를 메모리에 캐시하여 동일한 엔티티를 반복적으로 데이터베이스에서 조회하지 않도록 한다.
  • 동일성 보장: 같은 트랜잭션 내에서 동일한 엔티티를 조회하면 항상 같은 객체 인스턴스를 반환한다.
  • 변경 감지(Dirty Checking): 영속성 컨텍스트는 엔티티의 변경 사항을 감지하여 트랜잭션 커밋 시 자동으로 데이터베이스에 반영한다.
  • 쓰기 지연(Write-Behind): 엔티티의 변경 사항은 즉시 데이터베이스에 반영되지 않고 트랜잭션 커밋 시 한꺼번에 반영된다.

장점

  • 성능 향상: 1차 캐시를 통해 데이터베이스 접근을 최소화하여 성능을 향상시킨다.
  • 데이터 일관성 유지: 변경 감지를 통해 엔티티의 상태를 자동으로 추적하여 데이터 일관성을 유지한다.
  • 개발 편의성: 엔티티 매니저를 통해 데이터베이스 작업을 추상화하여 개발자의 부담을 줄여준다.

엔티티의 생명주기

엔티티에는 4가지 상태가 존재한다.

  • 비영속(new/transient): 영속성 컨텍스트와 전혀 관계없는 새로운 상태
  • 영속(managed): 영속성 컨텍스트에 저장된 상태
  • 준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed): 삭제된 상태

비영속

new 키워드로 객체를 생성했지만 아직 EntityManager.persist()를 호출하지 않은 상태이다. 영속성 컨텍스트에 등록되지 않았기 때문에 아무런 DB 작업도 발생하지 않는다.

Member member = new Member();
member.setId("member1");
member.setUsername("회원1");

영속

EntityManager.persist(member)를 호출하면 해당 객체는 영속성 컨텍스트에 저장된다. 이제부터는 JPA가 해당 엔티티의 상태 변화를 추적하며 트랜잭션 커밋 시 자동으로 DB 반영이 된다. 1차 캐시에 등록되며 동일 ID로 조회하면 항상 같은 객체 반환된다.

em.persist(member);

준영속

엔티티는 영속성 컨텍스트에서 분리되며 더 이상 상태 변화가 감지되지 않는다.

  • em.detach(entity)
  • em.clear()
  • 트랜잭션 종료 (커밋 또는 롤백)

따라서 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.

em.detach(member);
member.setUsername("변경된 이름"); // 반영되지 않음, 커밋해도 UPDATE 쿼리 X

삭제

EntityManager.remove(entity)를 호출하면 해당 엔티티는 삭제 예약 상태로 전환된다. 실제 DB에서 삭제되는 시점은 flush()가 호출되거나 트랜잭션이 커밋될 때이다.

em.remove(member);

참고

profile
개발자가 되고 싶은 취준생

0개의 댓글