최근 api서버에 응답데이터를 cache를 이용해서 관리하였다. 캐시 기능을 구현하면서 추가적으로 고려해야했던 것과 부수적으로 구현한 기능을 정리해보자.
가장 큰 관점은 캐시에 저장한 데이터가 언제까지 유효한가? 이다. 해당 데이터가 수정되거나 다시 계산해야할 필요가 있으면 캐시데이터를 업데이트해야할 것이다. 내가 구현했던 기능에서의 고려했던 점은 다음과 같다.
2-1) 데이터를 업데이트할 때
해당 api는 DB에서 가져온 데이터를 계산해서 결과값을 요청 데이터에 따라 캐시에 저장하는 기능이였다. 따라서 DB의 데이터가 업데이트가 되면 결과값도 달라지기 때문에 캐시데이터도 업데이트해야할 필요성이 있다.
2-2) 새로운 데이터로 계산해야할 때
적용기간에 따라 계산해야할 데이터를 필터링한 후 계산을 했기 때문에 현재 시간에 따라 캐시데이터에 저장할 때는 유효하지 않았지만 시간이 지남에 따라 계산에 사용해야할 데이터가 있을 수 있다. 따라서 업데이트 해야할 시간을 데이터와 함께 저장해야했다.
2-3) 적용기간이 끝난 데이터가 있을때
반대로 시간이 지남에 따라 적용기간이 끝나서 계산에 사용하지 말아야할 데이터가 있을 수 도 있다. 따라서 2-2)에서 계산한 캐시업데이트시간과 현재 사용한 데이터 중에서 가장 빠른 종료시간과 비교해서 캐시업데이트시간을 업데이트하는 로직을 추가했다.
해당 코드의 로직을 정리하자면 다음과 같다.
def get_target_data_obj_dict_and_cache_update_date(product_): """해당 상품에 대한 적용 data 오브젝트들을 반환하는 함수 """ # 적용가능 설정에 따른 데이터 필터링 data_obj_list_by_period = Data.objects.filter(query) # 적용예정인 data들로부터 캐시업데이트시간 계산 now = timezone.now() cache_update_date = get_cache_update_date_from_future_data(data_obj_list_by_period, now) # 적용시작된 data 필터링 data_obj_list_by_start_date = filter_data_list_by_start_date(data_obj_list_by_product, now) # 유형별로 적용할 data 탐색 target_data_obj_dict = find_target_data_obj_by_data_type(data_obj_list_by_start_date, product_obj) # 적용할 data들의 종료시간으로부터 캐시업데이트시간 계산 cache_update_date = get_cache_update_date_from_data_end_date(target_data_obj_dict, cache_update_date) return target_data_obj_dict, cache_update_date
def get_target_data_data_with_cache(product_): """해당 상품에 대한 적용 data 조회 & 캐시화 함수 : 캐시식별자 - 상품번호 """ # 상품번호에 대한 적용 data 정보가 캐시에 있는지 확인 target_data_cache_id = '_'.join(['target_data',str(product_.product_no)]) target_data = cache.get(target_data_cache_id) now = timezone.now() # 적용 data 정보가 캐시에 없거나 업데이트 날짜가 지났으면 새롭게 적용혜택 조회 if (not target_data or (target_data["cache_update_date"] is not None and target_data["cache_update_date"] <= now)): target_data_obj_dict, cache_update_date = get_target_data_obj_dict_and_cache_update_date(product_) # 계산 로직 tartget_data = calculate_discount_price(target_data_obj_dict) target_data = { "target_data": tartget_data, "cache_update_date": cache_update_date, } cache.set(target_data_cache_id, target_data) return target_data