잉?

영속성 컨텍스트 알아가기 본문

자바(Java)/JPA

영속성 컨텍스트 알아가기

Jye_647 2024. 12. 3. 01:46
JPA를 배우고 CRUD를 적용하면서, 문득 작성해야 하는 코드들에 대해 의문이 들었다. 물론 어렴풋이 이유를 이해하고 있지만, 그 이해가 깊지 않아 이번 기회에 확실히 짚고 넘어가고자 한다.
특히, 연관관계 매핑을 설정할 때 영속성 컨텍스트의 중요성을 깨달았다. 단순히 "다대다, 일대다 관계를 맺어줘야 할 것 같다"는 막연한 이유로 매핑을 추가하는 것이 아니라, 불필요한 매핑은 성능 저하를 초래할 수 있음을 인지하고 명확한 필요성을 느낄 때만 매핑을 작성해야 한다는 점을 깨달았다.
또한, JPA의 영속성 컨텍스트가 어떻게 동작하는지 흐름을 이미지로 이해하고, 이를 기반으로 @Transactional 어노테이션을 사용하지 않았을 때 어떤 문제가 발생할 수 있는지 알아보자.

출처 : 인프런 김영한님의 ‘자바 ORM 표준 JPA 프로그래밍’

 


영속성 컨텍스트란 ?

영속성 컨텍스트란 엔티티를 영구 저장하는 환경을 말한다.

애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상 데이터베이스라고 볼 수 있다.

엔티티 매니저를 통해 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.

 


1차 캐시

영속성 컨텍스트 내부에는 캐시가 있다. 이를 1차 캐시라 부른다.

1차 캐시는 트랜잭션 범위 내에서 엔티티를 캐싱하여 데이터베이스와의 중복 조회를 방지한다.

Member member = em.find(Member.class, "member2"); // em.find(엔티티 클래스 타입, 식별자 값);
  1. 엔티티를 조회하면 영속성 컨텍스트의 1차 캐시에 먼저 저장된다.
  2. 동일한 엔티티를 다시 조회하면 데이터베이스를 조회하지 않고 1차 캐시에서 반환된다.
  3. 1차 캐시는 엔티티의 식별자(PK)를 기준으로 엔티티를 관리한다.
  4. 엔티티 변경 시, 변경된 내용을 영속성 컨텍스트에 반영하며 데이터베이스 쿼리는 트랜잭션 종료 시점에 실행된다.
  5. 트랜잭션이 종료되면 1차 캐시는 초기화된다.

쓰기 지연

쓰기 지연은 말 그대로 지연하는 것이다. JPA의 영속성 컨텍스트가 SQL 쿼리를 즉시 실행하지 않고, 트랜잭션이 커밋될 때까지 쿼리를 모아뒀다가 한꺼번에 실행하는 방식이다.

 

  1. EntityManager.persist() 또는 Repository.save() 호출 시, 엔티티는 영속성 컨텍스트에 저장된다.
  2. 실행된 쿼리는 쓰기 지연 SQL 저장소에 쌓이고, 즉시 데이터베이스에 전달되지 않는다.
  3. 트랜잭션이 커밋되는 시점에 저장된 쿼리를 데이터베이스에 실행한다.
  4. 영속성 컨텍스트는 트랜잭션이 종료될 때 초기화된다.

변경 감지 (Dirty Checking)

JPA가 영속성 컨텍스트 내에서 관리 중인 엔티티의 상태를 감시하여, 변경된 필드가 있을 경우 자동으로 업데이트 쿼리를 생성하는 기능이다.

 

  1. 영속성 컨텍스트가 엔티티를 로드하고 스냅샷을 저장한다.
  2. → 스냅샷은 엔티티가 처음 조회되거나 저장될 때, 해당 엔티티의 원본 상태를 말한다.
  3. 필드 값을 수정하면 영속성 컨텍스트가 스냅샷과 현재 상태를 비교한다.
  4. 스냅샷과 다른 값이 발견되면 쓰기 지연 저장소에 UPDATE 쿼리를 저장한다. → 변경감지
  5. 트랜잭션 종료 시 flush()를 통해 쿼리가 데이터베이스에 반영된다.
  6. → flush는 트랜잭션 커밋 전에 자동으로 호출되며, 변경 사항을 데이터베이스와 동기화한다. sync

요약 : 더티 체킹 → 쓰기 지연 저장소 저장 → flush → 커밋

Comments