데이터베이스나 외부 시스템에 자주 접근해야 하는 데이터를 임시로 저장하는 메모리 공간
효과
종류
영속성 컨텍스트란, JPA의 생명주기를 관리하는 저장소
1차 캐시 이란, 영속성 컨텍스트 내부에 존재하는 엔티티 보관 저장소
엔티티 매니저로 조회하거나 변경하는 모든 엔티티는 1차 캐시에 저장
→ 트랜잭션을 커밋 or 플러시 호출 시 1차 캐시에 있는 엔티티의 변경 내역을 데이터베이스에 동기화
→ 트랜잭션을 시작하고 종료할 때까지만 1차 캐시 유효
쿼리 실행 전 캐시 확인:
클라이언트가 쿼리를 실행할 때, 데이터베이스는 먼저 JPQ 1차 캐시에서 해당 쿼리 결과가 이미 저장되어 있는지 확인
캐시 적중 시 응답 반환:
쿼리 결과가 캐시에 저장되어 있는 경우, 데이터베이스는 즉시 캐시된 결과를 클라이언트에게 반환
캐시 미스 시 데이터베이스 쿼리 실행:
쿼리 결과가 캐시에 없는 경우, 데이터베이스는 실제로 쿼리를 실행
캐시 업데이트:
쿼리 결과를 얻은 후, 데이터베이스는 해당 결과를 JPQ 1차 캐시에 저장
void cache() {
EntityManager em = entityManager.getEntityManagerFactory().createEntityManager();
em.getTransaction().begin();
Member member1 = em.find(Member.class, 1L);
Member member2 = em.find(Member.class, 1L);
System.out.println(member1 == member2);
em.getTransaction().commit();
em.close();
}

em.find(Member.class, 1L) 호출이 두 번 이루어짐 → 이미지 상 데이터베이스로 쿼리 실행2차 캐시 는, 애플리케이션이 공유하는 캐시 → 애플리케이션 범위의 캐시
2차 캐시는 애플리케이션을 종료할 때까지 캐시가 유지
1차 캐시 확인:
클라이언트가 쿼리를 요청하면, 데이터베이스 시스템은 먼저 1차 캐시를 확인
1차 캐시에 쿼리 결과가 있으면, 즉시 반환
2차 캐시 확인:
1차 캐시에 결과가 없으면, 데이터베이스 시스템은 2차 캐시를 확인
2차 캐시에 쿼리 결과가 있으면, 결과 반환 (객체가 아닌 복사본 반환)
해당 결과를 1차 캐시에 저장
캐시 미스 시 데이터베이스 쿼리 실행:
1차 캐시, 2차 캐시 모두 데이터가 없을 경우, 쿼리를 실행하여 결과 얻기
2차 캐시 및 1차 캐시 업데이트:
쿼리 결과를 얻은 후, 결과를 1차, 2차 캐시에 모두 저장
2차 캐시는 동시성을 극대화하기 위해 캐시 한 객체를 직접 반환하지 않고 복사본을 만들어서 반환
→ 캐시한 객체를 그대로 반환 시, 여러 곳에서 같은 객체를 동시에 수정한 문제가 발생할 수 있음
→ 락을 걸면 동시성의 저하를 일으킴 → 따라서 복사본을 반환하여 동시에 수정
캐시를 사용할 entity 클래스 위에 @Cacheable 어노테이션 작성
@Cacheable // 기본 값 true. false로 지정하면 2차 캐시 x
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
..
}
application.properties (application.xml) 에서 설정
// 2차 캐시 활성화
spring.jpa.properties.hibernate.cache.use_second_level_cache = true
// 2차 캐시 처리할 클래스 지정
spring.jpa.properties.hibernate.cache.region.factory_class
// 하이버네이트로 캐시 적용 여부 확인 출력
spring.jpa.properties.hibernate.generate_statistics = true
// 캐시 모드 설정
spring.jpa.properties.javax.persistence.sharedCache.mode= (기본값) Enable_selective
캐시 모드 설정
spring.jpa.properties.javax.persistence.sharedCache.mode= ?
@Cache에서 캐시 동시성 전략 설정
Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
public class Academy {
@Id
@GeneratedValue
private Long id;
private String name;
...
CacheConcurrencyStrategy.?
| 1차 캐시 | 2차 캐시 | |
|---|---|---|
| 범위 | 인스턴스 범위 | 애플리케이션 범위 |
| 유효 범위 | 트랜잭션 동안만 유효 | 애플리케이션이 실행되는 동안 유효 |
| 동작 방식 | 엔티티를 영속성 컨텍스트 내부에 캐싱 | |
| → 동일한 엔티티 매니저 내에서 동일한 엔티티를 조회할 때 동작 | 엔티티를 영속성 컨텍스트 외부에 캐싱 | |
| → 여러 트랜잭션 및 여러 엔티티 매니저 인스턴스에서 공유 |
참고자료