작성
·
15
0
안녕하세요. redis 강의를 통해 간단한 프로젝트로 적용을 하려고 합니다.
@Cacheable(
value = "reviewList",
key = "'review:store:' + #storeId + ':page:' + #pageable.pageNumber",
cacheManager = "reviewCacheManager",
condition = "#pageable.pageNumber == 0")
@Transactional(readOnly = true)
public Page<ResViewReviewDto> getReviews(UUID storeId, ReviewRepositorySearchConditionDto condition,
Pageable pageable) {
Page<ResViewReviewDto> reviews = reviewRepository.findReviews(storeId, condition, pageable);
return new PageImpl<>(reviews.getContent(), pageable, reviews.getTotalElements());
}
원래는 return reviews를 했더니 계속 조회를 누르면 ClassCastException: LinkedHashMap cannot be cast to Page 이 오류가 나오게 됩니다. 강의에서는 그냥 getContent를 List로 반환값을 보냈는데 혹시 위 코드처럼 new PageImpl 형식으로 return 해도 괜찮을까요?
답변 2
0
안녕하세요 수현님 ! 질문 잘해주셨어요 ~
질문해 주신 내용에 대해 답변드려볼게요 !
우선 'ClassCastException: LinkedHashMap cannot be cast to Page' 에러가 발생하는 이유는
Redis가 Page 객체를 직렬화/역직렬화하는 과정에서 문제가 생기기 때문이에요 !
Redis에 저장될 때 Page 객체가 JSON으로 변환되면서 LinkedHashMap 형태로 저장되는데,
이걸 다시 꺼낼 때 Page 객체로 변환하지 못해서 발생하는 에러죠 :)
"강의에서는 그냥 getContent를 List로 반환값을 보냈는데 혹시 위 코드처럼 new PageImpl 형식으로 return 해도 괜찮을까요?"
-> 우선 결론적으로 'new PageImpl 형식으로 return '보다 List로 반환하는걸 권장드려요 !
new PageImpl<>() 방식도 동작할 수는 있지만, 권장하지 않아요 !
PageImpl도 결국 Page 인터페이스를 구현한 객체라서 직렬화 문제가 발생할 수 있어요 !
그래서 실제로 동작하더라도 불안정할 수 있고,
Spring이나 Redis 버전이 바뀌면 또 다른 문제가 생길 수 있어요 !
혹시나 페이지네이션의 메타 데이터를 포함해서 응답하는 방법에 대해
궁금하신 거라면 댓글 한 번만 남겨주세요~!!
추가로 더 궁금하신 점 있으시면 언제든 추가 질문 남겨주시구요!
늘 파이팅입니다 😋
0
안녕하세요, 인프런 AI 인턴입니다. 이수현님,
Redis 캐싱 구현 도중 발생한 ClassCastException
에 대해 질문 주셨습니다. LinkedHashMap
cannot be cast to Page
오류는 객체의 직렬화/역직렬화 문제에서 발생할 수 있습니다. 특히, 캐시된 객체를 다시 가져올 때 일치하지 않는 타입이 원인이 됩니다.
@Cacheable
어노테이션을 사용할 때, 캐시된 데이터가 Page
객체로 바로 직렬화되지 않은 경우 발생할 수 있으며, 캐시에서 복원할 때 타입이 일치하지 않아 예외가 발생합니다.
DTO로 변환해 이용:
강의처럼 getContent()
를 통한 List
형태로 사용하면, 복잡한 객체 직렬화 문제를 피할 수 있습니다.
Page 대신 List로 캐싱:
new PageImpl<>(...)
을 통해 생성된 객체가 Page
로 인식되기 위해서는 프레임워크가 이를 직렬화할 수 있어야 합니다. 그러나 복잡한 구조의 Page
객체는 직렬화 과정에서 문제가 생길 수 있습니다. 따라서, 복잡성을 줄이기 위해 Page
객체 대신 List
객체를 캐싱하는 것이 좋습니다.
Page 캐싱 시 직렬화 방식 설정:
꼭 Page
객체를 캐싱해야 한다면, 직렬화 시 GenericJackson2JsonRedisSerializer
같은 JSON 변환기를 통해 해결할 수 있습니다. 하지만 이는 JSON 설정의 세부 조율이 필요하며 여전히 문제를 완전히 해결하지 못할 수 있습니다.
아래 링크들은 유사한 문제를 겪은 질문과 그에 대한 답변이며 도움이 되실 겁니다:
페이지 데이터 캐싱할때 질문: 유사한 Page
객체 캐싱과 관련된 질문입니다.
@Cacheable key 속성에서 page, size 파라미터값 null: @Cacheable
사용 시 발생할 수 있는 파라미터 이슈에 대한 답변입니다.
이해에 도움이 되었길 바랍니다. 질문자님의 이해를 돕고자 기존 답변을 참고하여 유사한 답변 링크를 추천해드렸습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.