- [트러블 슈팅] redis 관련 문제 발생(2025.01.03)2025년 01월 03일 23시 34분 41초에 업로드 된 글입니다.작성자: do_hyuk728x90반응형
IOS 개발자 분들에게 문제 상황을 들었다.
현재 발생한 문제는 좋아요 & 좋아요 취소와 회원 상세 조회 api 의 응답값이 401 에러가 온다는 것이었다.
1. 좋아요 & 좋아요 취소 문제
현재 좋아요 로직은 현재 사용자 아이디 값(= userId)과 좋아요할 회원 아이디(= likedId) 두 가지 값이 필수 값이다.
userId를 key값으로 하고 value 값으로 likedId 로 Redis에 저장하고 있다.
만약 이미 좋아요 되어있는데 좋아요 api를 호출하거나
if (Boolean.TRUE.equals(likeCountRedisTemplate.opsForSet().isMember(userLikesKey,likedId))) { throw new IllegalStateException("Already liked"); }
좋아요 되어있지 않은데 좋아요 취소 api를 호출할 경우
if (Boolean.FALSE.equals(likeCountRedisTemplate.opsForSet().isMember(userLikesKey, likedId))) { throw new IllegalStateException("Not liked yet"); }
에러 메시지를 남기는데 현재 likedId 가 2인 회원을 좋아요 하면 "Already liked" 라 나오고 그렇다고 좋아요 취소를 누르면 "Not liked yet" 에러 로그를 호출한다.
또한 Redis에 저장된 데이터를 보면
> get likeCount:2 "\"0\"" > smembers userLikes:tester1 "2"
이렇게 뜬다.
아직 정확한 문제 원인을 찾지는 못하였지만 추측 상 likeCount 부분에 저장된 값을 보면 역슬래쉬가 들어가 있는 것을 볼 수 있다. 기존에 userLikes 처럼 문자 하나만 들어가는게 맞지만 어떠한 이유인지 몰라도 이스케이프 문자가 같이 들어가서 발생한 문제 같다.
로컬에서 테스트 하였을 때 Redis에 저장된 데이터를 지운 후 다시 진행하니 제대로 동작하는걸 볼 수 있다.
> get likeCount:2 "1" > smembers userLikes:tester1 1) "\"2\""
일단 likeCount에 이스케이프 문자가 포함될 경우 오류가 발생한다고 생각하고 문제를 찾아봐야겠다.
2025.01.06
Redis에 큰 따옴표가 한 번 더 저장되기에 이스케이프 문자가 포함되는 것을 알았고 관련된 문제로 찾아보니
RedisConfig 쪽 문제인 것을 확인하였다.
@Bean public StringRedisTemplate stringRedisTemplate() { final StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); stringRedisTemplate.setKeySerializer(new StringRedisSerializer()); stringRedisTemplate.setConnectionFactory(redisConnectionFactory()); GenericToStringSerializer<Object> genericToStringSerializer = new GenericToStringSerializer<>(Object.class); stringRedisTemplate.setValueSerializer(genericToStringSerializer); return stringRedisTemplate; }
위의 코드가 기존에 사용하던 코드인데 직렬화 방식으로 GenericToStringSerializer<Object>를 사용하였다.
GenericToStringSerializer<Object>는 객체를 문자열로 변환하는 데 사용된다. 하지만 GenericToStringSerializer<Object>를 사용하면 여러 타입의 객체를 처리할 수 있지만, 숫자를 다룰 때에는 여러 문제가 발생할 수 있다.
예를 들어, 어떤 객체를 JSON 문자열로 변환할 때, 문자열 안의 큰 따옴표는 이스케이프 처리되어 "\"1\""와 같이 저장될 수 있고, 이처럼 이스케이프 처리되어 저장된 문자를 increment 함수로 실행하려 하니 숫자로 변환이 안되어 ERR value is not an integer or out of range 가 발생된 것이다.
이러한 이유로 StringRedisTemplate에서는 숫자 데이터를 저장할 때 StringRedisSerializer를 사용하는 것이 더 안전하고 직관적이며 StringRedisSerializer는 문자열 데이터만 처리하므로, 숫자를 문자열로 변환하여 저장하고, 다시 읽을 때도 문자열로 처리되기 때문에 일관성을 유지할 수 있기에 StringRedisSerializer 로 수정하였다.
@Bean public StringRedisTemplate stringRedisTemplate() { final StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); stringRedisTemplate.setKeySerializer(new StringRedisSerializer()); stringRedisTemplate.setConnectionFactory(redisConnectionFactory()); stringRedisTemplate.setValueSerializer(new StringRedisSerializer()); return stringRedisTemplate; }
728x90반응형'포트폴리오 > Eighteen' 카테고리의 다른 글
[트러블슈팅] 랜덤 Pagination 너무 쉽게 봤다. (0) 2025.01.09 [트러블 슈팅] 회원 상세 조회 문제 발생(2025.01.06) (0) 2025.01.07 [트러블 슈팅] 요청 값 Dto에 어떻게 매핑되는가 (0) 2024.11.15 [트러블 슈팅] JwtFilter와 Security Config의 동작 순서 (1) 2024.10.16 [트러블 슈팅] S3 HTTPS(443) 접근 문제 (1) 2024.10.13 댓글