웹 서버는 사용자가 웹 페이지를 요청할 때마다 데이터베이스 쿼리부터 비즈니스 로직, 템플릿 렌더링, 비즈니스 로직에 이르기까지 모든 종류의 계산을 수행해 웹 사이트 방문자가 볼 수 있는 웹 페이지를 만듦
만약 중간 규모 이상의 트래픽이 많은 웹 사이트의 경우, 가능한 많은 오버헤드를 줄이는 것이 필수임
이러한 문제를 해결하는 방법 중 하나로 캐시(Cache)를 사용할 수 있음
- 동적으로 생성된 웹 페이지에서 캐시가 작동하는 의사코드
given a URL, try finding that page in the cache
if the page is in the cache:
return the cached page
else :
generate the page
save the generated page in the cache (for next time)
return the generated page
Django는 동적 웹 페이지를 저장할 수 있는 캐시 시스템이 있기 때문에 각 요청을 계산할 필요 없고, 다른 수준의 캐시 세분성을 제공함
- 특정 뷰의 결과물을 캐싱
- 제작하기 어려운 부분만 캐싱
- 전체 웹 사이트를 캐싱
Django는 Squid 및 웹 브라우저 기반 캐시와 같은 다운 스트림 캐시에서도 잘 작동함
- 웹 사이트의 어느 부분이 캐시돼야 하는지와 캐시 방법에 대한 힌트(HTTP 헤더를 통해)를 제공할 수 있는 캐시 유형
캐시 설정
캐시 시스템은 캐시된 데이터가 어디에 있어야 하는지(파일 시스템, 데이터베이스, 직접 메모리 등)를 명시에줘야 함
- 캐시 성능에 영향을 미치는 중요한 결정임
- 캐시 환경 설정은 설정 파일의 캐시 설정에 있음
Memcached
memcached - a distributed memory object caching system
What is Memcached? Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. Memcached is an in-memory key-value store for s
memcached.org
- Django가 기본으로 지원하는 가장 빠르고 효율적인 캐시 유형
- 메모리 기반 캐시 서버
- 사용방법
- Memcached를 설치하고 Memcached 바인딩(pythonmemcached or pylibmc)을 설치해야 함
- Django의 캐시 설정을 다음과 같이함
# python-memcached
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.memcached.MemcachedCache'
# ip:port or unix:path
'LOCATION' : '127.0.0.1:11211' # ip:port
# ip는 Memcached 데몬ip 주소, port는 Memcached가 실행되는 포트 또는 unix:path 값
#'LOCATION': 'unix:/tmp/memcached.sock' unix:path
# path는 Memcached Unix 소켓 파일 경로
}
}
# pylibmc
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.memcached.PylibMCCache'
'LOCATION' : '127.0.0.1:11211'
}
}
# 여러 서버에서 캐시를 공유
# 프로그램은 각 세스템의 캐시 값을 복제하지 않고 컴퓨터 그룹을 단일 캐시로 처리
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.memcached.PylibMCCache'
'LOCATION' : [
'172.19.26.240:11211',
'172.19.26.242:11212',
'172.19.26.244:11213'
]
}
}
- Memcached은 메모리 기반 캐싱 방식이기 때문에 서버가 충돌하면 데이터가 손실됨
- 캐시 저장소는 데이터의 영구적인 저장을 위한 것이 아님
Redis(Django 4.0 부터 추가) 캐싱
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
데이터베이스 캐싱
- Django는 캐시된 데이터를 데이터베이스에 저장할 수 있음
- 빠르게 잘 색인된 데이터베이스 서버를 갖고 있다면 가장 잘 작동
- 사용방법(캐시 테이블 이름 : cache_table)
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.db.DatabaseCache'
'LOCATION' : 'cache_table'
}
}
- 먼저 데이터베이스 캐시를 사용하기 전에 다음과 같은 명령으로 캐시 테이블을 만들어야함, 이름은 LOCATION 설정에서 가져옴
python manage.py createcachetable
- 기존 테이블을 건드리지 않고, 누락된 테이블만 생성
여러 데이터베이스
- 여러 데이터베이스에서 캐싱을 사용하는 경우 테이블에 대한 라우팅 지침도 설정해야함
- 예시 : 라우터는 모든 캐시 읽기 작업을 cache_replica로 지시, cache_primary로 모든 쓰기를 보내고 캐시 테이블은 cache_primary에만 동기화됨
class CacheRouter:
"""A router to control all database cache operations"""
def db_for_read(self, model, **hints):
# 모든 캐시 일기 작은 복제본으로 이동
if model._meta.app_label == 'django_cache':
return 'cache_replica'
return None
def db_for_write(self, model, **hints):
# 모든 캐시 쓰기 작업은 기본으로 이동
if model._meta.app_label == 'django_cache':
return 'cache_primary'
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
# 기본 캐시 모델만 설치
if app_label == 'django_cache':
return db == 'cache_primary'
return None
- 데이터베이스 캐시 모델에 대한 라우팅 방향을 지정하지 않으면 캐시 백엔드가 default 데이터베이스 사용함
파일 시스템 캐싱
- 파일 기반 백엔드는 각 캐시 값을 직렬화해 개별 파일로 저장
- 사용방법
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.filebased.FileBasedCache'
'LOCATION' : '/var/tmp/django_cache', # 윈도우의 경우 'c:/foo/bar'
}
}
- LOCATION을 적절한 디렉터리에 설정, 디렉터리 경로는 절대경로
- 디렉터리를 웹 서버가 실행되는 시스템 사용자가 읽고 쓸 수 있는지 확이해야 함
로컬-메모리 캐싱
- 설정 파일에 다른 캐시가 지정돼 있지 않으면 로컬-메모리 캐싱이 기본 캐시임
- 사용방법
CACHES = {
'default':{
'BACKEND' : 'django.core.cache.backends.locmem.LocMemCache'
'LOCATION' : 'unique-snowflake'
}
}
- LOCATION은 개별 메모리 저장소를 식별하는 데 사용
- 하나의 locemem 캐시만 있으면 LOCATION 생략 가능, 둘 이상의 로컬 메모리 캐시가 있는 경우
더미 캐싱(개발용)
- 실제로 캐시되지 않는 더미 캐시, 아무것도 하지 않고 캐시 인터페이스 만 구현
- 개발/테스트 환경에 유용
- 사용방법
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
커스텀 캐시 백엔드 사용하기
- 사용자 정의 캐시 백엔드를 사용할 경우
- 사용방법
CACHES = {
'default': {
'BACKEND': 'path.to.backend',
}
}
CACHE 설정의 인수
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
- 예시
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
'TIMEOUT': 60,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
사이트별 캐시
캐시가 설정되면 캐싱을 사용하는 가장 간단한 방법은 전체 사이트를 캐시하는 것임
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
뷰별 캐시
캐싱 프레임워크를 사용하는 좀 더 세밀한 방법은 개별 뷰의 출력을 캐싱하는 것
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
URLconf에 per-view 캐시 지정하기
뷰별 캐시에서는 뷰가 캐시 된다는 사실을 하드코딩했음
이런 접근법은 캐시 시스템에 뷰를 연결하기 때문에 여러가지 이유로 이상적이지 않음
- 캐시 기능이 없는 다른 웹 사이트에서 뷰 기능을 재사용하거나 캐시하지 않고 뷰 기능을 사용하고자 하는 사람들에게 뷰 기능을 배포 할 수 있음
이러한 문제들을 해결하는 방법으로 URLconf에 뷰 단위 캐시를 지정하는 방법임
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
템플릿 조각 캐싱
더 많은 제어를 원하는 경우, 캐시 템플릿 태그를 사용해 템플릿 조각을 캐시할 수 있음
- {% load cache %} : 템플릿에 이 태그에 대한 액세스 권한을 부여, 템플릿에 맨 위에 둬야함
- {% cache %} ~ {% endcache %} : 주어진 시간 동안 블록 내용을 캐시
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
저수준 캐시 API
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
다운스트림 캐시
요청이 웹 사이트에 도착하기 전에도 사용자를 위해 웹 페이지를 캐시하는 시스템
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
다양한 헤더(Vary 헤더)
Vary 헤더는 캐시 키를 작성할 때 캐시 메커니즘이 고려해야 하는 요청 헤더를 정의
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
캐시 제어 : 다른 헤더 사용
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
'Back-end & Server > Django' 카테고리의 다른 글
[Django] 보안 (0) | 2023.02.06 |
---|---|
[Django] 미들웨어(Middleware) (0) | 2023.02.06 |
[Django] 비 HTML 콘텐츠와 세션 (0) | 2023.02.01 |
[Django] 배포 (0) | 2023.01.31 |
[Django] 테스팅 (0) | 2023.01.22 |