Web Cache, Caching, Cache Header
캐싱(Caching)이란?
나중에 있을 요청에 대해 빠르게 응답해주기 위해 응답 결과를 사전에 저장해두고 재사용하는 것을 캐싱이라고 합니다. 캐싱에는 다양한 종류가 있습니다.
크게는 어플리케이션 단 캐시와 메모리 단 캐시로 볼 수 있는데, 메모리 단 캐시는 우리가 흔히 아는 CPU에서 볼 수 있습니다. 주기억장치에서 저장된 데이터를 읽어올 때, 자주 사용하는 데이터를 캐시 메모리에 저장한 뒤, 다음에 이용할 때 주기억장치가 아닌 캐시 메모리에서 먼저 가져오면서 속도를 향상시킵니다.
그리고 어플리케이션 캐시 중 하나인 웹 캐싱은 네트워크 트래픽을 최소화하기 위해서 설계된 HTTP 프로토콜의 기능 중 하나입니다. 웹 캐싱은 특정 조건으로 들어오는 HTTP 요청에 대해 HTTP 응답을 캐싱해서 매번 반복되어 들어오는 요청에 대해 웹서버에 처음부터 다시 요청을 할 필요없도록 사용자에게 바로 응답해줄 수 있습니다.
장점
캐싱은 콘텐츠 소비자 그리고 제공자 모두에게 도움을 줄 수 있습니다.
- 네트워크 비용 감소 : 만약 사용자(콘텐츠 소비자)와 웹서버(콘텐츠 제공자) 간의 네트워크 경로 상 거리가 멀 경우에 중간에 캐시서버가 있어 컨텐츠가 사용자와 가까운 경로 상에 캐시되어 있을 경우에 추가적인 네트워크 간의 이동이 필요하지 않게 됩니다.
- 응답이 빠름 : 캐싱은 콘텐츠를 더 빠르게 응답 받게 할 수 있습니다. 만약 캐시가 네트워크 경로 상 사용자에게 더 가까운 곳에 있다면 훨씬 빠르게 사용자에게 응답해줄 수 있습니다. 예를 들어 캐시가 웹 브라우저에 저장되어 있는 경우라면 즉시 응답이 가능한 상황이 되겠죠.
- 가용성 : 가끔 서버에 요청을 했을 때 응답하지 못하는 경우도 있습니다. 예를 들어 서버가 죽었거나, 네트워크 상황이 좋지 못한 경우죠. 이런 경우에 캐시를 사용하게 되면, 사용자에게 캐싱되어 있는 데이터에는 바로 응답을 해주어 서비스 가용성을 보장시켜주게 됩니다.
다양한 장점이 있겠지만, 일반적으로 캐시를 사용함으로써 얻는 장점은 위와 같습니다.
어떤 걸 캐시할 수 있나요?
일반적으로 웹에서는 아래와 같은 항목들을 주로 캐싱합니다.
- 로고나 대표 이미지
- 고정된 이미지(네비게이션 아이콘이나 메뉴바 아이콘 같은)
- 스타일시트(CSS)
- javascript 파일들
- 다운로드 가능한 파일들
- 미디어 파일들
보통 위 파일들의 경우에는 잘 변하지 않기 때문에 캐싱하기 좋은 데이터들입니다.
반면에 아래와 같은 항목들은 캐시할 때 주의해야될 필요가 있습니다.
- HTML 페이지들
- 동적인 이미지들
- 자주 수정되는 javascript 나 CSS 파일들
- 쿠키 인증이 반드시 있어야지 요청 가능한 컨텐츠들
그리고 아래 사항들은 거의 캐시하지 않는 경우라고 봐도 됩니다.
- 주요 민감 정보들(은행 정보, 개인 정보 등)
- 사용자에 따라 다르게 출력되는 컨텐츠나 자주 변경되는 요소들
물론 일반적인 경우라면 위와 같은 정책으로 캐싱하겠지만, 상황에 따라서 서버 관리자가 캐싱 정책을 설정하여 커스터마이징할 수 있습니다. 예를 들어 모든 인증된 사용자가 똑같은 페이지를 사이트에서 봐야한다면, 해당 페이지를 캐싱해도 되는 것과 같이 말이죠. 또 만약 사용자의 개인 민감 정보라고 하더라도 사용자가 원한다면 한동안은 캐시되게 할 수도 있겠죠.
웹 콘텐츠들은 어디에 캐싱될까요?
어디에서 캐시를 받아서 처리하냐에 따라 다양한 곳에 캐싱될 수 있습니다. 저는 일단 아래와 같이 두가지로 나눠보았습니다.
- 웹 브라우저 캐시 : 웹 브라우저들은 자체적으로 캐시를 작게나마 가지고 있습니다. 일반적으로 브라우저들은 판단하기에 제일 중요하다고 생각되는 정보들을 캐싱합니다. 아마 사용자 개발 정보라거나 다시 요청하여 다운로드하기에는 비용이 클 것 같은 데이터들이 이에 해당할 겁니다.
- 캐시 리버스 프록시 : 웹 서버의 백엔드 단에서 자체적으로 캐시 기능을 제공하는 것을 의미합니다. 이를 사용하면 특정 요청을 처리할 때 백엔드에 있는 서버나 데이터베이스에 직접 닿을 필요없이 바로 응답해줄 수 있겠습니다.
주요 캐시 헤더
HTTP 헤더에서 볼 수 있는 캐시 관련 헤더는 어떤 것이 있을지 알아보면서 간단하게 정리해보았습니다.
- Expires : Expires 헤더는 말그대로 콘텐츠가 언제 만료될 것인지 날짜와 시간을 나타냅니다. (Cache-Control 헤더에서 max-age 또는 s-max-age 디렉티브를 지니면 Expires 헤더는 무시됩니다.)
- Etag : HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그입니다. 같은 주소의 자원이더라도 컨텐츠가 달라졌다면 ETag가 다릅니다. 예를 들어 GET 메소드로 domdom.tistory.com의 응답 본문이 “안녕 돔돔아”이고 ETag 값이 asdf1234 라고 합니다. 만약 서버의 응답 본문이 동일하다면 매번 위 컨텐츠로 요청할 때마다 ETag는 동일할 것입니다. 그런데 컨텐츠가 “안녕 돔돔아” 에서 “안녕 돔돔이야”로 바뀌었다면 ETag 헤더 값도 qwer4321로 바뀝니다. 그러면 서버가 클라이언트의 응답 내용이 달라졌구나를 깨닫게 되어 캐시를 지우고 새로 컨텐츠를 내려받을 수 있게 됩니다.
- If-None-Match : 서버 보고 ETag가 달라졌는지 검사해서 ETag가 다를 경우에만 컨텐츠를 새로 내려주라는 뜻입니다. 만약 ETag가 같다면 서버는 304 Not Modified 를 응답해서 캐시를 그대로 사용하게 됩니다.
- Last-Modified : 해당 응답의 서버가 알고 있는 가장 마지막으로 수정된 날짜와 시간을 담고 있습니다. 이는 저장된 요소가 이전과 같은지 유효성을 검토하는 데 사용됩니다. Etag 헤더보다는 덜 정확하지만, 대비책으로 사용된다고 합니다.
- Content-Length : 캐싱 자체에는 속하지 않는 헤더긴 하지만, 본 헤더는 캐싱 정책을 정의하는데 있어서 정말 중요한 헤더라고 합니다. 캐시되는 내용의 길이가 정확하지 않으면 소프트웨어에서 캐시하지 않기 때문입니다.
- Age : 이 헤더는 캐시 응답 때 나타나는데, max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려줍니다. 만약 max-age 값이 3600으로 설정된 경우에 1분이 지났다면 Age : 60 으로 응답 헤더에 포함될 것입니다.
- Vary : 캐시된 entity가 다중 자원을 가지고 있으므로 요청한 헤더를 지정한 목록이 상황에 따라 변할 수 있다는 것을 지정합니다. 여러 개의 헤더는 콤마(,)로 구분하여 나열합니다. ex) Vary : User-Agent 위 예와 같이 헤더를 사용할 경우에는 캐싱 서버는 캐시된 페이지를 응답할지 여부를 User-Agent 로 고려하게 됩니다. 예를 들어, 모바일 유저에게 다른 컨텐츠를 제공해야 할 경우, 모바일 유저에게 데스크탑 유저를 위한 캐시 컨텐츠가 제공되는 것을 피할 수 있습니다.
- Cache-Control : 이 헤더는 Expires 헤더를 대체하는 좀 더 최신의 헤더입니다. 또 이 헤더에는 다양한 옵션들이 있는데 아래와 같습니다.
- no-cache : 캐시된 복사본을 사용자에게 보여주기 이전에, 재검증을 위한 요청을 원 서버로 보내도록 강제합니다.
- no-store : 캐시 하지 않습니다.
- max-age = seconds : seconds에 지정한 것보다 오래된 entry는 캐시하지 않습니다.
- max-stale [=seconds] : 만료된 데이터를 보낸다. 만약 seconds 가 지정되어 있다면 지정한 숫자보다 적은 만료된 데이터를 보냅니다.
- min-fresh [=seconds] : 명시된 seconds 의 수 이후의 변경된 새 데이터만 보냅니다.
- only-if-cached : 새로운 데이터를 검색하지 않고 캐시에 있는 데이터만 반환합니다.
- public : 응답이 어떤 캐시에 의해서든 캐시된다는 것을 나타냅니다.
- private : 응답이 단일 사용자를 위한 것이며 공유 캐시에 의해 저장되지 않아야 한다는 것을 나타냅니다. 사설 캐시는 응답을 저장할 수도 있습니다.
- no-transform : 데이터를 변환하지 않습니다.
- must-revalidate : 클라이언트는 데이터를 재확인 해야 합니다.
- proxy-revalidate : 개인적인 클라이언트 캐시를 제외하고 데이터를 재확인 해야합니다.
참고문헌
https://www.zerocho.com/category/HTTP/post/5b594dd3c06fa2001b89feb9
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Cache-Control
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Vary