Django 성능 최적화: 캐싱 - (2)

구경회·2021년 8월 5일
2

Django-Caching

목록 보기
2/2
post-thumbnail

장고와 연결

우선 django-redis라는 라이브러리를 통해 연결할 수 있다. 기본적으로 장고에서 backend가 내장되어있는 memcached등과는 달리 서드파트 라이브러리를 이용해야 한다.

python -m pip install django-redis

위와 같이 라이브러리를 설치해주자.

settings/dev.py등 연결이 필요한 부분에 다음과 같이 연결해주면 된다.

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://<hostname>:<port>/<db_num>",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

캐시 키 관리

하드코딩

캐시는 와 그에 해당하는 으로 이루어진다. 전형적인 캐시의 이용 패턴은 다음과 같다.

def cached_scraps(self):
    data = cache.get(f"posts/{self.id}/scraps")
    if data is not None:
        return data
    else:
        qs = Scrap.objects.filter(post_id=self.id).values_list("user_id", flat=True)
        cache.set(f"posts/{self.id}/scraps", qs)
        return qs

위와 같이 하드코딩해서 키를 관리할 수도 있다. 프로젝트의 복잡성이 높지 않다면 나쁘지 않다. 하지만 프로젝트가 거대해지고 같은 키를 공유하는 경우가 많아질수록 유지보수에 곤란함이 많아진다. 그래서 추천하는 방법은 다음과 같다.

파일로 관리

필자는 redis_key_schema.py 라는 파일을 앱 별로 만들어 활용하는 것을 추천한다. 차후에 key의 형태를 바꿀 때도 편리하고 여러모로 편리하다.

def info_list(user):
    """
    format: `<username>:info-list
    """
    return f"{user}:info-list"


def board_list(user):
    """
    format: `<username>:board-list
    """
    return f"{user}:board-list"

이런 식으로 활용한다. 코드에서는 위의 하드코딩된 버전과 유사하지만

def list(self, request, *args, **kwargs):
    key = redis_key_schema.board_list(request.user)
    data = cache.get(key)

    if data:
        return Response(data)
    else:
        data = self.get_serializer(self.get_queryset(), many=True).data
        cache.set(key, data)
        return Response(data)

이렇게 redis_key_schema에서 불러와 활용한다. 다음과 같이 has_key 메소드를 활용할 수도 있다.

def list(self, request, *args, **kwargs):
    key = redis_key_schema.board_list(request.user)
    
    if cache.has_key(key):
        return Response(cache.get(key))
    else:
        data = self.get_serializer(self.get_queryset(), many=True).data
        cache.set(key, data)
        return Response(data)

삭제와 업데이트

시간에 따른 만료

일반적으로 cacheTTL(Time To Live) 설정을 통해 관리한다. 해당 시간이 지난 후에 만료시키는 방식이다. 앞선 세팅에서 timeout의 값을 바꾸어서 관리할 수도 있지만 캐시를 set 해 줄 때에 설정할 수도 있다. 다음과 같은 방식이다.

cache.set(key, value, timeout=60 * 60)

위와 같이 각 키와 값 쌍마다 명시적으로 timeout을 줄 수도 있다.

강제 만료

캐시를 제대로 지우는 것은 캐시는 제대로 얻어오는 것만큼이나 중요하다. 적절한 시기에 업데이트가 이루어지지 않는다면 유저는 자신의 액션이 제대로 서버에 반영되지 않는다고 느낄 것이기 때문이다. 따라서 updatecreate 등의 액션이 이루어질 때 다음과 같이 캐시를 제대로 지우는 것 또한 중요하다.

cache.delete(redis_key_schema.post(post_pk))
profile
즐기는 거야

0개의 댓글