[JPA] 캐싱(Caching)과 영속성(persistence)

현주·2023년 2월 9일
1

✏️ 캐시 (Cache)

  • 동일한 데이터에 반복해서 접근해야 하거나 많은 연산이 필요한 일일 때,
    결과를 빠르게 이용하고자 성능이 좋은 / 가까운 곳에 저장하는 것

  • 서버의 부담을 줄이성능을 높이기 위해 사용되는 기술

✔️ 캐시를 사용하기 좋은 경우

  • 반복적으로 동일한 결과를 반환하는 경우
  • DB에 접근하는 시간이 오래 걸리는 경우

✔️ 캐시를 사용하지 않아야 할 경우

  • 실시간으로 정확성을 요구하는 경우
  • 빈번한 데이터의 변경이 일어나는 경우

✏️ 캐싱 (Caching)

  • 캐시 영역으로부터 데이터를 가져와서 접근하는 방식

  • 네트워크를 통해 DB에 접근하는 시간 비용은 애플리케이션 내부 메모리에 접근하는 비용에 비해 훨씬 비쌈

    ➜ 필요한 데이터를 매번 DB에서 조회하지 않고,
    조회한 데이터를 메모리에 캐싱해두면 DB 접근 횟수를 줄여 애플리케이션의 성능 개선이 가능

Ex. JPA의 Repository에서 findBy~ 메서드로 동일한 데이터를 여러번 조회할 경우,
쿼리의 SELECT문이 5번 모두 실행되는 것이 아닌 1번만 실행됨
(연관관계가 없다고 가정할 경우임)

영속성(Persistance) 때문 !
( 첫번째 SELECT한 결과를 JPA의 1차 캐시에 보관하고 계속 재사용하기 때문 )

✔️ 영속성(Persistance)

  • 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성
    ( 저장하여 지속적으로 사용 )

💬 Q ) Update가 발생하면 데이터가 갱신되는데, 캐시에서 꺼내오면 갱신 이전의 데이터만 꺼내오는 것 아닐까?

👉 영속성 컨텍스트 내부에 있는 엔티티의 변화가 즉시 1차 캐시에 저장되기 때문에 갱신된 데이터를 받을 수 있음 !


✏️ 1차 캐시 (1L cache)

  • Hibernate가 기본적으로 제공하는 캐시

  • Transaction 범위 내에서 동작
    ➜ 동일한 트랜잭션 내에서만 1차 캐시가 존재

  • 영속성 컨텍스트 내부에 존재
    ➜ 영속성 컨텍스트의 생명주기와 동일 ➜ 트랜잭션이 종료되면 1차 캐시도 종료
    ➜ OSIV를 사용하더라도 사용자의 요청이 들어올 때부터 끝날 때까지만 1차 캐시가 유효함

    ✔️ OSIV (Open Session In View)

    • 영속성 컨텍스트를 뷰까지 열어두는 기능
      ➜ 영속성 컨텍스트를 열어두면 엔티티도 영속성 상태로 유지됨
    • 뷰까지 영속성 컨텍스트가 살아있다면 뷰에서도 지연로딩 사용 가능

      OSIV 참고
  • 객체의 동일성 보장
    Ex. 객체 1 == 객체 2

  • 애플리케이션 전체로 봐서는 DB 접근 횟수를 줄이지는 못함


✏️ 2차 캐시 (2L cache, Second level cache)

  • Application 범위 내에서 동작
    애플리케이션을 종료할 때까지 캐시가 유지됨
    ( 분산 캐시 / 클러스터링 환경의 캐시는 애플리케이션 범위보다 더 오래 유지될 수도 있음 )

  • 동시성을 극대화 하기 위해 캐시한 객체를 직접 반환하지 않고 복사본을 만들어 반환함

    ❗ 여기서 캐시한 객체를 그대로 반환하게 되면, 동시성 문제 발생 가능 !

    ➜ 이를 해결하기 위해 객체에 락을 걸으면 동시성이 떨어질 수 있음

  • 영속성 컨텍스트가 다르면 객체 동일성을 보장하지 않음

  • 적절히 활용하여 DB 접근 횟수 줄이기 가능
    ➜ ⭐ 애플리케이션 성능 개선 가능 !

✔️ 동시성 문제

  • 여러 스레드가 동시에 같은 인스턴스의 필드 값을 변경하면서 발생하는 문제
  • 값에 대해 변경이 일어나야만 발생
    ( 값을 읽기만 해서는 발생 X )

✏️ 캐싱 동작 방식

( 위 그림은 2차 캐시의 동작 방식을 나타낸 그림입니다. )

1. 최초 조회시

  • 엔티티가 없으므로 DB에서 가져와서 반환
  • DB에서 조회해 온 데이터를 영속성 컨텍스트 내부 저장소(1차 캐시)에 보관

1. 1차 캐시에 객체가 있는 경우

  • 1차 캐시에서 반환

2. 1차 캐시에는 없지만 2차 캐시에는 객체가 존재하는 경우

  • 2차 캐시에서 반환

🚩 참고하면 도움이 될만한 글

0개의 댓글