studybook
  • Introduction
  • 실무 하며 깨닫는 부분 정리
    • 옵션에 대해서
    • 코드 작성의 순서
    • 자바 프로그램에 문제가 생겼다면
    • 장애 대처법
  • Logstash, Beats 정리
  • Zookeeper 정리
  • Message Queue 정리
    • RabbitMQ 삽질
  • Java 관련 정리
    • Java Primitive Wrapper class
    • Java NIO
    • Java8 Double colon operator
    • Effective Java
      • 4장
      • 5장
      • 6장 - Enum, Annotation
      • 7장 - Method
      • 8장 - 프로그래밍 일반
      • 9장 - Exception
    • Java8 Lambda expression
    • JDBC
    • Linux에서 WatchService 이상동작
  • Spring 관련 정리
    • Spring Bean init, destroy 순서
    • Spring Async Controller
    • Spring Executable jar 웹 개발 및 배포
    • Spring Boot Font 배포 에러
    • Spring AOP
      • Spring AOP로 모든 Request 로그 남기기
    • Spring Cache
    • Spring Cloud
      • Consul로 spring 설정 관리하기
    • Spring Test
      • Spring Test DirtiesContext
      • Spring Test MockBean, SpyBean
      • Spring Test Dynamic @Scheduled
    • Spring JDBC
    • Spring Validation
    • Spring Transaction Management
      • Spring with JTA 삽질
    • Spring에서 효율적으로 Static resource 관리하기
    • Zuul을 사용해서 Spring Reverse proxy 만들기
    • Spring Security
    • 스프링 어노테이션이 안 먹힐 때 의심해볼만한 것
    • Spring Data
    • Spring Webflux
      • Tobi 강연
  • 코드 리팩토링
    • 한번에 하나씩
  • 지속적 통합 (CI)
    • Jenkins pipeline 삽질기
  • Log Aggregator 정리
    • Flume 테스트
    • Fluentd 테스트
  • Web Socket 정리
  • Akka
    • Actor 모델
    • Supervision
  • IE 8 대응 정리
  • 함수형 프로그래밍
    • 모나드
  • Netty
    • Netty 기본 예제
    • Netty 주요 특징
    • Netty 부트스트랩
    • Netty 채널 파이프라인, 코덱
    • Netty 이벤트 모델
    • Netty 바이트 버퍼
  • 스칼라 관련 정리
    • Maven으로 컴파일하기
    • Scala def 괄호 여부의 차이
    • 스칼라 function, method 차이점
    • ScalaTest와 Spring 연동하기
    • Programming in Scala
  • J2S 컨퍼런스
  • Android
    • 테스트
    • NDK
  • DDOS
  • HTTP
  • HttpClient
  • Container
    • Image 개요
    • cri-o
    • kata containers
    • Open Container Initiative Image
    • Buildkit
  • Github pages
  • Static Website
  • Webhook
  • Service Discovery Tools
    • Etcd
    • Eureka
    • Consul
      • ACL
    • 비교
  • React
    • JSX
    • React Element
    • Components, Props
    • State, Lifecycle
    • Handling Event
    • Flux
  • Vagrant
    • SSH 접속
  • Linux
    • Systemd
    • Alternatives
  • Messaging protocols
    • XMPP
    • AMQP
  • Windows
    • Windows10 내장 우분투에 ssh 클라이언트로 접속하기
    • Windows10 Hyper-V와 Virtual Box가 충돌을 일으켰을 때
    • Hyper-V 기반 docker에서 Shared Drives 설정 실패할 때
    • 윈도우 개발환경 설정
    • Docker desktop 없이 docker 환경 세팅하기
    • UWP 앱을 항상 관리자권한으로 실행하는 바로가기 만들기
  • Spring camp 2017
    • Project Reactive
    • 이벤트 소싱
    • CQRS
  • Spring webflux
  • 리액티브 프로그래밍
  • Linux Settings
    • 홈서버 백업 및 복구기
    • 홈서버 트러블슈팅
  • Kubernetes
    • k3s 설치 및 삽질
    • pod resources
    • Argo workflow
    • 트러블 슈팅
      • Kubernetes namespace의 phase가 Terminating에서 멈춰있을 때
    • 쿠버네티스 마스터
    • Knative
    • Knative Pipeline
    • Aggrerated API server
    • Accessing the API
      • Authenticating
  • Sonarqube
  • HTTP/2
  • Go
    • Go Module
    • Go dependency injection
    • Go Error handling
    • Go in Action
      • 3장 패키지
      • 4장 배열, 슬라이스, 맵
      • 5장 GO의 타입 시스템
      • 6장 동시성
      • 7장 동시성 패턴
      • 8장 표준 라이브러리
      • 9장 테스트와 벤치마킹
    • Go Channel 사용법
  • Cloud Native
