Spring | Redis로 Page 캐시 처리하기

바다·2024년 8월 31일
1

Spring

목록 보기
13/13
post-thumbnail

Redis Cache 처리 시 주의점

1. 기본 생성자가 있어야 한다

1) 캐시처리를 적용할 메소드의 반환 class에 기본 생성자가 있어야 함
2) Dto에는 @NoArgsConstructor 붙여 주어야 함
3) Page는 기본 생성자가 없음…

2. Serializer, Deserializer 적용

RedisCacheConfig 설정에 적용

@Configuration
@EnableCaching
public class RedisCacheConfig {
	@Bean
	public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
		
		RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
			.entryTtl(Duration.ofHours(1))
			.disableCachingNullValues()
			.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
			.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
		
		return RedisCacheManager.RedisCacheManagerBuilder
			.fromConnectionFactory(connectionFactory)
			.cacheDefaults(cacheConfiguration)
			.build();
	}
}

❗Page <'T'> 의 기본생성자가 없는 문제 해결하기

👉 PageImpl<'T'>을 상속 받은 RestPage<'T'> 라는 Wrapper class를 적용

  @JsonIgnoreProperties(ignoreUnknown = true, value = {"pageable"})
public class RestPage<T> extends PageImpl<T> {
	
	@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
	public RestPage(@JsonProperty("content") java.util.List<T> content,
					@JsonProperty("number") int page,
					@JsonProperty("size") int size,
					@JsonProperty("totalElements") long totalElements) {
		
		super(content, PageRequest.of(page, size), totalElements);
	}
	
	public RestPage(Page<T> page) {
		super(page.getContent(), page.getPageable(), page.getTotalElements());
	}
	
	public RestPage(List<T> content, Pageable pageable, Long total) {
		super(content, pageable, total);
	}
}

기존 코드

public Page<ReservationResponseDto> findReservations(Pageable pageable, String status, User user) {
		ReservationStatus reservationStatus = ReservationStatus.valueOf(status.toUpperCase());
		Page<Reservation> reservationPage = reservationRepository.findByUserIdAndStatus(user.getId(), reservationStatus, pageable);
		validatePageableWithPage(pageable, reservationPage);
		
		return reservationPage**.map(r -> ReservationResponseDto.of(r, r.getSlot()));
}

변경된 코드

@Cacheable(value = "reservations", key = "#user.id + ':' + #status + ':' + #pageable.pageNumber")
public RestPage<ReservationResponseDto> findReservations(Pageable pageable, String status, User user) {
		ReservationStatus reservationStatus = ReservationStatus.valueOf(status.toUpperCase());
		Page<Reservation> reservationPage = reservationRepository.findByUserIdAndStatus(user.getId(), reservationStatus, pageable);
		validatePageableWithPage(pageable, reservationPage);
		
		return new RestPage<>(reservationPage.map(r -> ReservationResponseDto.of(r, r.getSlot())));
}

참고

profile
ᴘʜɪʟɪᴘᴘɪᴀɴs 3:14

0개의 댓글