영속성 컨텍스트에 대한 정리

유수민·2022년 7월 11일
0

지식창고

목록 보기
24/64

📌내가 생각한 영속성 컨텍스트는?

영속성 : 데이터를 영구적으로 저장하는 것.
컨텍스트 : 대상의 모든 정보를 가지고 있는 것.
영속성 컨텍스트

  • 자바가 데이터 베이스에서 왔다갔다하는 모든 것들을 알고 있다. 자바와 데이터베이스의 중간단계
  • 자바는 영속성 컨텍스트를 통해 데이터를 저장하고 디비도 영속성 컨텍스트를 통해 데이터를 전달한다.

출처) 수민 뇌

  • 그림의 1번과 같이 데이터베이스의 정보가 영속성 컨텍스트의 1차 캐시에 존재하면 요청시 DB까지 가지 않고 바로 영속성 컨텍스트에서 데이터전달을 받는다.
  • 만약 그림의 2번과 같이 영속성 컨텍스트에 관련 데이터가 없으면 데이터베이스에서 데이터를 전달 받아 영속성 컨텍스트의 1차에 캐시에 넣고, 1차 캐시에 있는 데이터를 전달받는다.

하지만 이것은 내가 어렴풋이 아는 내용이고, 좀 더 자세히 영속성 컨텍스트를 설명해보자면,

📌영속성 컨텍스트란?

‘시스템이나 애플리케이션이 종료되도 데이터는 남아있도록 엔티티(Entity)를 저장하고 관리하는 저장소’라 생각하면 된다. 애플리케이션과 DB 사이에서 엔티티를 보관하는 가상의 DB 역할을 한다. 실제로 물리적으로 할당된 공간이 아닌 논리적/추상적인 개념이다.

영속성 컨텍스트는 EntityManager를 통해 접근한다. 즉, DB에 직접 저장하는 것이 아닌 EntityManager를 이용해서 Entity를 영속성 컨텍스트에 저장하는 것이다.

💡 EntityManager란?

  • EntityManager는 CRUD와 같은 엔티티와 관련된 모든 작업들을 처리해주는 관리자
  • JPA는 매 요청마다 EntitiyManagerFactory에서 EntityManager를 생성해주고, DB커넥션 풀을 사용하여 데이터베이스에 연결한다.
  • 보통 EntityManager가 생성되면 영속성 컨텍스트도 함께 생성된다. 스프링 프레임워크등을 사용할 경우에는 여러 개의 EntityManager가 하나의 영속
    성 컨텍스트를 공유해서 사용한다. (N:1관계)

📖영속성 컨텍스트를 통해 관리하는 이유

  • 1차 캐시
  • 동일성 보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경 감지(Dirty Checking)
  • 지연 로딩(Lazy Loading)

📚1) 1차 캐시

EntityManager를 통해 데이터를 insert하거나 select하면 영속성 컨테스트에 1차적으로 엔티티를 기록한다.

엔티티 조회 시

  1. 1차 캐시에서 조회
  2. 1차 캐시에 없을 경우 DB에서 조회 (1차 캐시에 저장 후 반환)

즉, 한번 find() 메서드등을 통해 1차 캐시에 저장되어 있다면, 같은 객체를 찾는 find() 에서는 DB를 거치지 않아 쿼리를 수행하지 않고 중간에 캐시된 데이터를 바로 가져올 수 있다.

📚2) 동일성 보장

JPA는 1차 캐시에 저장된 것을 가져오는 것이기 때문에 컬렉션에 이미 있는 값을 가져오는 것과 같은 효과를 누릴 수 있다. 따라서, 객체를 여러번 조회하더라도 동일성을 보장하기 때문에 데이터베이스의 트랜잭션 격리 레벨을 REPEATABLE READ로 할 필요가 없어진다.

📚3) 변경감지

EntityManager 에는 INSERT, DELETE, SELECT 를 담당하는 메서드는 존재하지만 UPDATE에 관련된 메서드는 없다. 그 이유는 1차 캐시에 존재하는 엔티티(영속 상태)는 속성의 변경이 이루어지면 UPDATE를 flush()시점에 수행하기 때문이다.

엔티티 수정 순서를 정리 하자면,

(1) 1차 캐시로 기록하면서 동시에 저장되는 시점의 최초 상태를 복사하여 스냅샷을 생성해둔다.
(2) 그 이후, 엔티티의 변화된 상태로 커밋
(3) 엔티티 매니저 내부에서 먼저 변경 내용을 반영하는 메서드인 flush() 호출
(4) 영속성 컨텍스트의 1차 캐시와 스냅샷을 비교
(5) 변경사항이 있는 경우 Update SQL Query를 생성하여 쓰기 지연 SQL 저장소로 보낸다.
(6) flush가 끝나기 전 쓰기 지연 저장소의 SQL를 DB에 날린다.
(7) 데이터베이스 트랜잭션을 커밋

📚4) 지연로딩

계속 변경이 일어나면 DB에 매번 쿼리를 보내기보단, SQL을 생성하여 쓰기 지연 저장소에 저장했다가, 트랜잭션이 커밋되는 순간 한번에 DB에 전송하게 하는 것. 성능상 이점을 가져온다.

💡 Flush

플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다. 영속성 컨텍스트의 변경 사항들과 데이터베이스를 동기화하는 작업이다.

💡플러시가 발생하면 어떤 일이 생기나?

  • 변경을 감지한다. Dirty Checking.
  • 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록한다.
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.(등록, 수정, 삭제 SQL)
  • 플러시가 발생한다고 커밋이 이루어지는게 아니고, 플러시 다음에 커밋이 일어난다.

💡Commit
커밋을 수행하게 되면 내부적으로 EntityManager 의 flush() 메서드를 호출한 후 트랜잭션을 닫는다.

💡Commit vs Flush
flush는 쿼리를 전송하는 역할이고 commit은 내부적으로 flush를 수행한 뒤 트랜잭션을 끝내는 역할.

profile
배우는 것이 즐겁다!

0개의 댓글