[Spring] JPA 영속성 관리

민스킴·2023년 9월 17일
0

Spring

목록 보기
3/12

영속성 관리

JPA 영속성 관리에 대해서 알아보겠습니다.

영속성 관리라는 말이 어렵게 느껴질 수 있는데,
쉽게 말해서 JPA가 엔티티를 어떻게 관리하는지를 의미합니다.

JPA는 영속성 컨텍스트라는 것에 엔티티를 등록해서 관리해요.
(영속성 컨텍스트에 등록되지 않았다면 관리하지 않습니다.)

영속성 컨텍스트는 엔티티 매니저를 통해서만 접근이 가능합니다.
엔티티 매니저를 만들면 내부에 영속성 컨텍스트도 같이 만들어져요!

엔티티 매니저는 엔티티 매니저 팩토리로 생성이 가능합니다. 엔티티 매니저 팩토리는 만드는 비용이 상당히 크기 때문에 애플리케이션 전체에서 한 개만 만들어서 공유합니다. (팩토리는 여러 스레드에서 동시 접근해도 안전하나, 매니저는 여러 스레드에서 동시에 접근하면 안됩니다!!!)


엔티티의 생명주기

엔티티에는 4가지 상태가 존재합니다.

  • 비영속
  • 영속
  • 준영속
  • 삭제

엔티티 컨텍스트와 전혀 관계가 없으면 비영속, 저장되어 있으면 영속, 저장 되었다가 분리되면 준영속, 저장 되었다가 삭제시키면 삭제 입니다.

영속성 컨텍스트는 엔티티를 식별자 값(@Id로 테이블의 기본 키와 매핑한 값)으로 구분됩니다. 따라서 영속 상태는 식별자 값이 반드시 있어야 합니다!


영속성 컨텍스트의 개쩌는 점

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

영속성 컨텍스트는 1차 캐시로 엔티티를 저장하고 있습니다. 따라서 find()를 호출했을 때 캐시에 엔티티가 존재한다면 데이터베이스에 접근하지 않고, 캐시에 있는 엔티티를 반환합니다.
매번 영속성 컨텍스트에서 캐시된 엔티티를 반환하기 때문에, 같은 트랜잭션에서는 엔티티의 동일성도 보장하죠.

엔티티 매니저는 트랜잭션을 커밋하기 직전까지 DB에 쿼리를 보내지 않고 내부 쿼리 저장소에 차곡차곡 모아둡니다. 그리고 커밋하는 순간에 모아둔 쿼리를 DB에 보낸죠. 이것을 트랜잭션을 지원하는 쓰기 지연이라고 합니다.
(이 덕분에 DB에 접근하는 횟수를 줄여 최적화를 할 수 있어요!)

JPA로 엔티티를 수정할 때는 단순히 find()로 엔티티를 조회하고 데이터만 변경해주면 됩니다.
따로 update()같은 메소드를 실행할 필요가 없어요. 이게 가능한 이유는 엔티티의 변경사항을 자동으로 감지하고 반영하는 변경 감지(dirty checking) 기능 덕분입니다.

위 이미지를 보면 스냅샷이라는게 있습니다. 스냅샷은 엔티티를 영속성 컨텍스트에 처음 보관할 때 상태를 저장해둔 것 입니다.
트랜잭션을 커밋하면 먼저 flush()가 호출되면서 스냅샷과 엔티티를 비교하고, 수정 쿼리를 작성해서 쓰기 지연 SQL 저장소에 보냅니다. 그 후에 쓰기 지연 SQL 저장소를 flush 하면서 저장된 모든 쿼리를 데이터베이스에 보내고 데이터베이스 트랜잭션이 커밋됩니다.

변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됩니다.

엔티티가 다른 엔티티를 참조하고 있을 때, 프록시 객체를 사용하여 지연 로딩을 사용할 수도 있습니다.

지연 로딩은 영속성 컨텍스트에 엔티티를 등록할 때, 연관된 엔티티를 바로 DB에 쿼리를 보내서 조회하고 같이 등록하지 않고, 프록시 객체를 만들어서 엔티티가 참조하게 한뒤 나중에 엔티티가 연관 엔티티를 사용하는 시점에 DB에서 조회하고 등록하는 기술입니다.

지연 로딩에 관해서는 다음에 프록시와 연관 관계를 정리할 때 자세히 다루겠습니다.


다음 글: 프록시와 연관 관계

profile
Boys, be ambitious!

0개의 댓글