[JPA] 영속성 컨텍스트 이해하기 (w. Entity manager)

Kai·2023년 1월 9일
1

JPA

목록 보기
1/5

☕ 시작


이번 글에서는 JPA에서 가장 중요한 개념 중에 하나인 영속성 컨텍스트(Persistence Context)와 이를 다루는 EntityManager를 알아보도록 하겠다.


🧐 EntityManager란?


JPA를 사용하기 위해서는 Database 구조와 맵핑된 JPA Entity 들을 먼저 생성하게 된다.
그리고, 모든 JPA의 동작은 이 Entity들을 기준으로 돌아가게 되는데, 이 때 Entity들을 관리하는 역할을 하는 녀석이 바로 EntityManager인 것이다.


⚡ EntityManager의 동작


JPA는 기본적으로 한 요청 당, 하나의 EntityManager를 사용한다.
또, 각 EntityManager들은 정해진 영속성 컨텍스트를 참조하게 된다.
그리고 이렇게 만들어진 EntityManager로 데이터를 다루려면 가장 먼저 Entity가 "영속화"되어 있어야 한다.

참고) 일반적으로는 EntityManager 한 개당 하나의 영속성 컨텍스트를 갖지만, 스프링에서는 공통된 영속성 컨텍스트 하나를 여러 EntityManager가 참조한다.

음... 글로 보니 너무 어렵다.
좀 더 쉽게 이야기 한다면, DB에 있던 데이터 또는 사용자가 넘긴 데이터를 Entity로 만든 후, EntityManager의 영속성 컨텍스트에서 들고 있겠다는 것이다.
간단히 정리해보자면, 아래와 같을 것이다.

1. (요청)
2. EntityManager 만들어짐
3. Entity들을 영속성 컨텍스트에 생성 -> Entity 영속화
4. Entity Manager가 영속성 컨텍스트를 기반으로 요청(생성, 조회, 수정, 삭제)처리

이 때, 각 Entity들은 상황에 맞게 생명주기를 갖게 된다.


Entity의 생명주기

아래의 이미지는 User를 생성하는 예제이다.

JPA의 Entity는 영속성 컨텍스트를 기준으로 'Entity가 어떻게 되어있냐?'라는 질문에 대응하는 상태를 갖는다.
그 상태들은 아래와 같다.

  • 비영속: 영속성 컨텍스트와 무관한 새로운 데이터인 경우
    ex) 클라이언트에서 넘어 온 데이터를 영속화하기 전의 상태
  • 영속: 영속성 컨텍스트에 주입 또는 관리되고 있는 경우
    ex) 클라이언트에서 넘어 온 데이터를 영속화함
  • 준영속: 영속화 되었다가 분리된 경우(또는 식별자는 있지만 영속성 컨텍스트에 없는 객체)
    ex) 데이터를 수정할 때, 클라이언트 측에서 넘어온 id를 갖고 있는 객체
  • 삭제: 영속성 컨텍스트에서 아예 삭제된 데이터

🧐 영속성 컨텍스트란?


위에서 충분히 이야기했지만 다시 정리하자면, 영속성 컨텍스트는 JPA에서 엔티티를 관리하기 위해서 만들어져있는 어떠한 공간이라고 할 수 있겠다.


영속성 컨텍스트를 쓰는 이유

JPA에서 영속성 컨텍스트라는 DB와 시스템 간의 중개자 역할을 하는 개념을 사용하는 이유는 이러한 구조가 갖는 장점들 때문이다.
어떠한 장점들이 있는지 하나하나 알아보자.

  1. 캐싱(1차 캐시)
    ex) 데이터를 조회하는 기능을 처리할 때, DB에서 바로 조회하는 것이 아니라 영속성 컨텍스트에서 먼저 조회한다.
  2. 영속된 엔티티의 동일성 보장 (1차 캐시의 연장선)
    ex) 영속되어 있는 동일한 id를 갖는 엔티티를 2번 조회한다고 가정해보자. 이 때, 조회된 각각의 객체는 동일한 주소값을 같는다. 즉, 정확히 동일한 객체인 것이다.
  3. 쓰기 지연
    ex) 트랜잭션을 commit하는 순간에 영속성 컨텍스트의 엔티티에 대한 쿼리를 DB에 실행한다.
  4. 변경 감지(Dirty checking)
    ex) 영속된 엔티티를 수정하면, 트랜잭션이 commit되는 순간 변경 쿼리가 DB에 실행된다.

트랜잭션 commit에 쿼리가 실행되는 원리

사실 JPA에서 DB의 트랜잭션이 commit되는 것을 알 수는 없다.
그런데, 어떻게 트랜잭션 commit이 일어나면 그에 맞는 쿼리들을 한번에 실행하는 것일까?

사실은 EntityManager의 flush() 메서드가 실행되어서 그런것이다.
JPA를 쓰면 EntityManager로 트랜잭션을 생성할 것이다.
이렇게 생성한 트랜잭션을 commit시키면 내부적으로 fluse()메서드가 실행된다.
그래서 이 순간, DB 쿼리들이 실행되는 것이다.


☕ 마무리

이렇게 EntityManager와 영속성 컨텍스트에 대해서 나름 알아봤는데... 설명을 잘 못한 것 같다 ㅎㅎ;;
개인적으로는 누군가에게 쉽게 설명하지 못하면 그 지식이 '내 것'이 아니라고 생각하는데...
영속성 컨텍스트는 내께 아닌가보다 😂

추후에 좀 더 글을 다듬어 봐야겠다..

0개의 댓글