문제 상황
@Cacheable(value = "books", key = "...")
public PagedResponse<BookResponseDto> findAllCached(...) {
return bookService.findAll(...);
}
PagedResponse<BookResponseDto> 와 같은 제네릭 타입으로 캐싱할 때
캐시에서 조회된 데이터가 LinkedHashMap으로 역직렬화되어 아래와 같은 오류가 발생
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class cohttp://m.example.book_api.global.dto.PagedResponse (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; cohttp://m.example.book_api.global.dto.PagedResponse is in unnamed module of loader 'app')
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.example.book_api.global.dto.PagedResponse (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.example.book_api.global.dto.PagedResponse is in unnamed module of loader 'app')
2. 원인 분석
- @Cacheable 내부에서 Jackson이 객체를 JSON으로 직렬화하고 역직렬화하는 과정에서 제네릭 타입 정보가 손실된다.
- Java의 타입 소거(Type Erasure) 특성 때문에 런타임에 제네릭 타입을 정확히 알 수 없어,
- 역직렬화 시 기본적으로 LinkedHashMap 타입으로 변환하게 된다.
3. 해결 방법
직접 캐시 로직 구현 및 TypeReference 사용
- 자동 캐시 대신 RedisTemplate 등으로 직접 캐시를 관리한다.
- ObjectMapper에 TypeReference를 명시해 정확한 타입으로 역직렬화한다.
// 역 직렬화 문제로 수동 캐싱
public PagedResponse<BookResponseDto> findAllCached(...) {
// key 조회
String key = ...;
Object cached = redisTemplate.opsForValue().get(key);
PagedResponse<BookResponseDto> cachedResponse = objectMapper.convertValue(
cached,
new TypeReference<PagedResponse<BookResponseDto>>() {}
);
// 저장된 캐시가 있으면, 캐시 값 출력
if (cachedResponse != null) {
...
return cachedResponse;
}
// 저장된 캐시가 없으면, DB 조회 + 캐시 생성
PagedResponse<BookResponseDto> result = bookService.findAll(...);
redisTemplate.opsForValue().set(key, result, 30, TimeUnit.MINUTES);
return result;
}
'Spring > 문제 해결 (Troubleshooting)' 카테고리의 다른 글
context-path와 Security: 예상과 다른 경로 매칭 문제 (0) | 2025.07.15 |
---|---|
@ControllerAdvice가 Filter 예외를 잡지 못하는 문제 해결 (0) | 2025.06.04 |
Spring Security 에러 핸들링 오류 해결, /error 접근 권한 문제 (0) | 2025.05.29 |
@LastModifiedDate 와 DB의 ON UPDATE CURRENT_TIMESTAMP 동시 사용 문제 (1) | 2025.05.23 |
JPA 변경사항이 즉시 반영되지 않을 때 - 영속성 컨텍스트와 DB 값 불일치 문제 (2) | 2025.05.23 |