package kr.co.vividnext.sodalive.configs import org.redisson.Redisson import org.redisson.api.RedissonClient import org.redisson.config.Config import org.springframework.beans.factory.annotation.Value import org.springframework.cache.annotation.EnableCaching import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.data.redis.cache.RedisCacheConfiguration import org.springframework.data.redis.cache.RedisCacheManager import org.springframework.data.redis.connection.RedisConnectionFactory import org.springframework.data.redis.connection.RedisStandaloneConfiguration import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory import org.springframework.data.redis.core.RedisTemplate import org.springframework.data.redis.repository.configuration.EnableRedisRepositories import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer import org.springframework.data.redis.serializer.RedisSerializationContext import org.springframework.data.redis.serializer.StringRedisSerializer import java.time.Duration @Configuration @EnableCaching @EnableRedisRepositories class RedisConfig( @Value("\${spring.redis.host}") private val host: String, @Value("\${spring.redis.port}") private val port: Int ) { @Bean(destroyMethod = "shutdown") fun redissonClient(): RedissonClient { val config = Config() config.useSingleServer() .setAddress("rediss://$host:$port") .setSslEnableEndpointIdentification(true) .setSslTruststore(null) .setDnsMonitoringInterval(30000) .setConnectionMinimumIdleSize(0) .setConnectionPoolSize(5) return Redisson.create(config) } @Bean fun redisConnectionFactory(): RedisConnectionFactory { val clientConfiguration = LettuceClientConfiguration.builder() .useSsl() .disablePeerVerification() .build() return LettuceConnectionFactory(RedisStandaloneConfiguration(host, port), clientConfiguration) } @Bean fun redisTemplate(): RedisTemplate<*, *> { val redisTemplate: RedisTemplate<*, *> = RedisTemplate() redisTemplate.setConnectionFactory(redisConnectionFactory()) return redisTemplate } @Bean fun cacheManager(redisConnectionFactory: RedisConnectionFactory): RedisCacheManager { val defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(30)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) val cacheConfigMap = mutableMapOf() cacheConfigMap["default"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(30)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) cacheConfigMap["cache_ttl_3_days"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofDays(3)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) cacheConfigMap["cache_ttl_3_hours"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(3)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) cacheConfigMap["cache_ttl_10_minutes"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(10)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) cacheConfigMap["cache_ttl_5_minutes"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(5)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) cacheConfigMap["cache_ttl_3_minutes"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(3)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) // 24시간 TTL 캐시: 인기 캐릭터 집계용 cacheConfigMap["popularCharacters_24h"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(24)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( GenericJackson2JsonRedisSerializer() ) ) return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(defaultCacheConfig) .withInitialCacheConfigurations(cacheConfigMap) .build() } }