본문 바로가기
Spring

Spring Boot에 Redis Cache 적용해보기

by setung 2021. 11. 25.

간단하게 Spring boot에서 Redis를 통해 Cache를 해보겠습니다.

 

첫째로 Redis 의존성을 추가하고 설정을 해야 합니다.

 

builde.gradle

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

 

RedisConfig.class

@Configuration
public class RedisConfig {

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

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

    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory());
        redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }
    
    @Bean
    public CacheManager redisCacheManager() {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(connectionFactory())
                .cacheDefaults(redisCacheConfiguration)
                .build();

        return redisCacheManager;
    }
}

 

application.properties

spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379

 

@SpringBootApplication
@EnableCaching
public class RedisApplication {

   public static void main(String[] args) {
      SpringApplication.run(RedisApplication.class, args);
   }

}

 

RedisTemplate 빈은 만들고, 메인 클래스에 @EnableCaching 어노테이션을 추가해 줍니다.

 

설정은 끝났습니다.

예제를 위한 Controller, Service, Repository를 만들어보겠습니다.

 

RedisController.class

@Slf4j
@RestController
@RequestMapping("/redis")
@RequiredArgsConstructor
public class RedisController {

    private final RedisService redisService;

    @GetMapping
    public String getData(@RequestParam String param) {
        log.info("------ call Controller");

        long start = System.currentTimeMillis();
        String data = redisService.getData(param);
        long end = System.currentTimeMillis();

        log.info("------ controller time = {}", end - start);
        return data;
    }
}

RedisService.class

@Slf4j
@Service
@RequiredArgsConstructor
public class RedisService {

    private final RedisRepository repository;

    public String getData(String param) {
        log.info("call Service");
        return repository.getData(param);
    }

}

RedisRepository.class

@Slf4j
@Repository
public class RedisRepository {

    public String getData(String param) {
        log.info("call Repository");

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return param;
    }

}

단순히 param이란 String 파라미터를 넘겨주면 그대로 반환하는 Controller, Service, Repository를 만들었습니다.

Repository는 Thread.sleep(5000)을 넣어 복잡한 로직임을 연출해 보았습니다.

 

localhost:8080/redis?param=data를 호출해보겠습니다.

매번 호출할 때마다 5초 정도 걸리게 됩니다.

 

Cache 적용 전

 

드디어 Cache를 적용해 보겠습니다.

Service에 Cache를 적용할 메서드에 @Cacheable 어노테이션을 추가합니다.

어노테이션 안에 key, value 값은 Redis의 Key 값으로 사용됩니다.

@Slf4j
@Service
@RequiredArgsConstructor
public class RedisService {

    private final RedisRepository repository;

    @Cacheable(key = "#param", value = "getData")
    public String getData(String param) {
        log.info("call Service");
        return repository.getData(param);
    }

}

Cache 적용 후

다시 localhost:8080/redis?param=data를 호출해 보았습니다.

처음 요청은 5초가 걸렸지만 그 후엔 바로 응답이 되는 것을 볼 수 있습니다.

심지어 Service, Repository 메서드가 호출도 되지 않았네요.

 

 

Redis

Redis를 보면 "getData::data"라는 key가 저장되어있습니다.

Redis의 "getData::data"를 지우고 요청을 하면 다시 5초가 소요됩니다.

 

 

Issue 사항

LocalDate, LocalDateTime, LocalTime와 같은 클래스는 직렬화, 역직렬화 문제로 예외가 발생한다.

아래와 같이 사용하면 된다.

@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime createdAt;

 

'Spring' 카테고리의 다른 글

Spring의 @Transactional  (0) 2021.12.15
JDK Dynamic Proxy와 CGLIB  (0) 2021.12.07
Spring AOP  (0) 2021.12.02
Spring JPA Specification을 사용해 유연하게 조회 API 만들기  (3) 2021.11.08
@RestControllerAdvice 예외 처리  (0) 2021.10.31

댓글