<aside>
현재 진행중인 프로젝트의 서비스는 큐레이션을 제공하고 해당 큐레이션은 관리자가 생성 및 수정할 수 있다.
즉, 큐레이션 서비스는 실시간으로 변경되는 것이 아닌 관리자 주도로 업데이트 되기 때문에 캐시가 성능에 엄청난 이점을 가져다 줄 수 있다. 그렇다면 이때 어떤 과정을 통해서 캐시 성능을 높였는지 보자.
</aside>
<aside>
자주 업데이트하지 않는 데이터이기에 캐시를 사용한다면, 애초에 캐시된 데이터를 클라이언트 측에서 관리하는 것도 하나의 방안이 될 수 있다.
실제로 브라우저 캐시를 보면, 브라우저에 캐시된 정보가 있다면 이를 활용하기도 한다.
다만 중요한 점은 캐시가 변경되었는지 확인을 할 필요가 있다. 예를 들어 클라이언트가 캐시된 데이터를 가지고 있다고 해도 새로운 업데이트가 발생하면 이를 갱신해줘야 하는것이다.
그래서 캐시마다 버전 필드를 부여하고 이를 비교하는 방식으로 진행한다.
</aside>
<aside>
<aside>
응답 DTO를 기반으로 캐시가 적용되는 대상의 클래스를 보자.
기본적으로 categoryList의 길이는 4, 각 CategoryResponseDto는 4개의 PostResponseDto를 가진다. 또한 각 PostResponseDto는 title은 30글자 content는 300글자 정도를 가진다.
즉 이를 계산했을때 아래 표와 같은 결론이 나온다.
사용자 수 | 절약 데이터 | KB 환산 | MB 환산 |
---|---|---|---|
1명 | 6 566 바이트 | 6.42 KB | 0.0063 MB |
100명 | 656 600 바이트 | 641 KB | 0.63 MB |
10 000명 | 65 660 000 바이트 | 64 137 KB | 62.7 MB |
</aside> |
<aside>
/* 서브 아이템 캐시를 통해 조회 성능 개선 */
@Transactional(readOnly = true)
@Cacheable(
value = "subItemCache",
key = "'cached-sub-item-' + #type + '-' + #itemId",
sync = true
)
public ItemResponseDto getCachedItem(Integer type, Long itemId) {
return getItem(type, itemId);
}
</aside>
<aside>
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(7))
.serializeValuesWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer())
);
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
</aside>
<aside>
@Transactional(readOnly = true)
@CachePut(
value = "pageCache",
key = "'cached-page-' + #type + '-' + #period"
)
public PageResponseDto putCachedPage(Integer type, Integer period) {
BabyPage babyPage = getPage(type, period);
if (babyPage == null) {
return null;
}
if (babyPage.getType() == TYPE_PREGNANCY_GUIDE
|| babyPage.getType() == TYPE_CHILDCARE_GUIDE) {
List<CategoryResponseDto> categoryList = getPageItemWithPost(babyPage);
return new PageResponseDto(babyPage, categoryList);
}
if (babyPage.getType() == TYPE_CHILDCARE_NUTRITION
|| babyPage.getType() == TYPE_PREGNANCY_NUTRITION) {
List<CategoryResponseDto> categoryList = getPageItemWithNutrition(babyPage);
return new PageResponseDto(babyPage, categoryList);
}
List<CategoryResponseDto> categoryList = getPageItemWithInspection(babyPage);
return new PageResponseDto(babyPage, categoryList);
}
</aside>