강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

이수현님의 프로필 이미지
이수현

작성한 질문수

비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)

redis 적용을 위한 service 반환값

작성

·

14

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

JSCODE 박재성님의 프로필 이미지
JSCODE 박재성
지식공유자

안녕하세요 수현님 ! 질문 잘해주셨어요 ~

질문해 주신 내용에 대해 답변드려볼게요 !

우선 '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 객체로 바로 직렬화되지 않은 경우 발생할 수 있으며, 캐시에서 복원할 때 타입이 일치하지 않아 예외가 발생합니다.

해결 방법

  1. DTO로 변환해 이용:
    강의처럼 getContent()를 통한 List 형태로 사용하면, 복잡한 객체 직렬화 문제를 피할 수 있습니다.

  2. Page 대신 List로 캐싱:
    new PageImpl<>(...)을 통해 생성된 객체가 Page로 인식되기 위해서는 프레임워크가 이를 직렬화할 수 있어야 합니다. 그러나 복잡한 구조의 Page 객체는 직렬화 과정에서 문제가 생길 수 있습니다. 따라서, 복잡성을 줄이기 위해 Page 객체 대신 List 객체를 캐싱하는 것이 좋습니다.

  3. Page 캐싱 시 직렬화 방식 설정:
    Page 객체를 캐싱해야 한다면, 직렬화 시 GenericJackson2JsonRedisSerializer 같은 JSON 변환기를 통해 해결할 수 있습니다. 하지만 이는 JSON 설정의 세부 조율이 필요하며 여전히 문제를 완전히 해결하지 못할 수 있습니다.

추가 참고 자료

아래 링크들은 유사한 문제를 겪은 질문과 그에 대한 답변이며 도움이 되실 겁니다:

이해에 도움이 되었길 바랍니다. 질문자님의 이해를 돕고자 기존 답변을 참고하여 유사한 답변 링크를 추천해드렸습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

이수현님의 프로필 이미지
이수현

작성한 질문수

질문하기