[JPA] 영속성 컨텍스트

Bam·2025년 5월 14일
0

Spring

목록 보기
51/73
post-thumbnail

영속성 Persistence

영속성 Persistence는 '계속 지속됨'이라는 의미를 가진 단어로 컴퓨터공학에서는 프로그램이 종료된 후에도 데이터가 사라지지않고 유지되는 특성을 의미하는 단어입니다.

JPA에서 영속성은 Entity(자바 객체)의 상태 변화를 데이터베이스에 안전하게 저장하고 관리하고자 하는 특성을 의미합니다.


엔티티 매니저

엔티티 매니저는 엔티티를 조회/저장/수정/삭제와 관련된 엔티티 업무를 처리하는 관리자의 역할을 합니다. 일종의 가상 데이터베이스로 생각하여 엔티티를 저장하고 관리한다 정도로 생각하시면 됩니다.

기본 스프링과 JPA에서는 엔티티 매니저 팩토리로 부터 엔티티 매니저를 생성하고 사용하도록 되어있습니다.

그리고 스프링부트 환경에서는 spring-boot-starter-data-jpa dependency를 사용하면 자동으로 엔티티 매니저 팩토리 빈, 엔티티 매니저 빈이 생성 및 주입되기 때문에 스프링부트를 사용한다면 따로 엔티티 매니저 빈을 정의하지 않아도 됩니다.


영속성 컨텍스트

영속성 컨텍스트 Persistence Context엔티티 매니저를 통해 조회하거나 저장한 엔티티 인스턴스의 집합입니다. 즉, 엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 영속성 컨텍스트에 엔티티를 보관하고 관리하게 됩니다.

엔티티 생명주기

JPA에서 엔티티는 비영속, 영속, 준영속, 삭제 4 가지 생명주기를 갖습니다.

  • 비영속 Transient
    엔티티가 생성되었으나 EntityManager에 의해 등록되지 않은 상태
  • 영속 Persistent
    em.persist() (또는 em.find() 등)을 통해 영속성 컨텍스트에 관리가 시작된 상태
  • 준영속 Detached
    영속성 컨텍스트가 닫히거나 em.detach()로 분리되어 관리되지 않는 상태
  • 삭제 Removed
    em.remove()로 삭제 예약이 된 상태. 커밋시 DELETE 쿼리가 수행

이때 영속 상태의 엔티티는 변경 감지(dirty check)를 통해 필드 변경이 자동적으로 감지되어 트랜잭션 커밋(또는 flush()) 시점에 자동으로 INSERT/UPDATE/DELETE SQL이 수행됩니다.

준영속

영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 것을 준영속 상태라고 합니다. 준영속 상태에서는 영속성 컨텍스트에서 분리되었기 때문에 영속성 컨텍스트가 제공하는 기능을 사용할 수 없습니다.

준영속 상태는 거의 비영속 상태에 가깝지만 한 번 영속 상태가 되었다 돌아온 것이기 때문에 식별자 값을 반드시 가지고 있다는 차이점이 있습니다.

또한 준영속 상태에서는 지연 로딩 Lazy Loading 사용시 문제가 발생합니다.

지연 로딩 Lazy Loading은 실제 객체 대신 프록시 객체를 로딩해놓고, 해당 객체가 실제로 사용되는 시점에 영속성 컨텍스트를 사용해 불러오는 방식을 말합니다.

영속성 컨텍스트의 특징

  • 엔티티를 식별자 값으로 구분
    영속성 컨텍스트는 엔티티를 식별자 값으로 구분합니다. 식별자 값은 @Id가 붙은 테이블의 기본키(PK)와 매핑된 값을 의미합니다.
    이는 영속 상태에서는 식별자 값이 반드시 존재해야 함을 의미합니다.

  • 플러시
    트랜잭션을 커밋하게 되면 영속성 컨텍스트에 저장된 엔티티를 데이터베이스에 적용하게 됩니다. 이를 플러시 Flush라고 부릅니다.

  • 1차 캐시
    영속성 컨텍스트가 가진 내부 캐시를 1차 캐시라고 부릅니다. 1차 캐시에 엔티티를 저장해두어서 동일 트랜잭션 내에서 동일 식별자 값을 가진 엔티티를 중복 조회하지 않게 보장해줍니다.

    조회 대상이 1차 캐시에 없으면 데이터베이스에서 조회하고 엔티티를 생성하여 1차 캐시에 저장합니다. 이런식으로 동일 트랜잭션 내에서 동일한 엔티티를 조회하고자 할 때 중복으로 데이터베이스에서 조회하지 않도록 보장합니다.

  • 변경 감지 Dirty Check
    트랜잭션 커밋 시점에 엔티티의 변경 사항을 자동으로 감지하여 INSERT/UPDATE/DELETE SQL을 수행합니다. 변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에서만 적용됩니다.

  • 쓰기 지연
    영속성 컨텍스트에 모아둔 변경사항(SQL)들을 한 번에 배치(batch)로 발행합니다.

영속성 컨텍스트 생명주기

  • 생성
    @Transactional이 붙은 메소드가 호출되면 EntityManagerFactory가 트랜잭션 범위 내의 EntityManager(영속성 컨텍스트)를 생성

  • 관리
    persist(), find() 등으로 영속성 컨텍스트에 등록된 엔터티는 영속 상태가 되어 변경 감지 활성화

  • 플러시
    flush() 호출 또는 트랜잭션 커밋 시점에 영속성 컨텍스트의 엔티티 스냅샷과 실제 엔티티 값을 비교하여 SQL 일괄 수행

  • 분리
    detach(entity)는 해당 엔티티, clear()는 전체 컨텍스트를 준영속 상태로 변경

  • 종료
    트랜잭션이 종료되고 EntityManager가 반환되면 해당 트랜잭션의 영속성 컨텍스트 폐기

@Transactional이 붙은 메소드를 트랜잭션 경계라고 합니다.

  • 메소드 진입 시 EntityManagerFactory에서 Thread-bound EntityManager를 생성하고 바인딩
  • 메소드 종료 시 flush > commit(정상 처리) or rollback(예외 발생) > EntityManager close 처리

이미지 출처

0개의 댓글