CacheEvict key 패턴과 매치되는 경우 제거하기

정명진·2023년 9월 7일
1
post-custom-banner

사이드 프로젝트를 진행하면서 캐시를 적용해야 할 일이 생겼다. 그런데 폴더상세뷰를 구현하면서 key가
userId, folderName, pageSize, pageNumber의 일련의 조합이 되면서 컨텐츠 CRUD 또는 폴더 CRUD가 일어날 경우 해당 캐시를 evict 해야하는 상황에 key 값으로 userId만 넘겨주다 보니 정상적으로 캐시가 제거되지 않는 현상이 발생했다. 물론 CacheEvict의 condition 기능을 활용할 수 있지 않을까 생각했지만 해당 경우는 파라미터로 넘어온값에 대해 조건을 걸어 구현하는것이기에 불가능했다.

그래서 다른 방법을 찾다가 AOP를 적용할 수 있다는 사실을 알게되어 적용후 서비스에 반영하였다.

코드는 다음과 같다.

우선 Annotaion을 만들어줬다.

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class CachePrefixEvict(
    val key: String = "",
    val value: String = "",
)

기존 CacheEvict 처럼 key, value를 받도록 했다.

그리고 Aspect를 다음과 같이 구현했다.

@Aspect
@Component
class CachePrefixEvictAspect(
    private val redisCacheManager: RedisCacheManager
) {
    val log = logger()

    @Around("@annotation(CachePrefixEvict)")
    fun cachePrefixEvict(joinPoint: ProceedingJoinPoint){
        val signature = joinPoint.signature as MethodSignature
        val method = signature.method
        val cachePrefixEvict = method.getAnnotation(CachePrefixEvict::class.java)
        val parseKey = getDynamicValue(signature.parameterNames, joinPoint.args, cachePrefixEvict.key)?.let { it as String }
        log.info("value {}", cachePrefixEvict.value)
        log.info("key {}", parseKey)
        // delete key
        val redisCache = redisCacheManager.get(cachePrefixEvict.value) as RedisCache
        redisCache.clear("$parseKey*")
        joinPoint.proceed()
    }
}

이제 CachePrefixEvict 어노테이션을 실제 메소드에 적용후 테스트 했을 때 userId를 포함한 folderDetailView의 캐시가 정상적으로 제거되는걸 확인했다.

@CachePrefixEvict(value = "folderDetailView", key = "#userId")
override fun create(userId: String, contentCreateDTO: ContentCreateDTO)
profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..
post-custom-banner

0개의 댓글