Powered by GitBook
On this page
  • Cache Abstraction
  • Cache vs Buffer
  • Annotation
  • @Cacheable
  • @CacheEvict
  • @CachePut
  • @Cacheing
  • @CacheConfig
  • 설정
  • Dependency 추가
  • 활성화
  • 캐시 스토리지 설정
  • 테스트
  1. Spring 관련 정리

Spring Cache

PreviousSpring AOP로 모든 Request 로그 남기기NextSpring Cloud

Last updated 7 years ago

  • 스프링 3.1버전 이후부터 지원

  • 스프링 4.1 버전부터 에 맞춰서 기능이 개선됨

Cache Abstraction

  • 자바 메소드에 캐싱 적용

    • 메소드를 실행하기 전에 캐시를 먼저 거치게 하여 메소드의 실행 횟수를 줄여줌

    • 주어진 argument를 기준으로 판단

      • 따라서 같은 input이 주어지면 언제나 같은 output이 나와야함

  • 캐시를 지우거나 수정할 수 있는 기능 제공

  • 추상체기 때문에 실제 캐시 저장소 구현체중 하나를 선택하여 사용해야 함

    • org.springframework.cache.Cache, org.springframework.cache.CacheManager 인터페이스를 사용해서 접근

  • 멀티 쓰레드, 멀티 프로세스 관련 처리는 캐시 구현체에서 처리해야 됨

    • 특히 멀티 프로세스의 경우 여러 노드에서 같은 데이터를 가질 수 있도록 처리해야 됨

Cache vs Buffer

  • Cache와 Buffer은 서로 바꿔 쓸 수 있는 단어

  • Buffer는 전통적으로 연산 속도가 서로 다른 객체 사이에 임시로 데이터를 저장하는 저장소 지칭

    • 연산 속도가 빠른 쪽이 불필요하게 대기하지 않도록 도와 성능 향상에 도움을 줌

    • 작은 데이터 조각들을 모아서 한번에 움직일 수 있게 도와줌

    • 적어도 한 객체는 버퍼의 존재를 알아야함

  • Cache는 보이지 않고 또한 두 객체 모두 그 존재를 알 필요가 없음

    • 같은 데이터를 여러 번 읽으려고 할 때 상대적으로 빠른 방법(느린 네트워크 요청 대신에 로컬 메모리에 저장된 것을 바로 돌려주는 등)을 제공하여 성능 향상에 도움을 줌

Annotation

@Cacheable

  • 메소드의 결과 값이 캐싱되고, 존재하는 키 요청은 캐시에서 찾아 반환하도록 만드는 어노테이션

    • 이 어노테이션이 붙어있는 메소드는 결과가 캐시에 저장됨

  • 캐시 이름은 여러 개를 동시에 입력할 수 있음

    • 최소한 하나 이상 hit가 있으면 캐시 값 반환

키 생성

기본 키 생성

  • KeyGenerator 사용

    • 패러미터가 없을 땐 SimpleKey.EMPTY

    • 패러미터가 한 개 있을 땐 패러미터 인스턴스 사용

    • 패러미터가 여러 개 있을 땐 모든 패러미터를 담은 SimpleKey 사용

  • 패러미터 객체에 적절한 hashCode(), equals() 구현이 있다면 수정할 필요 없음

  • 기본 키 생성 방식을 바꾸고 싶으면 org.springframework.cache.interceptor.KeyGenerator 인터페이스를 구현

  • 스프링 4.0 이전 버전에서는 org.springframework.cache.interceptor.DefaultKeyGenerator 사용

    • 여러 패러미터를 가진 키를 생성할 때 hashCode()만 사용하여 예기치 않은 키 충돌을 일으킴

    • 4.0 이후로는 SimpleKeyGenerator 사용

커스텀 키 생성

  • 메소드의 모든 패러미터를 써서 캐시 키를 만들기엔 적절하지 않을 때 사용

    • 일부만 캐시 키로 쓰고, 나머지는 메소드 내부 로직에만 사용하는 경우

  • SpEL을 사용해서 특정 패러미터, 혹은 그 패러미터의 프로퍼티를 지정

  • 코드 베이스가 확장됨에 따라 메소드의 패러미터도 복잡해지기 때문에 추천되는 방법

    • 기본 키 생성 전략이 모든 메소드에 적용되는 일은 드뭄

  • ex)

@Cacheable(cacheNames="testCache", key="#param")
public Object test(Object param, Object param2)
  • 정말 특별한 키 생성 알고리즘을 쓰거나 샤딩이 필요하면 keyGenerator에 별도의 bean 정의

    • key, keyGenerator 두개는 동시에 적용할 수 없음

캐시 탐색

기본 캐시 탐색

  • CacheResolver 에서 CacheManager 의 설정을 보고 캐시 탐색

    • 마찬가지로 기본 CacheResolver을 바꾸고 싶으면 org.springframework.cache.interceptor.CacheResolver 구현

커스텀 캐시 탐색

  • cacheManager 에 별도의 CacheManager bean을 정의하거나 아예 cacheResolver 에 CacheResolver bean을 정의해서 갈아끼워도 됨

    • 둘 중 하나만 선택

