티스토리 뷰
캐시와 Jpa
네트워크를 통해 데이터베이스 접근하는 시간 비용은 애플리케이션 서버 내부에서 메모리에 접근하는 시간 비용보다 수만~수십만 배 이상 비싸다. 따라서 조회한 데이터를 메모리에 캐시하여 데이터베이스 접근 횟수를 줄이면 성능을 획기적으로 개선할 수 있다.
Jpa에서 캐시를 제공하는 방법으로 1차 캐시와 2차 캐시가 있다.
Jpa 1차 캐시

@Transaction으로 DB 트랜잭션을 사용하는 경우, 대상 엔티티는 영속성 컨텍스트에 포함된다. 영속성 컨텍스트 내부에는 엔티티를 보관하는 저장소가 있다. 이를 1차 캐시라고 한다.
데이터베이스 기본 키로 기준으로 캐시되어 있는지 확인한다. 트랜잭션을 커밋하거나 플러시를 호출하면 1차 캐시에 있는 엔티티의 변경 내역을 데이터베이스에 반영(동기화)한다. (= Dirty Check)
영속성 컨텍스트는 동일 트랜잭션 내에서만 적용되므로, 트랜잭션을 시작하고 종료할 때까지만 1차 캐시가 유효하다. 트랜잭션을 넘나들어 1차 캐시를 사용할 수는 없다. 일반적으로 트랜잭션을 시작할 때 영속성 컨텍스트도 시작하고, 트랜잭션을 종료할 때 영속성 컨텍스트도 종료한다.
Jpa 2차 캐시

애플리케이션단에서 공유하는 캐시, 공유 캐시(Shared Cache)라고도 한다.
애플리케이션을 종료할 때까지 유지된다. 트랜잭션을 넘나들어 캐시된 값를 사용할 수 있다. 2차 캐시는 완전히 동일한 쿼리를 호출하여 동일한 엔티티를 조회하는 경우 적용된다. 만약 쿼리 조건이 달라진다면 2차 캐시를 활용할 수 없다. (캐시 미스 발생)
2차 캐시의 동작 방식은 다음과 같다.
1. 엔티티가 필요하면 1차 캐시(영속성 컨텍스트에 보관)를 조회한다.
2. 1차 캐시에 데이터가 없다면 2차 캐시를 조회한다.
3. 2차 캐시에 없다면 데이터베이스를 조회한다.
4. 데이터베이스 조회 결과를 2차 캐시에 보관한다.
5. 2차 캐시는 자신이 보관하고 있는 엔티티를 복사해서 반환한다. (데이터베이스 기본 키를 기준으로 캐시한다.)
2차 캐시는 동시성을 극대화하기 위해 캐시한 객체를 직접 반환하지 않고 복사본을 만들어서 반환한다. 캐시한 객체를 그대로 반환하면 여러 곳에서 객체를 동시에 수정하면 동시성 문제가 발생할 수 있다. Lock을 걸면 동시성을 보장할 수 있지만 비용이 비싸다. Lock에 비해 객체를 복사하는 비용은 아주 저렴하다. 따라서 복사본을 만들어 반환한다. 이러한 특징으로 영속성 컨텍스트가 다르면 객체 동일성 (a == b)을 보장할 수 없다.
2차 캐시로 데이터베이스 조회 횟수를 획기적으로 줄일 수 있다.
분산 캐시 (Redis 캐시)
서버 인스턴스간 공유하는 캐시, 애플리케이션 범위를 넘나들어 값을 캐시하고 사용할 수 있다.


참고한 곳
- https://velog.io/@bagt/JPA-2%EC%B0%A8-%EC%BA%90%EC%8B%9C%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC
- https://hoestory.tistory.com/69
- https://junghyungil.tistory.com/203