728x90
JPA 캐시
- 네트워크를 통해서 데이터베이스에 접근하는 시간 비용은 애플리케이션 서버 내부 메모리에 접근하는 시간보다 훨씬 비싸다
- 따라서 조회한 데이터를 메모리에 캐싱해두면 데이터베이스 접근 횟수를 줄여 성능을 개선할 수 있다
영속성 컨텍스트
- 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 논리적 개념
- EntityManager를 통해서 영속성 컨텍스트에 접근한다
- EntityManager가 생성되면 논리적 개념인 영속성 컨텍스트(Persistence Context)가 1:1로 생성된다
- 영속성 컨텍스트에서 관리되는 엔티티의 상태를 '영속 상태'라고 한다
영속성 컨텍스트의 장점
- 1차 캐시 / 엔티티 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (Transactional write-behind)
- 지연 로딩 (Lazy Loading)
- 변경 감지 (Dirty Checking)
1️⃣ 1차 캐시
- 영속성 컨텍스트 내부에는 엔티티를 보관하는 저장소가 있는데, 이를 1차 캐시라고 한다
- 영속성 컨텍스트 자체가 사실상 1차 캐시이기 때문에 1차 캐시는 끄고 켤 수 있는 옵션이 아니다
- 엔티티 매니저로 조회하거나 변경하는 모든 엔티티는 1차 캐시에 저장된다
- 트랜잭션을 커밋하거나 플러시를 호출하면 1차 캐시에 있는 엔티티의 변경 내역을 데이터베이스에 동기화한다
- 일반적으로 트랜잭션을 시작하고 종료할 때까지만 1차 캐시가 유효하다
- 따라서 애플리케이션 전체로 보면 데이터베이스 접근 횟수를 획기적으로 줄이지는 못한다
- OSIV를 사용하더라도 사용자의 요청이 들어올 때부터 끝날 때까지만 1차 캐시가 유효하다
💡 OSIV (Open Session In View)
- 영속성 컨텍스트를 뷰까지 열어두는 기능
- 영속성 컨텍스트가 유지되면 엔티티도 영속 상태로 유지된다
- 뷰까지 영속성 컨텍스트가 살아있다면 뷰에서도 지연 로딩을 사용할 수가 있다
1차 캐시의 동작 방식
1) 데이터가 1차 캐시에 없을 때
- 최초 조회 시, 엔티티가 없으므로 DB 데이터를 조회한다
- DB에서 조회한 데이터를 영속성 컨텍스트 내부 저장소(1차 캐시)에 보관한다
- 1차 캐시에 있는 데이터를 반환한다
2) 데이터가 1차 캐시에 있을 때
- 1차 캐시(영속성 컨텍스트)에 데이터가 있으므로 데이터를 반환한다
- (DB는 조회하지 않는다!)
1차 캐시의 특징
- 같은 엔티티가 있으면 객체 동일성을 보장한다
- 객체끼리 비교했을 때 같다
- 객체 1 == 객체 2
- OSIV (Open Session In View) 를 사용한다면 서버에서 응답이 나갈 때까지 1차 캐시가 유효하지만, OSIV가 꺼져있으면 트랜잭션이 종료되어 1차 캐시는 없어진다
- EntityManager를 통해 save를 하면 영속성 컨텍스트에 저장되지만, JPQL을 사용할 경우 영속성 컨텍스트를 조회하지 않고 데이터베이스를 먼저 조회한다
- JPQL을 통해 DB를 조회한다
- 조회한 결과를 영속성 컨텍스트에 저장을 시도한다
- 영속성 컨텍스트에 조회한 결과가 있다면 DB에서 조회한 데이터를 버린다
2️⃣ 2차 캐시
- 애플리케이션 범위의 캐시로, 공유 캐시라고도 한다
- Hibernate를 포함한 대부분의 JPA 구현체들은 2차 캐시를 지원한다
- 따라서 애플리케이션을 종료할 때까지 캐시가 유지된다
- 분산 캐시나 클러스터링 환경의 캐시는 애플리케이션보다 더 오래 유지될 수도 있다
- 2차 캐시를 적용하면 엔티티 매니저를 통해 데이터를 조회할 때, 1차 캐시에서 엔티티를 찾아보고 없으면 2차 캐시까지 찾아보고 데이터베이스에서 찾기 떄문에 2차 캐시를 적절히 활용하면 데이터베이스 조회 횟수를 획기적으로 줄일 수 있다
2차 캐시의 동작 방식
- 영속성 컨텍스트에서 2차 캐시를 조회한다
- 2차 캐시에 데이터가 없으면 DB를 조회한다
- DB에서 조회한 데이터를 2차 캐시에 보관한다
- 2차 캐시에 저장된 엔티티를 복사해서 반환한다
2차 캐시의 특징
- 동시성을 극대화하기 위해 한 객체를 직접 반환하지 않고 복사본을 만들어서 반환한다
- 캐시한 객체를 그대로 반환하면 여러 곳에서 같은 객체를 동시에 수정하는 동시성 문제가 발생할 수 있어 복사본을 반환한다!
- 이를 해결하기 위해서는 객체에 Lock을 걸어야 하는데, 그러면 동시성이 떨어질 수 있다
- 따라서 2차 캐시는 원본 대신 복사본을 반환한다
- 영속성 컨텍스트가 다르면 객체 동일성을 보장하지 않는다
참고)
https://willseungh0.tistory.com/m/77
https://insanelysimple.tistory.com/m/353
728x90
'야미스터디 > Java' 카테고리의 다른 글
[Java - Stream] 02. 컬렉션과 Stream의 구현방식의 차이 (0) | 2022.12.07 |
---|---|
[Java - Stream] 01. 스트림을 학습해야 하는 이유 (0) | 2022.12.07 |
[Java] Checked Exception vs Unchecked Exception 📌 (1) | 2022.10.14 |
[Java] Java 버전 별 차이점📌 (0) | 2022.09.06 |
[Java] JDK, JRE, JVM (0) | 2022.09.04 |
댓글