[maxxlog] 스터디방 목록 캐시 - Redis

maxxyoung·2024년 4월 5일
0

maxxlog

목록 보기
7/9

스프링 캐시 정리를 토대로 실제로 적용해보자.
스터디 목록은 모든 유저가 다 같은 화면을 볼 것이다. 자주, 반복적으로 조회되는 쿼리로 캐시적용을 통해 조회 성능을 개선하고자 했다.

스프링 캐시 + 스프링 레디스의 조합으로 스터디방 목록을 캐시 해보겠다.

설정

implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation("org.springframework.boot:spring-boot-starter-cache")
  • 의존성을 추가한다.
private const val PREFIX_OF_CACHE = "API::"
private const val LONG_TERM_CACHE = "longTerm"
private const val SHORT_TERM_CACHE = "shortTerm"


@Configuration
class CacheConfig {
    @Bean
    fun redisCacheConfiguration(): RedisCacheConfiguration {
        return RedisCacheConfiguration.defaultCacheConfig()
            .prefixCacheNameWith(PREFIX_OF_CACHE)
            .entryTtl(Duration.ofMinutes(1))
            .disableCachingNullValues()
            .serializeKeysWith(keySerializer)
            .serializeValuesWith(valueSerializer)
    }

    @Bean
    fun redisCacheManagerBuilderCustomizer(): RedisCacheManagerBuilderCustomizer? {
        return RedisCacheManagerBuilderCustomizer { builder: RedisCacheManagerBuilder ->
            builder
                .withCacheConfiguration(
                    SHORT_TERM_CACHE,
                    RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMinutes(1))
                        .disableCachingNullValues()
                        .serializeKeysWith(keySerializer)
                        .serializeValuesWith(valueSerializer)
                )
                .withCacheConfiguration(
                    LONG_TERM_CACHE,
                    RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofHours(2))
                        .disableCachingNullValues()
                        .serializeKeysWith(keySerializer)
                        .serializeValuesWith(valueSerializer)
                )
        }
    }

    private val keySerializer
        get() = RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string())
    private val valueSerializer
        get() = RedisSerializationContext.SerializationPair.fromSerializer(
            GenericJackson2JsonRedisSerializer(
                redisObjectMapper
            )
        )

    private val redisObjectMapper
        get() = ObjectMapper()
            .registerModules(KotlinModule.Builder().build(), JavaTimeModule())
            .activateDefaultTyping(
                BasicPolymorphicTypeValidator.builder().allowIfBaseType(Any::class.java).build(),
                ObjectMapper.DefaultTyping.EVERYTHING)

}

설정을 추가한다.

  • 모듈 기준으로 캐싱하려고 접두사로 API::를 사용했다.
  • 캐시 항목을 목적에 따라 shortTermlongTerm으로 나누었다.
  • shortTerm의 경우 1분, longTerm의 경우 2시간
  • data class는 기본 생성자를 만들지 못하는 이슈로 역직렬화InvalidDefinitionException이 발생하는 문제가 있었다. 해당 문제를 해결하기 위한 방법 중 하나가 kotlinModule을 등록하는 것이다. redisObjectMapper에 정의된 objectMapper를 설정에 등록해 주었다.

적용

@Cacheable(cacheNames = ["shortTerm"])
    fun getStudyRoomList(request: StudyRoomListRequest): StudyRoomListResponse? {
        val findStudyRoomList = studyRoomQueryRepository.findStudyRoomList(request.studyRoomSearch, request.studyRoomId, request.pageSize)
        return StudyRoomListResponse(findStudyRoomList?.map{SimpleStudyRoomDto.of(it)} ?: null)
    }
  • 스터디방이 빠른 주기로 만들어진다고 생각하여 짧은 주기 캐시 항목을 적용하였다.

github 스터디방 목록 조회 캐시 적용

profile
오직 나만을 위한 글. 틀린 부분 말씀해 주시면 감사드립니다.

0개의 댓글