본문 바로가기
  • 실행력이 모든걸 결정한다
Spring 사전 준비/JPA Hibernate

[JPA] 2차 캐시

by 김코더 김주역 2022. 8. 30.
반응형

1. 캐시의 사용 이유

- 네크워크(외부 DB) 호출은 애플리케이션 서버의 내부 메모리에 접근하는 것보다 시간 비용이 훨씬 비싸기 때문에 캐시를 이용하는 것이 성능에 좋다.

 

 

 

2. 1차 캐시와 2차 캐시

1) 1차 캐시

- 1차 캐시는 영속성 컨텍스트 내부에 있는 캐시다.

- 일반적으로 트랜잭션과 수명이 같고, OSIV를 키더라도 요청이 끝날 때까지만 유효하다.

- 애플리케이션 전체로 보면 DB 접근 횟수를 획기적으로 줄이지는 못한다.

 

 

2) 2차 캐시

- 대부분의 JPA 구현체들이 지원하는 애플리케이션 범위의 캐시로, 공유 캐시라고도 한다.

- 애플리케이션을 종료할 때까지 캐시가 유지된다.

- 1차 캐시에 비해 DB 접근 횟수를 획기적으로 줄일 수 있기 때문에 성능을 더욱 더 향상시킬 수 있다.

 

동작 원리

- EntityManager를 통해 데이터를 조회할 때 우선 2차 캐시에서 찾고 없으면 DB를 조회한다. 2차 캐시는 동시성을 보장하기 위해 객체의 복사본을 만들어서 반환한다.

- 영속성 컨텍스트가 다르면 객체의 동일(==)성을 보장하지 않는다.

 

 

 

3. JPA 2차 캐시 표준 기능

- JPA 2.0에서 2차 캐시 표준을 정의했다. 더 세밀한 설정을 하려면 구현체에 의존적인 기능을 사용해야 한다. 여러 구현체가 공통으로 사용하는 2차 캐시 표준 기능을 알아보자.

 

1) 캐시 모드 설정

- javax.persistence.Cacheable 어노테이션을 사용한다.

@Cacheable // @Cacheable(true)와 동일
@Entity
public class Member {...}

- 캐시 모드는 javax.persistence.SharedCacheMode에 정의되어 있다.

  • ALL : 모든 엔티티를 캐시함
  • NONE : 캐시를 사용하지 않음
  • ENABLE_SELECTIVE : @Cacheable(true)로 설정된 엔티티만 캐시를 적용함 (일반적으로 사용됨)
  • DISABLE_SELECTIVE : @Cacheable(false)로 설정된 엔티티를 제외한 모든 엔티티에 캐시를 적용함
  • UNSPECIFIED : JPA 구현체가 정의한 설정을 따름

- 이제 애플리케이션 전체에 캐시를 어떻게 적용할지를 설정해야 한다. 다음과 같이 persistence.xml의 <persistence-unit>의 shared-cache-mode 속성에 지정할 수도 있고,

<persistence-unit name="hello">
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
</persistence-unit>

다음과 같이 엔티티매니저 팩토리의 shardCacheMode 속성에 지정할 수도 있다.

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    ...
    <property name="sharedCacheMode" value="ENABLE_SELECTIVE"/>
</bean>

 

 

2) 캐시 조회 및 저장 방식 설정

(1) 프로퍼티

- javax.persistence.cache.retrieveMode : 캐시 조회 모드 

- javax.persistence.cache.storeMode : 캐시 보관 모드

 

(2) 옵션

- javax.persistence.CacheRetrieveMode : 캐시 조회 모드의 설정 옵션

  • CacheRetrieveMode.USE (기본값) : 캐시에서 조회한다.
  • CacheRetrieveMode.BYPASS : 캐시를 무시하고 DB에서 직접 조회한다.

