JPA : 2차 캐시

    이 글은 자바 표준 ORM JPA 프로그래밍 책을 보고 정리한 글입니다.


    2차 캐시의 필요성

    네트워크를 통해 DB에 접근하는 시간 비용은 어플리케이션의 내부 메모리에 접근하는 비용에 비해 수만 ~ 수십만배 이상 비싸다. 따라서 필요한 데이터를 매번 DB에서 조회하는 것보다는 어플리케이션 메모리에 캐시 후, DB 접근 횟수를 줄이면 어플리케이션의 성능을 획기적으로 개선할 수 있다고 한다. 

     

     


    JPA의 영속성 컨텍스트

    영속성 컨텍스트 내부에는 엔티티를 보관하는 1차 캐시가 있다. 그렇지만 이 1차 캐시는 영속성 컨텍스트가 존재하는 동안에만 캐시로 사용할 수 있다. 스프링의 기본적인 영속성 컨텍스트 전략은 트랜잭션이 시작할 때 영속성 컨텍스트를 만들고, 트랜잭션이 종료되면서 영속성 컨텍스트를 종료한다. OSIV를 사용하면 필터로 요청이 들어오고 나갈 때까지 영속성 컨텍스트가 유지된다.

    그렇지만 위의 1차 캐시 사용 방법 모두 캐싱 관점에서 DB 접근 횟수를 줄이는 역할을 크게 많이 하지는 않는다. 예를 들어 메인 화면을 띄우는데 항상 똑같은 데이터가 올라온다고 해보자. 이 때 1차 캐시를 사용하면 항상 요청마다 DB에 접근해야한다. 

     

    위의 문제점을 개선하기 위해서 어플리케이션 단위의 캐시를 도입해야한다. JPA는 어플리케이션 범위의 캐시를 지원하는데 이를 2차 캐시라고 한다. 

     


    1차 캐시, 2차 캐시의 동작 방식 차이

    1차 캐시

    1차 캐시의 동작 방식은 다음과 같다.

    1. 최초 조회할 때는 영속성 컨텍스트에 엔티티가 없다.
    2. DB에 엔티티를 조회한다.
    3. DB에서 받은 엔티티를 영속성 컨텍스트의 1차 캐시에 보관한다.
    4. 1차 캐시에 보관한 결과를 반환한다.
    5. 동일한 엔티티를 조회하면 1차 캐시에 있는지 확인한 후, 없으면 DB에 조회해서 반환한다. 있으면 바로 반환한다. 

     

    1차 캐시의 특징은 다음과 같다.  

    1. 동일한 영속성 컨텍스트에는 객체 동일성(a == b)을 보장한다 
    2. 1차 캐시는 영속성 컨텍스트 범위의 캐시다. 

     

    2차 캐시 조회

     

    2차 캐시의 동작 방식은 다음과 같다.

    1. 영속성 컨텍스트는 엔티티가 필요하면 2차 캐시를 조회함
    2. 2차 캐시에 엔티티가 없으면 DB를 조회해서 결과를 2차 캐쉬에 보관한다.
    3. 2차 캐시에 엔티티가 있으면, 2차 캐시는 자신이 가지고 있는 엔티티를 복사해서 반환한다.

     

    2차 캐시는 동시성을 극대화하기 위해 자신이 가지고 있는 엔티티를 복사해서 반환한다. 만약 캐시한 객체를 그대로 반환하면 멀티 쓰레드 환경에서 동시성 이슈가 발생할 수 있다. 이를 해결하기 위해 Lock을 걸 수 있는데, Lock을 사용해서 해결하는 것보다 객체를 복사해서 반환하는 것의 비용이 더 저렴하다고 한다. 

    2차 캐쉬의 특징은 다음과 같다. 

    1. 2차 캐시는 요청을 받으면, 가지고 있는 객체를 복사해서 반환한다.
    2. 2차 캐시는 PK를 기준으로 캐시하지만, 객체를 복사해서 반환하기 때문에 영속성 컨텍스트가 다르면 객체 동일성을 보장하지 않는다.
    3. 2차 캐시는 어플리케이션 범위의 캐시로, 어플리케이션이 종료되는 시점까지 유효하다. 

     


    JPA의 2차 캐시 실무 적용은?

    JPA의 2차 캐시는 실무에 적용하지 않는다고 한다. JPA의 2차 캐시는 설정하는 과정이 복잡하고(책을 봤는데 복잡하다), 지원하는 캐시 라이브러리의 범위도 작다고 한다. 가장 큰 단점은 JPA의 2차 캐시는 엔티티 수준만 캐시가 된다는 점이다. 실무에서는 API 통신을 하기 때문에 주로 DTO 단위로 캐싱을 해야하는데, JPA의 2차 캐시는 그렇지 못하다고 한다. 

    따라서 실제로 캐시를 사용하기 위해서는 JPA의 2차 캐시가 아닌 스프링이 제공하는 2차 캐시를 활용하는 것이 권장된다고 한다. 이 내용은 이 답변을 참고했다 (https://www.inflearn.com/questions/33629)

     

    'Spring > JPA' 카테고리의 다른 글

    JPA : Bulk 연산의 주의할 점  (0) 2022.02.23
    JPA : Collection과 JPA 동작 방식  (1) 2022.02.23
    JPA : 트랜잭션 격리 수준과 JPA의 락  (0) 2022.02.23
    JPA : Batch 처리하기  (0) 2022.02.21
    JPA : N+1 문제 및 해결방법 정리  (0) 2022.02.21

    댓글

    Designed by JB FACTORY