간단하게 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를 적용해 보겠습니다.
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);
}
}
다시 localhost:8080/redis?param=data를 호출해 보았습니다.
처음 요청은 5초가 걸렸지만 그 후엔 바로 응답이 되는 것을 볼 수 있습니다.
심지어 Service, Repository 메서드가 호출도 되지 않았네요.
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 |
댓글