
redis에 객체(dto)를 저장할 때 serializer를 통해 직렬화해주어야 한다.
이 때, 선택할 수 있는 여러가지 직렬화 방법이 존재한다.
Class Type을 지정해야 하며, redis에 객체를 저장할 때 class 값 대신 Classy Type 값을 JSON 형태로 저장한다.
pacakge 등의 정보 일치를 고려할 필요가 없다는 장점이 있다.
하지만, class type을 지정해야 하기 때문에 특정 클래스에 종속적이며, redisTemplate을 여러 쓰레드에서 접근하게 될 때 serializer 타입의 문제가 발생하는 경우가 발생한다.
StringRedisSerializer는 String 값을 그대로 저장한다.
JSON 형태로 직접 encoding, decoding을 해줘야한다는 단점이 있지만 위의 두 개의 serializer에서 발생할 수 있는 문제가 발생하지 않는다.
class 타입을 지정할 필요가 없다.
쓰레드간의 문제가 발생하지 않는다.
객체의 클래스 지정 없이
모든 Class Type을 JSON 형태로 저장할 수 있는 Serializer이다
Class Type에 상관 없이 모든 객체를 직렬화해준다는 장점을 가지고 있다.
하지만, 단점으로는 Object의 class 및 package까지 전부 함께 저장하게 되어 다른 프로젝트에서 redis에 저장되어 있는 값을 사용하려면 package까지 일치시켜줘야한다.
따라서 MSA 구조의 프로젝트 같은 경우 문제가 생길 수 있을 것 같다.
나는 여러 객체를 캐싱해야 했기 때문에, 여러 객체를 직렬화/역직렬화 사용할 수 있는
GenericJackson2JsonRedisSerializer를 사용하기로 했다.
Resolved [org.springframework.data.redis.serializer.SerializationException:
Could not write JSON: Java 8 date/time type `java.time.LocalDateTime`
not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
앞서 봤듯이 GenericJackson2JsonRedisSerializer을 사용하면 class type에 상관 없이 직렬화/역직렬화가 가능하다. 하지만 날짜 타입에 대해서는 default로 지원이 안되는 것 같다.
jackson-datatype-jsr310 의존성을 추가한다.에러 문구에 나와있는대로, 해당 모듈을 추가해봤지만, 여전히 에러를 뱉었다.
Custom Serializer 사용하기
이런 형식인데, 찾아보니 Serializer를 커스텀할 필요가 없고, 더 간편한 방법이 있었다.
Custom ObejctMapper 생성하기Custom ObjectMapper를 생성하고, JavaTimeModule을 등록해준 후 GenericJackson2JsonRedisSerializer의 파라미터로 해당 ObjectMapper를 넘겨주면 된다.

registerModule() : 추가하고 싶은 모듈을 추가할 수 있다. 여기서는 JavaTimeModule을 추가하여 LocalDateTime 역직렬화를 가능하도록 함.
enableDefaultTyping() : 직렬화 시 type 정보를 저장할 scope를 지정한다. 여기서는 non-final 클래스들에 대해 타입 정보를 저장할 수 있도록 했다.(GenericJackson2JsonRedisSerializer의 기본 동작 방식)
하지만 얘는 2.10 버전 이후로 Deprecated 됐으며, activateDefaultTyping()을 사용이 권장되므로 코드를 수정한다.


class java.util.LinkedHashMap cannot be cast to class ...web.board.dto.BoardResponseDto
(java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.
이 에러는 위에서 ObjectMapper에 설정한 activateDefaultTyping()이 없을 때 만났던 에러이다. 이 메서드는 직렬화 시 기본적으로 type information을 함께 저장하도록 한다.
이때 의아했던 점은, Redis에 저장된 데이터에 class type이 존재하지 않았던 것이다.

분명 GenericJackson2JsonRedisSerializer는 class type 정보를 기본적으로 함께 저장한다고 알고 있고, custom ObjectMapper를 사용하기 전에는 class type을 함께 저장했었다.
하지만 custom ObjectMapper를 등록 후 에러를 뱉기 시작했고, 이유는 다음과 같았다.
먼저, GenericJackson2JsonRedisSerializer가 기본적으로 직렬화 시 class type(@class 속성)을 함께 정보하는 건 맞다.
하지만, GenericJackson2JsonRedisSerializer가 custom한 ObjectMapper를 사용할 때는 다른 이야기이다.
ObjectMapper는 기본적으로 직렬화/역직렬화 시 class type 정보를 포함하지 않기 때문에, 직렬화된 데이터에는 type 정보가 존재하지 않는다.
또한 역직렬화 시에도 ObjectMapper가 type 정보를 모른 채 역직렬화를 진행하게 되고, 기본 타입인 LinkedHashMap으로 역직렬화 되어 에러가 나는 것이다.
따라서, 앞서 본 것처럼 ObjectMapper에 activateDefaultTyping()을 통해 class type을 함께 직렬화/역직렬화 하도록 설정해주어야 한다.
저랑 비슷한 문제를 겪으신 듯 하여 찾아왔습니다 :D 저도 Generic ~ 을 직접 구현했는데, 스프링 3.1.1 부터는 좀 더 세련되게 ObjectMapper 를 변경할 수 있게 되었어요. 참고해보세요!
https://github.com/spring-projects/spring-data-redis/issues/2722