본문 바로가기
Spring&Spring Boot

(Spring/Redis/@Cacheable) Spring Cacheable로 캐싱기능 적용

by Developer RyanKim 2020. 3. 21.

Spring Redis @Cacheable Spring Cacheable

쿠팡 메인페이지의 상품섹션 일부입니다.

유저 만족도에 중요한 응답속도를 높히기 위해 여러 영역에 여러방법으로 캐시가 적용되어 있을 것으로 예상해봅니다.


Spring 환경에서는 캐시적용에 Spring에서 제공하는 @Cacheable 인터페이스를 사용할 수 있습니다.

    @Override
    @Cacheable(value = "example", keyGenerator = "customKeyGenerator", cacheManager = "cacheManager")
    public List<Goods> example(Param p1, Praram p2)
            ...
    }

: 위 설정으로 특정 메소드, 파라메터 기반으로 캐시를 생성합니다. ex) 상품목록


파라메터를 기반으로 캐시 key를 생성하는 클래스 구현

public class CustomKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object target, Method method, Object... params) {
        return target.getClass().getSimpleName() + "_" + method.getName() + "_" + StringUtils
                .arrayToDelimitedString(params,"_");
    }
}

: 키 생성에 타깃 오브젝트 이름, 메소드이름, 파라메터가 사용됩니다.
따라서 같은 메소드라도 파라메터가 다르면 캐싱이 따로 적용되도록 합니다.

이 부분이 중요한 이유가 있습니다. 예를 들어 한국지역에서 처음 조회가 되어 캐싱이 되어있다고 가정하고
그다음 다른 유저가 지역을 미국에서 들어와서 모두 영어 번역본으로 데이터가 제공되어야 한다고 할 때,
locale이 다른 값으로 들어올 것입니다. 하지만 파라메터 기반으로 키가 만들어지지 않고 메소드명만 사용한다면
key가 같으니 캐시 hit로 판단하여 이전에 캐싱된 한국어로 된 데이터들이 보이게 되겠죠!


저도 개발시 캐시를 적용하고 난 후, 평균 응답속도가 매우 빨라짐을 느낄수 있었습니다. (캐시 적용 전 3~4초 -> 적용 후 0.5초 미만) 

서버 및 DB 간 통신 과정, 로직수행시간 등이 생략되어 속도가 향상 되었습니다.

하지만!

 

캐시를 적용할 때 고려할 사항이 몇가지 있습니다.
1. 캐시 히트율이 적으면 오히려 더 성능이 나쁠 수있음
 : 캐시를 확인하고, 저장하는 과정이 더 추가되기 때문에 캐시 히트가 되지 않았을 때는 적용되지 않은 것보다 더 비용이 많이 듭니다.

2. 동기화 문제 발생 가능
: 캐시가 만료되지 않았을 경우 캐시에서 응답은 기존 데이터로 계속 응답하게 됩니다.
만약 상품 1에 캐시가 적용되어 있다고 가정하였을 때, 상품 1의 가격이 바뀌어도 
조회했을 때 캐시가 남아있으면 기존 가격으로 보이게 될것입니다.


트래픽 저하시 대처

 

페이지에 접속자가 많이 없다면 캐시 히트율이 급격하게 떨어져 페이지 응답속도가 느려질 것입니다.
따라서, 캐시 만료시간을 늘려야 합니다.

캐시 만료시간을 늘리게 되면, 만료시간안에 다시 요청될 확률이 늘어나니 히트율이 높아지게 되겠지요.

하지만, 가격이 바뀌거나 댓글이 달려서 상품의 댓글수가 바뀌었을 경우 등
캐시 만료시간이 끝날 때까지 데이터가 갱신되지 않는 문제점이 있을 수 있습니다.

이 문제를 해결하기 위해 Spring이 제공하는 @CacheEvict 인터페이스를 활용하여 해당 상품의 캐시 데이터를 지우는 기능을 만들고

상품 관련 데이터에 변동이 있을 경우, 위 기능을 호출하도록 할 수 있습니다.

예시)

    @Override
    @CacheEvict(value = "example", keyGenerator = "customKeyGenerator", cacheManager = "cacheManager")
    public Goods example(Param p1, Param p2){
     ...
    }

이제 캐시를 시간단위로 늘려도 갱신이 되지 않거나 하는 일은 없을 것이고
캐시 히트율이 늘어 응답속도가 향상 될 것입니다.

주의할점: 위 상황은 상품 관련 데이터가 변동이 적다는 가정하에 진행한 것이고,
계속 캐시를 갱신시켜야된다면 캐시를 사용하는 의미가 많이 떨어질 것입니다.

읽어주셔서 감사합니다.

By. Ryankim

 

관련 글 : https://lion-king.tistory.com/entry/Redis-what-is

 

(Redis) Redis란? 우아한 Redis 발표영상 후기

https://www.youtube.com/watch?v=mPB2CZiAkKM Cache란? - Cache는 요청결과를 미리 저장해 두었다가 나중에 빠르게 서비스 해주는것을 의미 다이내믹 프로그래밍? 앞의 연산결과를 다시 사용하는 것이 핵심! 예.

lion-king.tistory.com

댓글