Redis
먼저 결과 코드를 쓰자면 이거다.
public StatDictResponseDto getDto(String key){
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Dto.class));
ValueOperations<String, Dto> redis = redisDtoTemplate.opsForValue();
Dto data = redis.get(key);
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
return data;
}
이틀동안 붙잡고 있던 문제였다. 단순하지 않은 구조의(내부에 List<>를 가지고 있는 형태의) DTO를 Redis로 불러오려고 하니 정상적으로 매핑되지 않고 java.util.LinkedHashMap cannot be cast to ... 오류메세지가 출력되는 문제였다.
나는 DTO로 SET을 했는데, 왜 LinkedHashMap인 줄 아는거냐고. 의문에 의문이 뒤따랐다. 내부 필드 하나하나를 전부 캐싱하고 불러오는 식으로 해야하나? 하는 생각까지 들었다.
근데 Redis key를 직접 확인해보면 데이터는 잘 들어가 있는 상태였다. 그것을 보면서 내가 레디스를 뭔가 잘못 쓰고 있구나 하는 생각이 들었다.
프로젝트가 이제는 일주일가량 남았다. 사실 이제 와서 레디스를 공부하기엔 많이 촉박하다. 런칭도 해야하기때문에 이 문제를 해결하기 위해 주어진 시간은 일주일보다도 더 적다. 어차피 속성으로 배운 것, 속성으로 해결해야 했다. 그래서 이것저것 자료를 찾아보기 시작했다.
단서는 아래 블로그에서 얻었다. 감사의 뜻을 전합니다.
[SpringBoot Redis] Redis에 커스텀 객체 저장 시 오류 - Azderica
[SpringBoot Redis] Redis에 커스텀 객체 저장 시 오류 Posted 4. June 2021. 3 min read. Redis HashValue 에 커스텀 객체 저장 시 오류 발생점. 스프링으로 개발을 진행하던 중, Redis HashValue에 커스텀 데이터 객체를
azderica.github.io
가장 먼저 들었던 생각은 '그러면 그동안 다른 DTO는 어떻게 매핑하고 있었던거지?' 였다.
답은 가까이에 있었다. 처음 레디스를 세팅했을 때, 그 형식을 직접 지정해준 것이었다. Jackson으로. 내가 직접. 내 손으로.
[SpringBoot/Redis/Ubuntu] 우분투 환경에 Redis 설치, SpringBoot에 세팅
Redis Redis. 얼마나 좋길래 이렇게 추천을 받는 것인지. 써보고 싶어졌다. 그래서 세팅해본다. 1. ubuntu 환경에 Redis 설치 $sudo apt-get update $sudo apt-get install -y redis-server 2. Redis configuratio..
dazbee.tistory.com
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
여기서 ValueSerializer를 설정해줬기 때문에 일반 클래스가 레디스에 잘 들어갈 수 있었던 것이다. 이 순간 깨달음을 얻었다. 그러면 이 시리얼라이저를 잘 건드리면 어떻게 잘 해볼 수 있지 않을까?
그래서 코드를 바로 건드려봤다.
public void setDto(String key, Dto object){
redisTemplate.delete(key);
redisDtoTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Dto.class));
ValueOperations<String, Dto> redis = redisDtoTemplate.opsForValue();
redis.set(key, object);
redisTemplate.expire(key, 10, TimeUnit.MINUTES);
}
결과는 성공이었다. 해당 Dto 형식으로 값을 세팅 하는 것도, 불러오는 것도 잘 되었다. 자동으로 형식을 지정해주던 것을 명시적으로 정의해주니 잘 되는 것이다. 속성으로 공부하는 것이 이렇게 무섭다. 아마 위의 코드도 임시방편같은 것일 수 있다. 진짜 나중에 제대로 공부해서 다시 만들어봐야겠다.
뭐 아무튼 오늘도 문제 해결. 기쁘다.
추가)
문제 해결이 아니었다. template를 변경하면 해당 인스턴스에 대해서만 바뀌는 줄 알았는데 redistemplate 전체에서 바뀌는 것이었다. 야매로 적용된 기술의 한계다. 그래서 해결도 야매로 했다.
public StatDictResponseDto getDto(String key){
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Dto.class));
ValueOperations<String, Dto> redis = redisDtoTemplate.opsForValue();
Dto data = redis.get(key);
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
return data;
}
set이 아닌 get 쪽에서 값을 받아올 때만 잠깐 바꿔주고 원복하는 형식으로 해주었다.
'기술 > Spring-Boot' 카테고리의 다른 글
[Spring] Gradle은 JDK 19를 현재 지원하지 못 함 (0) | 2022.11.24 |
---|---|
스프링부트 3.0 메모.. (0) | 2022.10.22 |
[SpringBoot] FetchJoin 없이 N+1 문제 제거하기 (0) | 2022.01.10 |
[Ubuntu/nginx] 스프링 부트 및 우분투 환경에서 nginx 이용한 무중단배포 구현 (0) | 2022.01.05 |
[Ubuntu/Travis-CI/CodeDeploy] SpringBoot 환경 배포 자동화 환경 구축 (0) | 2022.01.04 |
댓글