전산학에서 캐싱은 아주 자연스러운 개념이다.
cpu를 예로 들어 생각해보자. 상대적으로 자주 쓰는 것들을 다른 저장장치가 아니라 속도가 빠르고 가까이 있는 캐시에 둠으로써 성능 향상을 꾀할 수 있다. 똑같은 일을 웹에서도 진행할 수 있다.
웹 서버에서는 일반적으로 램처럼 빠르게 접근할 수 있는 곳에 적절한 데이터를 두어 상대적으로 훨씬 느린 DB등의 액세스를 최소화하는데 있다. 우선 클라이언트에서의 캐싱에 대해 가볍게 알아본 후 장고에서 캐싱에 대해 알아보자.
일반적으로 클라이언트 사이드에서 캐싱을 하기 위해 서버는 알맞은 HTTP 헤더 값을 내려준다.
Cache-Control: max-age=31536000
위와 같은 헤더를 통해 아주 긴 시간 동안 클라이언트 사이드에서 캐싱을 해야한다는 정보를 줄 수 있다. 위 max-age
는 Expires
보다 우선한다.
Cache-Control: private
Cache-Control: public
위와 같이 private
이나 public
디렉티브를 주어 단일 사용자를 위한 캐시인지 아닌지를 알려줄 수도 있다.
서버사이드에서는 보통 Redis
나 Memchached
등의 라이브러리를 이용하여 메모리 상에 주요 데이터를 올려놓고 이용한다. 캐싱을 하지 않는 것은 MS의 가이드에 따르면 안티 패턴으로 간주될 정도인데, 캐싱이 그만큼 중요하다는 것을 드러낸다.
여러가지 대안이 있지만, 이 글에서는 캐싱을 위해 Redis
를 선택하도록 하자. 기본적인 캐시로서의 기능 이외에도 메세지 큐로서 활용할 수도 있고 영속성을 지닌 저장소로 이용할 수도 있다.
docker
를 이용해 설치하고 실행해보자. docker
의 설치는 다음 글을 참고하라.
그 다음 터미널에서 다음과 같이 입력하자. 맥은 docker engine을 실행시켜야 한다.
docker run -p 3000:3000 redis
위 사진과 같이 redis가 실행되었다는 알림이 나올 것이다. 이제 redis-cli
를 설치해서 redis를 제어해보자. redis
의 실행은 도커에 맡겨 두었기 때문에 로컬에는 Redis-cli
만 설치해도 무방하다.
물론 컨테이너 내부로 들어가서 실행할 수도 있지만, 로컬 환경에서 서버에 있는 레디스를 사용하고 싶은 경우도 있을 수 있기 때문에 툴을 설치하는 것이 편리하다.
우분투의 경우 다음과 같이 입력하여 설치하자.
sudo apt-get install redis-tools
다음과 같이 입력해 잘 실행되고 있는지 확인하자.
redis-cli ping
위와 같이 입력이 오면 Redis가 잘 동작하고 있음을 알 수 있다.
위와 같은 에러가 발생할 수 있다. 말 그대로 localhost에서 레디스가 동작하지 않고 있다는 것인데, docker run
을 제대로 실행했다면 포트를 제대로 연결해주지 않아서 그럴 수 있다. docker run -p 6379:6379 redis
에서 -p 6379(local pc):6379(container)
는 나의 6379번 포트에 컨테이너의 6379번 포트를 연결하란 뜻이다. 위 포트 설정을 제대로 했는지 확인해보자.
실제로 레디스를 운영하며 다음과 같은 에러를 자주 만났다.
(error) MISCONF Redis is configured to save RDB snapshots,
but is currently not able to persist on disk.
앞서 말했듯, 레디스는 in-memory 저장소의 문제점을 해결하기 위해 자신의 키와 값을 디스크에 저장해두려고 한다. 하지만 어떤 이유로 인해 이 과정이 실패하면 다른 쓰기 요청을 거부하게 된다. 스냅샷을 찍는게 필요하지 않기 때문에 다음과 같이 입력하자. redis-cli
에서 다음과 같이 입력하자.
config set stop-writes-on-bgsave-error no
위와 같이 입력함으로서 문제를 해결할 수 있다. 좀 더 근본적인 해결책으로는 스냅샷 옵션을 끄거나 저장 공간의 크기를 늘려주는 방식도 있다.
레디스는 싱글 스레드로 동작한다. 그래서 뭐 어떡하라고? 오래 걸리는 명령어는 지양해야한다. 캐시는 O(1)으로 동작하는게 아닌가 싶을 수도 있지만, KEYS
나 FLUSHALL
같은 명령어는 O(N)
의 시간 복잡도를 가진다. 즉, 테이블 전체를 훑어야 하는 명령어는 자제해야 한다.
이제 다음 글에서는 본격적으로 장고와 연동을 하고 우아하게 캐시를 관리하는 법을 알아보자.