본문 바로가기
프로젝트/미니

Cache에 Redis 적용시키기

by HWK 2023. 9. 23.

기존 Cache는 시간 관련 기능이 적용되지 않았고, 이를 해결하기 위해 Redis를 도입했다.
가장 먼저 redis를 다운받았다. https://redis.io/download/

 

Download

Redis You can download the last Redis source files here. For additional options, see the Redis downloads section below. Stable (7.2) Redis 7.2 includes optimizations, several new commands, some improvements, bug fixes, and several new module APIs. It also

redis.io

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는 StringSet, 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

 

Spring Cache 적용으로 읽기 작업 성능 향상시키기

Spring Cache로 읽기 작업의 성능 향상시키기 Overview 현재 진행하고 있는 SNS 프로젝트에서 게시물 관련 기능을 개발하고 테스트를 하면서 서버에 동일한 요청을 여러 차례 보내게 되었다. 이 과정에

chagokx2.tistory.com

아래 블로그에서는 TypedJsonJacksonCodec 라는 기능을 소개하는데,
내가 직접 사용하지는 않았지만, @class 관련 문제를 많이 겪은 나에게 힌트를 주었고,
그 결과 jackson2JsonRedisSerializer를 이용해서 @class 문제를 해결할 수 있었다.

https://zorba91.tistory.com/352

 

[Redisson] 레디스로 객체 저장 시 클래스 (타입)정보 제외하기

redis client로 redisson을 쓰고 있는데 따로 설정 없이 객체를 저장할 경우 클래스 정보도 함께 저장된다. 데이터 직렬화를 하면서 클래서 정보도 포함시킨다. redisson은 객체를 사용하기 위해 RBucket

zorba91.tistory.com


오늘은 사실 노트북 분해조립을 했다. 마치 무면허 상태로 사람의 배를 갈라서 청소하는 느낌이였다...ㅋㅋㅋㅋ
어쨋든 이제 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