com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type java.lang.String
from Object value (token JsonToken.START_OBJECT
)
at [Source: (byte[])"{"sender":"닉네임1","roomId":"7fbbe852-028b-4bf0-bfd9-3a00ec8ef7cb","receiver":"닉네임2","message":"안녕"}"; line: 1, column: 1]
websocket stomp 를 이용한 채팅 내역을 redis 에 저장했다.
cache 에 데이터가 있다면 cache 데이터를 사용하고, 없다면 DB 데이터를 사용 후 이를 다시 cache 에 저장하는 방식인
look aside cache 전략을 사용해서 채팅 내역을 조회하고자 했다.
그러나, 위와 같은 에러 메시지가 발생했는데 이는 역직렬화와 관련된 문제였다.
당연히 조회에 문제가 있다고 생각했고, 이를 Json 객체를 문자열로 변환해주는 등... 다양한 시도를 했으나 해결되지 않았다.
문제 해결의 핵심은 '저장하는 데이터'에 있었다.
public MessageResponseDto createMessage(Long id, MessageDto messageDto, User user) {
MessageRoom messageRoom = messageRoomRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("쪽지방이 존재하지 않습니다.")
);
// Message 클래스 직렬화
redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(Message.class));
// list 로 redis 에 저장
redisTemplateMessage.opsForList().rightPush(messageDto.getRoomId(), messageDto);
// DB 저장
Message message = new Message(messageDto.getSender(), messageDto.getRoomId(), messageDto.getReceiver(), messageDto.getMessage(), messageRoom, user);
Message saveMessage = messageRepository.save(message);
return new MessageResponseDto(saveMessage);
}
Redis는 데이터를 문자열 형태로 저장하지만, 객체를 저장하려면 이를 직렬화하여 문자열로 변환해야 한다.
json 형식으로 저장하기 위해 jackson 라이브러리로 Message 클래스의 직렬화 처리를 진행하는 것으로 해결할 수 있었다.