본문 바로가기
개발/SpringBoot

SpringBoot Redis Cache 적용 - @Cacheable, @CacheEvict

by 궁즉변 변즉통 통즉구 2024. 10. 14.
반응형

SpringBoot에서 Redis를 활용하여 Cache를 적용하는 방법을 알아본다. 보통 로컬 Cache를 적용할 때 Caffeine Cache 또는 Ehcache를 적용할 수 있는데 글로벌 Cache로 Redis도 쉽게 적용이 가능하다.

 

1. 의존성 설정

redis 적용을 위해서 'spring-boot-starter-data-redis' 의존성을 추가해준다.

implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.1.0'

 

2. Config 설정

application.yml 이나 application.properties 파일에 아래와 같이 redis 설정을 진행한다. 필자는 properties 파일 기준으로 작성을 했다. 

# redis
spring.cache.type=redis
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.repositories.enabled=false
expire.defaultTime=600

 

다음으로 Config 파일을 아래와 같이 작성해준다. 제일 상단에 @EnableCaching 어노테이션을 설정하는 것과, 하단에 RedisCacheManager 빈을 등록해주는 것이 중요하다. 

@EnableCaching
@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.port}")
    private int redisPort;

    @Value("${spring.data.redis.password}")
    private String redisPwd;

    @Value("${expire.defaultTime}")
    private long defaultExpireSecond;

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // timestamp 설정 제거
        mapper.registerModules(new JavaTimeModule(), new Jdk8Module()); // java8, java time module 등록
        return mapper;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setPort(redisPort);
        redisStandaloneConfiguration.setHostName(redisHost);
        redisStandaloneConfiguration.setPassword(redisPwd);
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration);
        return lettuceConnectionFactory;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory,
                                               ObjectMapper objectMapper) {
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
                .disableCachingNullValues() // null 허용 제거
                .entryTtl(Duration.ofSeconds(defaultExpireSecond))
                .serializeKeysWith(RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)));

        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(configuration).build();
    }

}

 

3. Cache 적용

Service 클래스에서 Cache를 적용할 메소드에 @Cacheable 어노테이션을 작성해준다. 

@Service
@Slf4j
@RequiredArgsConstructor
public class PostSearchServiceImpl {

    private final PostSearchMapper postSearchMapper;

    @Cacheable(value = "getProducts", key = "'getProducts-' + #postSearchRequest.getId()")
    public List<PostDTO> getProducts(PostSearchRequest postSearchRequest) {
        List<PostDTO> postDTOList = null;
        try {
            postDTOList = postSearchMapper.selectPosts(postSearchRequest);
            log.info("call method getProducts!!,  {}", postDTOList); // Redis 적용 테스트용 로그
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        return postDTOList;
    }
}

 

Cache 삭제 테스트를 위해서 다른 메소드에는 @CacheEvict 어노테이션을 아래와 같이 작성해준다. 

@CacheEvict(value = "getProducts", allEntries = true)
public void register(String id) {
	log.info("cache evict!!")    
}

 

4. 테스트

먼저 Cache 적용(@Cacheable)을 테스트 해보면 메소드가 처음 호출될 때는 아래와 같이 로그가 최초에 한번 찍히게 되고, 두번째 호출부터는 Cache가 적용되어(메소드 내부가 호출되지 않음) 해당 로그가 찍히지 않게 되는 것을 확인할 수 있다.

 

그리고 Redis를 조회해보면 아래와 같이 Cache값이 저장된 것을 확인할 수 있다.

 

이제 Cache를 삭제하는(@CacheEvict) 메소드를 호출하게 되면 Cache가 제거되고, 위의 Cache 적용 메소드를 다시 호출하면 메소드가 호출되어 로그가 다시 찍히게 된다. 

 

반응형

댓글