package com.kamco.cd.kamcoback.config; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.time.Duration; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; 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.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @EnableCaching public class RedisConfig { @Value("${spring.data.redis.host}") private String host; @Value("${spring.data.redis.port}") private int port; @Value("${spring.data.redis.password}") private String password; @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); redisConfig.setHostName(host); redisConfig.setPort(port); redisConfig.setPassword(password); return new LettuceConnectionFactory(redisConfig); } /** Redis에서 사용할 공통 ObjectMapper */ @Bean(name = "redisObjectMapper") @Primary public ObjectMapper redisObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.findAndRegisterModules(); return objectMapper; } /** 공통 Serializer (Template + Cache 둘 다 이거 사용) */ @Bean public GenericJackson2JsonRedisSerializer redisSerializer( @Qualifier("redisObjectMapper") ObjectMapper redisObjectMapper) { return new GenericJackson2JsonRedisSerializer(redisObjectMapper); } @Bean public RedisTemplate redisTemplate( RedisConnectionFactory connectionFactory, GenericJackson2JsonRedisSerializer redisSerializer) { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setValueSerializer(redisSerializer); template.setHashValueSerializer(redisSerializer); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager( RedisConnectionFactory connectionFactory, GenericJackson2JsonRedisSerializer redisSerializer) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) // 기본 TTL 1시간 .serializeKeysWith( RedisSerializationContext.SerializationPair.fromSerializer( new StringRedisSerializer())) .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)); return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build(); } }