캐싱 동기화

  • 캐시 구현체가 thread safe 하지 않을 때, 자체적으로 캐시 접근에 동기화를 거는 방법

    • @Cacheable(..., sync="/* true or false */")

조건부 캐싱

  • 특별한 조건을 만족할 때만 캐싱하도록 제약을 거는 방법

condition

    • condition 패러미터에 SpEL 방식으로 작성

  • 연산 결과가 true일 때 캐싱

  • false일 땐 캐싱되지 않았을 때와 동일하게 동작

  • 현재 캐시 상태, 패러미터와 상관없이 항상 실행됨

  • ex) condition="#name.length < 32"

unless

    • unless 패러미터에 SpEL 방식으로 작성

  • 연산 결과가 false일 때 캐싱

  • condition 이랑 달리 메소드가 호출된 이후에 연산

  • 메소드 결과를 #result로 참고

  • java.util.Optional을 쓸 때도 #result는 Optional 래퍼 객체가 아니라 담고 있는 객체

@CacheEvict

  • 메소드가 호출될 때 캐시에 저장되어있는 데이터가 삭제되도록 만드는 어노테이션

  • 여러 개의 캐시 이름을 동시에 등록 가능

  • @Cacheable 에 있는 여러 설정 사용 가능

  • allEntries=/* true or false */ 옵션을 통해 한번에 모든 캐시 값을 지울 것인가 키에 해당하는 캐시만 지울 것인가 선택 가능

  • beforeInvocation=/* true or false */ 옵션을 통해 메소드가 실행되기 전에 날릴 것인가 실행 완료 이후에 날릴 것인가 선택 가능

    • 메소드 실행 도중 Exception 등 에러가 발생해서 실패했을 때 유용

  • void 리턴 메소드 사용 가능

    • 이 경우 Eviction trigger로 사용

@CachePut

  • 메소드 호출 완료 후 그 결과 값을 바탕으로 캐시 데이터를 수정하게 만드는 어노테이션

  • @Cacheable 에 있는 여러 설정 사용 가능

  • 언제나 메소드가 실행된 이후 캐시에 저장

  • @Cacheable과 같이 사용하지 말 것

    • 메소드 실행을 스킵하여 업데이트가 일어나지 않게 됨

@Cacheing

  • 조건이나 key가 다른 여러 어노테이션들을 한 메소드에 동시 적용하기 위해 사용하는 어노테이션

    • @Cacheable, @CachePut, @CacheEvict 중첩 사용 가능

@Caching(evict = { @CacheEvict("cache1"), @CacheEvict(cacheNames="cache2", key="#param1") })
public Object testFunc(String param, String param1)

@CacheConfig

  • 모든 메소드에서 공통되는 옵션을 설정하게 도와주는 클래스 레벨 어노테이션

    • 캐시 이름, KeyGenerator, CacheManager, CacheResolver 등 설정 가능

설정

Dependency 추가

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

활성화

  • @Configuration 중 하나에 @EnableCaching 추가

@Configuration
@EnableCaching
public class AppConfig {
}

캐시 스토리지 설정

  • 스프링 자체적으로 지원하는 캐시들은 해당하는 CacheManager 구현체를 bean 등록

  • 그 외에는 CacheManager, Cache 직접 구현 필요

    • AbstractCacheManager 와 같은 추상 클래스들을 사용하여 보일러플레이트 줄이기 가능

JDK ConcurrentMap

  • cacheManager: org.springframework.cache.support.SimpleCacheManager

Ehcache

  • cacheManager: org.springframework.cache.ehcache.EhCacheCacheManager

  • ehcache: org.springframework.cache.ehcache.EhCacheManagerFactoryBean

Caffeine

  • cacheManager: org.springframework.cache.caffeine.CaffeineCacheManager

Guava

  • cacheManager: org.springframework.cache.guava.GuavaCacheManager

GemFire

JSR-107

  • cacheManager: org.springframework.cache.jcache.JCacheCacheManager

테스트

  • 테스트를 위해 캐시 어노테이션을 일일히 지우는 대신 더미 캐시 사용 가능

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

@TestConfiguration
public class TestConfig {
  @Autowired
  private CacheManager jdkCache; // 예시

  @Autowired
  private CacheManager guavaCache; // 예시

  @Bean
  @Primary
  public CacheManager cacheManager() {
    CompositeCacheManager manager = new CompositeCacheManager(jdkCache, guavaCache);

    // CompositeCacheManager에 포함된 CacheManager 외
    // 모든 캐시 요청을 NoOpCache로 보냄 (여기에선 jdkCache, guavaCache 외의 모든 캐시)
    // NoOpCache는 캐시가 없는 것과 동일하게 동작
    manager.setFallbackToNoOpCache(true);

    return manager;
  }
}

JCache Annotations
http://docs.spring.io/spring-gemfire/docs/current/reference/html/