- javax.persistence.CacheStoreMode : 캐시 보관 모드의 설정 옵션

  • CacheStoreMode.USE (기본값) : 조회한 데이터를 캐시에 저장한다. 조회한 데이터가 이미 캐시에 있으면 캐시를 최신 상태로 갱신하지는 않는다. 트랜잭션을 커밋하면 등록, 수정한 엔티티를 캐시에 저장한다.
  • CacheStoreMode.BYPASS : 캐시에 저장하지 않는다.
  • CacheStoreMode.REFRESH : USE 전략에 추가로 DB에서 조회한 데이터를 최신 상태로 캐시한다.

 

(3) 설정 예시

- EntityManager.setProperty() 메소드에 설정

em.setProperty("javax.persistence.cache.storeMode", CacheStoreMode.BYPASS);

- EntityManager.find() 메소드에 설정

Map<String, Object> param = new HashMap<String, Object>();
param.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
param.put("javax.persistence.cache.storeMode", CacheStoreMode.BYPASS);
em.find(Member.class, id, param);

※ 문서에 나와있는 바와 같이 EntityManager.refresh() 메소드에 설정하는 방법도 있다.

- Query 또는 TypedQuery의 setHint() 메소드에 설정

em.createQuery("SELECT m FROM Member m WHERE m.id=:id", Member.class)
    .setParameter("id", id)
    .setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS)
    .setHint("javax.persistence.cache.storeMode", CacheStoreMode.BYPASS)
    .getSingleResult();

 

 

3) JPA 캐시 관리 API

(1) Cache 얻기

- JPA에서 제공하는 javax.persistence.Cache 인터페이스로 캐시를 관리할 수 있다. Cache는 EntityManagerFactory로부터 가져올 수 있다.

Cache cache = emf.getCache();

 

(2) Cache 관리 여부 조회

- Cache.contains() 메소드를 이용하여 특정 엔티티가 Cache에 저장되어 있는지 확인할 수 있다.

boolean contains = cache.contains(Member.class, member.getId());

 

(3) Cache에서 특정 엔티티 제거

- Cache.evict() 메소드를 이용하여 특정 엔티티 또는 특정 타입을 가진 모든 엔티티들을 Cache에서 제거할 수 있다.

cache.evict(Member.class, member.getId()); // Member 타입의 특정 엔티티를 캐시에서 제거
cache.evict(Member.class); // Member 타입인 모든 엔티티들을 캐시에서 제거

 

(4) 모든 Cache 데이터 제거

cache.evictAll();

 

그 외의 다양한 API 사용 예시들은 https://www.javatips.net/api/javax.persistence.cache를 참고하자.

 

 

 

4. Hibernate가 지원하는 캐시

  • 엔티티 캐시
  • 컬렉션 캐시
  • 쿼리 캐시

※ 컬렉션 캐시와 쿼리 캐시는 엔티티의 식별자 값만 캐시한다. 따라서, 컬렉션 캐시와 쿼리 캐시를 사용할 것이라면 결과 대상 엔티티에 엔티티 캐시를 적용해야 추가적인 조회 쿼리 호출로 인한 심각한 성능 저하를 막을 수 있다.

 

 

 

+ 보충) Hibernate에 EHcache 적용하기

- EHCache는 Java 기반 오픈소스 캐시 라이브러리다. 참고가 될만한 자료들을 첨부하겠다.

 

EHcache 공식 문서

https://www.ehcache.org/documentation/

 

Documentation

 

www.ehcache.org

 

EHcache 적용 예시

https://velog.io/@dev_osj/zotl

 

EHCache (1. 선택 및 특징)

현재 회사에서 EHCache를 적용한 경험이 있어서 관련해서 포스팅을 하려고 합니다.현재 저는 기존에 운영하던 API를 신규 개발을 하였습니다.우선 제가 맡고 있는 API와 아키텍쳐에 대해서 간단히

velog.io

 

 

● 참고자료 : 자바 ORM 표준 JPA 프로그래밍

 

반응형

댓글