JPA 1차 캐시와 2차 캐시

pgmjun·2023년 9월 28일

JPA

목록 보기
1/2
post-thumbnail

🤔 1차 캐시는 알겠는데.. 2차 캐시가 뭐지?

김영한님의 JPA 강의를 보며 학습하던 도중, 1차 캐시에 대한 내용이 나왔다.
동시에 2차 캐시라는 것에 대해 말씀하셨는데, 2차 캐시에 대한 내용은 자세히 설명되어 있지 않아 1차 캐시와 뭐가 다를지 너무 궁금했다.

때문에 개인적으로 이에 대해 학습하여 정리하게 되었다.



💭 1차 캐시

EntityManager를 통해 Entity를 persist 했을 때
엔티티가 영속성 컨텍스트에 저장이 되는데,
이때 그냥 저장되는 것이 아닌 ‘1차 캐시’ 라는 것에 저장이 된다.

1차 캐시는 다음과 같은 Key-Value 형태의 구조를 가진다.

Key : DB의 기본키
Value : 엔티티

그렇다면 이와 같은 1차 캐시는 어떻게 사용될까?



⚙️ 1차 캐시에서 조회

EntityManger를 통해 find 명령으로 DB를 조회했을 때,
DB를 먼저 찾는 것이 아니라 영속성 컨텍스트의 1차 캐시를 먼저 조회한다.

find 시에 입력받은 id값이 1차 캐시에 존재하면 그 값을 찾아 리턴해준다.

그럼 위와 같이 persist를 한 다음, find를 수행하는 코드가 있다면,

find 수행 시 DB를 조회하지 않고 1차 캐시의 값을 가져올 것이기 때문에
select 쿼리는 사용되지 않을 것이다.

실제 결과도 insert 쿼리만 수행되는 것을 확인할 수 있었다.



⚙️ 데이터베이스에서 조회

그럼 1차 캐시에 값이 없다면 어떻게 작동할까?

  1. find 시, 1차 캐시를 조회한다.
  2. 1차 캐시에 입력받은 id를 가진 데이터가 존재하지 않으면 DB를 조회한다.
  3. DB에서 가져온 데이터를 1차 캐시에 저장한다.
  4. 1차 캐시에 저장한 값을 return한다.

‘1차 캐시에서 조회’ 실험을 하며 DB에 id가 101인 Entity가 저장되었기 때문에,
이제 코드를 조금 수정한 뒤 find를 통해 DB에서 조회하는 과정을 테스트해보자

id가 101인 Entity를 조회하는 코드가 있을 때,
첫 번째 조회 시에 1차 캐시에 엔티티가 저장되므로 두 번째 조회 시에는 select 쿼리가 필요 없다.

때문에 총 1번의 select 쿼리가 수행된다는 것이다.

그리고 예상대로 1번의 select 쿼리만이 수행되었다.



🚨 1차 캐시의 한계

좋은 기술같지만, 사실 1차 캐시는 효율성을 크게 제공해주진 못한다.

1차 캐시는 10명의 요청이 들어오면 10개의 1차 캐시가 생성된다..

또한 요청마다 생성되는 영속성 컨텍스트는 요청이 끝나고 트랜잭션이 종료될 때
함께 사라지기 때문에 1차 캐시는 큰 도움이 안되는 경우가 많다.

물론 비즈니스 로직이 굉장히 복잡한 경우엔 쿼리가 줄어들긴 하지만, 1차 캐시는 성능보다 매커니즘에서 얻는 이점이 크다.

반면, 하나의 트랜젝션이라는 작은 생명 주기를 가지는 1차 캐시와 다르게,
전체에서 공유하는 캐시는 ‘2차 캐시’라는 것이 있다.



💭 2차 캐시

애플리케이션에서 공유하는 캐시를 JPA는 공유 캐시(Shared Cache)라 하는데
일반적으로 2차 캐시 (Second Level Cache, L2 Cache)라 부른다.



⚙️ 2차 캐시 동작

1차 캐시와 뭐가 다르냐고 생각할 수 도 있지만 2차 캐시는 애플리케이션 범위의 캐시이므로 데이터베이스 조회가 1차 캐시만 사용할 때 보다 획기적으로 줄어든다.

1차 캐시에서 엔티티를 찾아보고 없으면 2차 캐시에서 엔티티를 찾는다.
찾는 엔티티가 존재하면 2차 캐시에서 반환하고 존재하지 않으면 DB를 조회해서 반환한다.

이때 2차 캐시는 동시성을 극대화하기 위해 캐시 한 객체를 직접 반환하지 않고 복사본을 만들어 반환한다.



⚙️ 복사본 사용을 통한 동시성 극대화

만약 캐시한 객체의 복사본을 반환하는 것이 아니라 원본을 그대로 반환하면 여러 곳에서 같은 객체를 동시에 수정하는 동시성 문제가 발생할 수 있다.

이 문제를 해결하기 위해 객체에 락(lock)을 걸어 두는 방식도 있지만 이는 동시성을 떨어뜨리는 문제가 있다.
이러한 락에 비하면 객체를 복사하는 비용은 아주 저렴하다.

그렇기 때문에 2차 캐시는 객체를 직접 반환하지 않고 복사본을 만들어 반환한다.

아직 2차 캐시를 직접 적용해보거나 의미있는 사용 경험을 해보지 못했기 때문에 자세한 내용은 이후의 포스팅에서 다루도록 하겠다.



📚 Reference

https://junghyungil.tistory.com/203

profile
하나씩 천천히 깊이있게 쌓아가는 백엔드 개발자 최승준입니다.

0개의 댓글