DRF 내장 캐싱을 활용한 API 응답 캐싱 전략

API 성능 향상을 위해 Django의 캐시 프레임워크를 활용하여 반복적인 DB 조회와 직렬화 과정을 생략하고 저장된 응답을 재사용하는 전략

Django 캐시 프레임워크 설정

개발 환경 - LocMemCache

# settings/local.py
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "unique-snowflake",
    }
}

운영 환경 - Redis

# settings/production.py
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

View 단위 캐싱 (@cache_page)

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    @method_decorator(cache_page(60 * 10))  # 10분 캐싱
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

    @method_decorator(cache_page(60 * 60))  # 1시간 캐싱
    def retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

Vary 헤더를 이용한 조건부 캐싱

인증 상태별 캐시 분리

from django.views.decorators.vary import vary_on_headers

@method_decorator(cache_page(60 * 10))
@method_decorator(vary_on_headers("Authorization"))
def list(self, request, *args, **kwargs):
    return super().list(request, *args, **kwargs)

캐시 무효화 전략

전략
방법
장점
단점

시간 기반

timeout 설정

구현 간단

데이터 변경 시에도 timeout까지 낡은 정보 노출

이벤트 기반

Django Signals 활용

데이터 변경 시 즉시 캐시 삭제

@cache_page의 복잡한 캐시 키로 인해 삭제 어려움

캐싱 적용 지침

캐싱하면 좋은 경우

  • 자주 변경되지 않는 읽기 전용 API

  • DB 조회나 직렬화 비용이 높은 API

  • 공지사항, 상품 카테고리 등 정적 데이터

캐싱하지 말아야 할 경우

  • 데이터 변경이 매우 잦은 API

  • 쓰기(POST, PUT, PATCH, DELETE) 요청

  • 사용자별 민감한 정보를 다루는 API

캐시 백엔드 선택

백엔드
추천 용도

LocMemCache

로컬 개발, 단위 테스트

Redis

대부분의 운영 환경 (강력 추천)

Last updated