SpringBoot] Redis Cache 의 값을 DTO로 저장하고 불러오기

JUNHYUK CHANG·2024년 3월 18일
1

TIL

목록 보기
30/33

지난 포스트에서 @Cachable어노테이션 없이 Cache등록하기를 사용해보았고, 캐시의 적중 여부에 따라 Boolean 형태로 응답하는 과정을 구현해 보았다.

이번엔 적중 여부에 따라 실제 저장된 값을 가져와 반환하도록 하는 기능을 구현해보자.

그러기 위해 우선 Redis 의 캐시매니져에서 우리의 캐시를 어떻게 저장하는지 부터 알아보면

Redis-cli 에서 TYPE 를 통해 읽어왔을 때 모두 String 으로 저장된 것을 확인할 수 있다.

아하~ 그러면 다시 가져왔을땐 .toInt() 나 .toDouble() 등으로 고치면 되겠구나~

아니다.

get() 메서드를 통해 캐시에 저장된 value 를 가져왔을 때의 데이터 형은 ValueWrapper 라는 형태로 가져오게 된다.

ValueWrapper는

스프링 프레임워크에서 제공하는 인터페이스로, 캐시에 저장된 값의 래퍼(wrapper) 역할을 한다. 이 인터페이스는 캐시에 저장된 값과 해당 값에 대한 메타데이터를 함께 관리한다.

일반적으로 캐시에 저장된 값을 가져올 때, 스프링 캐시 추상화 API를 사용하면 ValueWrapper 형태로 값을 가져올 수 있다. 이를 통해 실제 값에 접근할 수 있으며, 캐시에 저장된 값이 존재하지 않거나 타입이 일치하지 않는 경우에 대비하여 안전하게 처리할 수 있다.

그렇다면 우리는 ValueWrapper.get() 메서드로 Wrapper 안에 감싸여진 실제 데이터(value)를 가져오도록 하면 되는 것이다.

아하~ 그럼 인제 DTO 도 .get() 으로 가져오면 되겠구나~ 좋네~

가 아니었다.

이번엔 LinkedHashMap cannot be cast to class ~~~(dto 클래스로 변환할 수 없다~) 라고 말하고 있다.

LinkedHashMap는

Java에서 제공하는 클래스로, 해시맵(HashMap: 해시 테이블을 사용하여 키-값 쌍을 저장하는 자료구조)과 연결 리스트(Linked List:각 요소가 이전 요소와 다음 요소를 가리키는 포인터를 갖는 구조)의 특징을 결합한 것이다. 이 클래스는 삽입 순서 또는 접근 순서를 보존하여 요소를 저장한다.

그래서 왜 LinkedHashMap 이 튀어나왔는고 하니 직렬화/역직렬화 문제와 관련되는 문제였다.
RedisConfig 에서 CacheManager 를 정의할 때 GenericJackson2JsonRedisSerializer를 통해 역직렬화 하도록 하고 있었는데, ObjectMapper 가 우리의 DTO type 정보를 모른 채 역직렬화를 진행하기 때문에 기본타입인 LinkedHashMap 으로 역직렬화 시키고 있던 것이다.

따라서 LinkedHashMap 으로 가져온 값을 as EventResponse 를 통해 명확하게 변환할 대상을 지정해주면 원하는 결과를 얻을 수 있게 된다!!


제대로 구조를 잘 파악하지 못했을 땐 생성자 오류가 계속 떠서 어떻게든 값을 보여주기 위해 아래와 같은 삽질을 하기도 했었는데 다른 DTO 도 일일히 변환할 생각을 했다니 정말 아찔하다..

0개의 댓글