포스트

[데이터베이스 이론] JPA 핵심 엔진 : EntityManager 넌 어떤녀셕이냐?!?

자바 전형 백엔드 개발자에서 ORM 프레임워크인 JPA (Java Persistence API) 를 사용한다면, EntityManager라는 이름을 수도 없이 마주치셨을겁니다. 제가 지금 하고 있는 프로젝트는 Mybatis기반으로 JPA 를 사용하지 않지만요

실 프로젝트에서는 사용하지 않지만 JPA에 대한 공부와 사이드프로젝트에서 사용해본 내용을 정리 해보려고 해요. 정확히 이 Entity Manager가 하는 역할이 어떤건지 명확하게 한번 같이 알아봅시다


EntityManager, 한마디로 정리한다면?

EntityManager는 JPA에서 Entity(엔티티)를 관리하는 객체입니다. 여기서 ‘엔티티’는 우리가 @Entity 어노테이션을 붙여 매핑한 자바객체를 의미합니다. 쉽게 말해 EntityManager는 자바 객체와 데이터베이스 테이블을 연결해주는 다리 역할을 한다고 생각하시면 됩니다.

우리가 자바 객체를 저장하거나, 조회하거나, 수정하거나, 삭제하는 모든 작업은 EntityManager를 통해서 이루어져야 합니다.

EntityManager의 핵심 역할 : 영속성 컨텍스트 (Persistence Context) 관리

EntityManager 의 가장 중요한 역할은 바로 영속성 컨텍스트를 관리하는 것입니다.

영속성 컨텍스트는 EntityManager가 엔티티를 영속(Persist) 시키는 환경을 의미합니다. 쉽게 말해, “엔티티 객체를 담아두는 논리적인 공간” 입니다., 이 공간에 엔티티가 담겨 있는 한, EntityManager는 이 엔티티의 상태 변화를 추적하고, 적절한 시점에 데이터베이스에 반영합니다.

영속성 컨택스트는 다음과 같은 특징을 가집니다.

  • 1차 캐시(First-Level Cache) : 영속성 컨텍스트 내부에 엔티티를 캐싱하여, 동일한 엔티티를 여러 번 조회해도 데이터베이스에 한 번만 접근하게 하여 성능을 향상시킵니다.
  • 동일성 보장 : 영속성 컨텍스트에서 같은 엔티티(동일한 ID)를 조회하면 항상 동일한 인스턴스를 반환하여 객체의 동일성을 보장합니다.
  • 트랜잭션을 통한 DB 동기화 : 트랜잭션이 커밋되는 시점에 영속성 컨텍스트에 있는 엔티티의 변경 내용을 데이터베이스에 자동으로 반영합니다. 이를 쓰기 지연 이라고도 합니다.

엔티티의 4가지 생명 주기 (Lifecycle)

EntityManager를 통해 엔티티는 다음 4가지 상태를 오가며 관리됩니다.

  1. 비영속
    • 객체를 생성했지만 아직 영속성 컨텍스트에 저장되지 않은 상태, EntityManager와 아무런 관련이 없습니다.
    • 예시 : Member member = new Member();
  2. 영속
    • 객체가 영속성 컨텍스트에 저장되어 EntityManager의 관리를 받는 상태.
    • EntityManager가 엔티티의 변경을 감지하고 데이터베이스에 반영할 준비를 합니다.
    • 예시 : em.persist(member) (이 시점에 DB에 저장되는 것 아님!)
    • 예시 : em.find(Member.class, id) (데이터베이스에서 조회해 오면 바로 영속 상태가 됨)
  3. 준영속
    • 객체가 영속성 컨텍스트에서 분리된 상태, 영속성 컨텍스트가 더 이상 데이터를 관리하지 않습니다.
    • 한번 영속 상태였던 객체가 영속성 컨텍스트에서 분리된 것이므로, 여전히 식별자(ID) 값을 가지고 있습니다.
    • 예시 : em.detach(member), em.clear(), em.close()
  4. 삭제
    • 객체가 영속성 컨텍스트와 데이터베이스에서 삭제될 준비가 된 상태
    • 트랜잭션 커밋 시 데이터베이스에서는 해당 엔티티가 삭제됩니다.
    • 예시 : em.remove(member)

EntityManager의 주요 메서드 역할

  • persist(Object entity)
    • 엔티티를 영속성 컨텍스트에 저장합니다. (쓰기 지연 SQL 저장소에 쌓입니다.)
    • 트랜잭션 커밋 시점에 실제 INSERT SQL이 데이터베이스로 전송됩니다.
  • find(Class entityClose, Object primaryKey)
    • 영속성 컨텍스트에서 엔티티를 먼저 찾습니다 (1차 캐시)
    • 없으면 데이터베이스에서 조회하여 영속성 컨텍스트에 저장한 후 엔티티를 반환합니다.
  • remove(Object entity)
    • 엔티티를 영속성 컨텍스트에서 삭제하고, 트랜잭션 커밋 시 DB에서 해당 엔티티를 삭제합니다.
  • merge(Object entity)
    • 준영속 상태의 엔티티를 다시 영속 상태로 만들 때 사용합니다.
    • 병합하려는 엔티티가 영속성 컨텍스트에 없으면 DB에서 조회하고, 영속성 컨텍스트에 있으면 기존 엔티티를 반환합니다.
    • 주로 웹 애플리케이션에서 사용자가 폼으로 수정된 데이터를 전송하면, 해당 데이터를 DB에 반영할 때 사용됩니다.
  • flush()
    • 영속성 컨텍스트의 변경 내용을 즉시 데이터베이스에 반영합니다 (트랜잭션 커밋 전에 강제로 DB동기화)
  • clear()
    • 영속성 컨텍스트를 초기화ㅎ여, 모든 엔티티를 준영속 상태로 만듭니다.
  • close()
    • EntityManager 인스턴스를 닫습니다. 영속성 컨텍스트도 함께 종료됩니다.

EntityManager 생명주기와 스코프

일반적으로 EntityManager는 요청 하나당 하나의 인스턴스가 생성되고 소멸되는 ‘트랜잭션 스코프’로 관리됩니다.

  • 웹 애플리케이션에서는 하나의 HTTP 요청이 들어오면 EntityManager가 생성되고, 해당 요청에 대한 모든 비즈니스 로직(조회, 저장, 수정 등)을 처리한 후 요청이 끝나면 EntityManager가 자동으로 종료됩니다.
  • 스프링(Spring) 같은 프레임워크에서는 이 EntityManager의 생성, 관리, 종료를 AOP(Aspect-Oriented Programming)를 통해 자동으로 처리해 주기 때문에 개발자가 직접 em.close()를 호출할 필요가 없습니다. (@PersistenceContext 어노테이션 등으로 주입받아 사용하죠.)

마무리하며

EntityManager는 JPA를 효과적으로 사용하기 위한 핵심 개념입니다. 이 EntityManager가 영속성 컨텍스트를 관리하며 엔티티의 생명주기를 책임지고, 변경 감지, 1차 캐시 등의 기능을 통해 ORM의 장점을 극대화하는 것을 이해하는 것이 중요합니다.

처음에는 어렵게 느껴질 수 있지만, EntityManager와 영속성 컨텍스트의 관계를 명확히 이해한다면 JPA를 훨씬 효율적으로 활용하고, 복잡한 데이터 관련 문제들을 더욱 수월하게 해결할 수 있을 것입니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.