기존 Cache는 시간 관련 기능이 적용되지 않았고, 이를 해결하기 위해 Redis를 도입했다.
가장 먼저 redis를 다운받았다. https://redis.io/download/
gradle.build에는 다음과 같은 코드가 추가되었다.
// Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
또한 application.properties에는 다음과 같은 코드가 추가되었다.
보는대로 redis의 주소와 cacheType를 redis로 지정해 주는 것이다.
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.cache.type=redis
Redis는 String, Set, Sorted, Set, Hash, List 데이터 형식만을 지원하기 때문에, CookieStoreResponsDto를 새로 만들었다.
자동 형변환에 대해 다시 고민해보자.
@Getter
@NoArgsConstructor
public class CookieStoreResponseDto{
private String id;
private String storeName;
private String storeDetails;
private String storeAddress;
private String avgStar;
private String storePoint;
public CookieStoreResponseDto(Store store){
this.id = Long.toString(store.getId());
this.storeName = store.getStoreName();
this.storeDetails = store.getStoreDetails();
this.storeAddress = store.getStoreAddress();
this.avgStar = Double.toString(store.getReviewedPeople() != 0 ? store.getStar() / store.getReviewedPeople() : 0);
this.storePoint = Integer.toString(store.getStorePoint());
}
}
이후 Redis 기능을 기존 Spring Framework에 추가시키는 코드인 CacheConfig를 추가했다.
별거 없어 보이긴 하지만 아래의 코드를 완성시키는데 6시간 정도 걸린것같다.
아래의 코드 덕분에 @CacheAble 함수에 시간 기능을 적용시키고, Redis의 @class를 함께 반환해주는 문제를 해결했다.
@Configuration
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
RedisSerializationContext.SerializationPair<Object> jsonSerializer =
RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);
RedisSerializationContext.SerializationPair<String> keySerializer =
RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer());
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(
RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(keySerializer)
.serializeValuesWith(jsonSerializer)
.entryTtl(Duration.ofSeconds(20))
)
.build();
return redisCacheManager;
}
}
한줄 한줄 설명해보겠다.
- @Configuration은 이 클래스가 Spring Bean 구성 클래스임을 나타내는 어노테이션이고,
@Bean은 Spring IoC 컨테이너에 Bean을 등록하는 어노테이션이다. 아는 내용이지만 중요하다. - public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory)는 @Bean에 의해
RedisCacheManager Bean을 생성한다. - Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class)의 역할은 Jackson2JsonRedisSerializer를 생성하는데,
이는 Redis에 저장된 객체를 JSON 형식으로 직렬화하고 역직렬화하는 데 사용된다. - RedisSerializationContext.SerializationPair<Object> jsonSerializer =
RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);를 사용하여
JSON 직렬화 설정을 정의다. 이 부분에서는 키와 값의 직렬화 방법을 지정한다.
이렇게 하면 객체 유형 정보를 유지하면서 @class 필드가 포함되지 않는 형태의 캐시 데이터를 저장할 수 있다. - RedisSerializationContext.SerializationPair<String> keySerializer = ...:
RedisSerializationContext를 사용하여 키의 직렬화 설정을 해준다. 여기서는 키를 문자열로 직렬화하도록 지정한다.
만약 자동 형변환이 가능하다면, 그것은 Spring Data Redis의 특정 설정을 통해 가능할 수 있다.
또는 직접 Dto를 이용할 수 있다. String 형을 다시 int나 double등 원하는 형으로 변환해줘도 될 것이다.
어쨋든 Redis에서는 문자열로 키를 직렬화 하는것이 일반적이다. - RedisCacheManager redisCacheManager = ...:
RedisCacheManager를 빌드한다. RedisCacheConfiguration을 사용하여 캐시 설정을 구성하고,
이 설정에 앞에서 정의한 직렬화 설정을 적용한다. - cacheDefaults(...): 기본 캐시 구성을 설정한다. 여기서는 키와 값을 지정한 직렬화 설정으로 설정하고, entryTtl(Duration.ofSeconds(20))을 사용하여 캐시 항목의 만료 시간을 20초로 지정한다.
- .build(): RedisCacheManager를 빌드하여 완성된 캐시 매니저 객체를 반환한다.
- return redisCacheManager;: 구성된 RedisCacheManager를 반환한다.
이 결과 다음과 같은 @Cachable을 적용한, 시간 설정 기능도 있는, Service 메서드를 활용할 수 있다.
@Cacheable(cacheNames = "storeCache", key = "#keyword")
public List<CookieStoreResponseDto> getStoreByKeyword(String keyword) {
List<CookieStoreResponseDto> results = storeRepository.findAllByStoreNameContaining(keyword)
.stream().map(CookieStoreResponseDto::new).toList();
return results;
}
가장 참고하는데 도움이 된 두 블로그를 소개하겠다. 아래 블로그에서 CacheConfig 코드의 원본을 얻을 수 있었다.
https://chagokx2.tistory.com/98
아래 블로그에서는 TypedJsonJacksonCodec 라는 기능을 소개하는데,
내가 직접 사용하지는 않았지만, @class 관련 문제를 많이 겪은 나에게 힌트를 주었고,
그 결과 jackson2JsonRedisSerializer를 이용해서 @class 문제를 해결할 수 있었다.
https://zorba91.tistory.com/352
오늘은 사실 노트북 분해조립을 했다. 마치 무면허 상태로 사람의 배를 갈라서 청소하는 느낌이였다...ㅋㅋㅋㅋ
어쨋든 이제 Redis를 여러 코드에 적용시켜보자!
'프로젝트 > 미니' 카테고리의 다른 글
Eclipse, MS-SQL 연습용 프로젝트 (2) | 2024.10.10 |
---|---|
웹 미니 프로젝트 총평 (1) | 2023.10.03 |
효과적인 부분 문자열 검색(Full-Text, 캐시, Redis) (0) | 2023.09.23 |
프론트엔드 개발 (0) | 2023.09.22 |
코드 병합 (0) | 2023.09.18 |