HTTP Caching

TwentyFiveSeven·2021년 4월 13일
1

Cache란 ?

AWS에서 정의하는 Cache를 설명해보겠습니다.

  • 컴퓨팅에서 캐시는 일반적으로 일시적인 특징이 있는 데이터 하위 집합을 저장하는 고속 데이터 스토리지 계층입니다. 따라서 이후에 해당 데이터에 대한 요청이 있을 경우 데이터의 기본 스토리지 위치에 액세스할 때보다 더 빠르게 요청을 처리할 수 있습니다. 캐싱을 사용하면 이전에 검색하거나 계산한 데이터를 효율적으로 재사용할 수 있습니다.

  • 캐시의 데이터는 일반적으로 RAM(Random Access Memory)과 같이 빠르게 액세스할 수 있는 하드웨어에 저장되며, 소프트웨어 구성 요소와 함께 사용될 수도 있습니다. 캐시의 주요 목적은 더 느린 기본 스토리지 계층에 액세스해야 하는 필요를 줄임으로써 데이터 검색 성능을 높이는 것입니다.

  • 속도를 위해 용량을 절충하는 캐시는 일반적으로 데이터의 하위 집합을 일시적으로 저장합니다. 보통 완전하고 영구적인 데이터가 있는 데이터베이스와는 대조적입니다.

  • 캐싱(Caching)은 애플리케이션의 처리 속도를 높여줍니다.

  • 이미 가져온 데이터나 계산된 결과값의 복사본을 저장함으로써 처리 속도를 향상시키며, 이를 통해 향후 요청을 더 빠르게 처리할 수 있습니다.

  • 대부분의 프로그램이 동일한 데이터나 명령어에 반복해서 엑세스하기 때문에 캐싱은 효율적인 아키텍처 패턴입니다.

Web Cache란?

  • Web Cache란 client가 요청하는 자원을 첫 요청 시에 파일을 내려받아 특정 위치에 복사본을 저장하고, 이후 동일한 URL의 Resource요청을 한다면 내부에 저장한 파일을 사용하여 더 빠르게 서비스하기 위한 것입니다.
  • 서버를 통해 내려 받는 양이 적어지니 응답 시간이 감소하고 네트워크 트레픽이 감소되니 server와 client 모두가 win-win할 수 있는 최고의 tradeoff 인 셈입니다.

Web Cache의 종류

웹 캐쉬의 종류는 어디에 적용하느냐에 따라 다음과 같이 나뉠 수 있으며 이중 중점적으로 볼 내용은 Browser Cache입니다.


1. Browser Caches(사설 브라우저 캐시)

  • 브라우저 또는 HTTP요청을 하는 Client Application에 의해 다운로드된 모든 문서들을 내부 디스크에 캐쉬
  • Cache된 Resource를 공유하지 않는 한 개인에 한정된 Cache
  • 이 캐시는 서버에 대한 추가적인 요청 없이 뒤로 가기나 앞으로 가기, 저장, 소스로 보기 등을 위해 방문했던 문서들을 사용할 수 있도록 해 줍니다.
  • 유사한 방법으로 캐시된 컨텐츠의 오프라인 브라우징을 개선시킵니다.


2. Proxy Caches(공유 프록시 캐시)

  • Browser Cache와 동일한 원리로 동작하며 Client나 Server가아닌 네트워크 상에서 동작.
  • 공유 캐시는 한 명 이상의 사용자에 의해 재사용되는 응답을 저장하는 캐시입니다.
    • 예를 들어, 당신의 회사의 ISP는 많은 사용자들을 서비스하기 위해 지역 네트워크 기반의 일부분으로서 웹 프록시를 설치해뒀을 수도 있는데, 그 덕분에 조회가 많이 되는 리소스들은 몇 번이고 재사용되어 네트워크 트래픽과 레이턴시를 줄여줍니다.
  • 큰회사나 IPS의 방화벽에 설치 되며 대기시간 & 트래픽 감소, 접근정책 & 제한 우회, 사용률 기록등 수행
  • 한정된 수의 클라이언트을 위하여 무한대의 웹서버의 컨텐츠를 캐쉬


3. Gateway Caches (REVERSE OR SURROGATE PROXY)

  • 서버 앞 단에 설치되어 요청에 대한 캐쉬 및 효율적인 분배를 통해 가용성, 신뢰성, 성능등을 향상
  • Encryption / SSL acceleration, Load balancing, Serve/cache static content, Compression등을 수행
  • 무한대의 클라이언트들에게 한정된 수(또는 하나)의 웹서버 컨텐츠를 제공


Cache-Control

Cache-Control 일반 헤더 필드는 요청과 응답 내의 캐싱 메커니즘을 위한 디렉티브를 정하기 위해 사용됩니다. 캐싱 디렉티브는 단방향성이며, 이는 Request 내에 주어진 디렉티브가 Response 내에 주어진 디렉티브와 동일하다는 것을 뜻하지는 않는다는 것을 의미합니다.

Cacheability

  • public
    • 응답이 일반적으로 캐시 불가능한 상태에도 캐시에 저장 될 수 있습니다.
  • private
    • 응답이 단일 사용자를 위한 것이며 공유 캐시에 의해 저장되지 않아야 한다는 것을 나타냅니다.
    • 사설 캐시는 응답을 저장할 수도 있습니다.
  • no-store
    • 캐시는 클라이언트 요청 혹은 서버 응답에 관해서 어떤 것도 저장해서는 안됩니다.
  • no-cache
    • 캐시된 복사본을 사용자에게 보여주기 이전에, 항상 재검증을 위한 요청을 서버로 보내도록 강제합니다.
  • only-if-cached
    • 새로운 데이터를 내려받지 않음을 나타냅니다. 클라이언트는 캐시된 응답만을 원하며, 더 최신 복사본이 존재하는지를 알아보기 위해 서버에 요청해선 안됩니다.

Expire

  • max-age: seconds
    • 리소스가 최신 상태라고 판단할 최대 시간을 지정합니다. Expires에 반해, 이 디렉티브는 요청 시간과 관련이 있습니다.
  • stale-while-revalidate: seconds
    • 클라이언트가 오래된 응답을 수락하는 동안 백그라운드에서 새로운 응답을 비동기 적으로 확인 함을 나타냅니다.
    • seconds 값은 클라이언트가 Stale Response를 수락하는 시간을 나타냅니다.
  • stale-if-error: seconds
    • 새로운 응답에 대한 검사가 실패하면 클라이언트가 Stale Response를 사용한 다는 것을 나타냅니다.
    • seconds 값은 클라이언트가 expire time 이후 Stale Response를 수락하는 시간을 나타냅니다.

Revalidation and reloading

  • must-revalidate
    • 캐시는 사용하기 이전에 기존 리소스의 상태를 반드시 확인해야 하며 만료된 리소스는 사용되어서는 안됩니다.
  • proxy-revalidate
    • must-revalidate와 동일하지만, (프록시와 같은)공유 캐시에만 적용되며 사설 캐시에 의해서는 무시됩니다.
  • immutable
    • 시간이 지나도 Response Body가 변경되지 않음을 나타냅니다.
    • 만료되지 않은 리소스는 서버에서 변경되지 않으므로 클라이언트는 사용자가 명시적으로 페이지를 새로 고친 경우에도 업데이트를 확인하기 위해 조건부 재 검증 (ex : If-None-Match 또는 If-Modified-Since)을 보내서는 안됩니다.


## 유효성(Freshness)
  • 리소스가 캐시 내에 저장되고 나면, 이론적으로는 영원히 캐시에 의해 서비스될 수도 있지만, 캐시는 유한한 저장 공간을 가지므로 아이템들은 주기적으로 스토리지에서 제거됩니다. 이런 과정을 캐시 축출(cache eviction)이라고 부릅니다.

  • 반면 어떤 리소스들은 서버 상에서 변경될 수 있고, 캐시가 갱신되어야 합니다.

  • HTTP가 클라이언트-서버 프로토콜이므로, 리소스가 변경됐을 때 서버는 캐시와 클라이언트에 접근할 수 없습니다

    • 서버는 리소스에 대한 만료 시간을 알려줄 수밖에 없습니다.
    • 만료 시간 이전에는, 리소스가 유효(fresh)하고, 만료 시간 이후의 리소스는 실효(stale)됩니다.
  • 실효된 리소스는 축출되거나 무시되지 않는다는 것을 알아두어야 합니다.

  • 캐시는 실효(stale)된 리소스에 대한 요청을 받은 경우, 이 리소스가 실제로 아직 유효한지 아닌지를 확인하기 위해 If-None-Match (en-US)와 함께 요청을 전달합니다.

  • 만약 아직 유효하다면 서버는 요청된 리소스 본문을 전송하지 않고 304 (Not Modified) 헤더를 돌려보내 캐시 데이터를 사용하게 하여 대역폭을 절약합니다.



Revved resources

  • 우리가 캐시된 리소스들을 많이 사용할수록, 웹 사이트의 응답성과 성능은 점점 더 좋아질 것입니다.

  • 이것을 최적화하기 위한 좋은 방법은 가능한 먼 미래로 만료 시간을 설정하는 것입니다.

  • 이것은 자주 업데이트되는 리소스에 대해서는 적절하고 좋겠지만, 드물게 업데이트되는 리소스의 경우에는 문제가 됩니다.

  • 이런 리소스들을 캐시하면 이득이 크지만, 업데이트하기가 매우 어렵기 때문입니다.

  • 웹 개발자들은 Steve Sounders가 revving이라고 불렀던 기술을 발명했습니다.

  • 드물게 업데이트되는 파일들은 특정한 방법으로 이름붙여집니다.

  • 그렇게 해서 해당 리소스의 각각의 새로운 수정본 자체는 결코 변경되지 않으며, 보통 1년 혹은 그 이상의 아주 먼 미래로 만료 시간이 설정될 수 있습니다.

  • 새로운 버전을 가지기 위해, 해당 리소스와의 모든 연결(link)들은 전부 변경되어야 하는 것이 이 방법의 단점입니다.

  • 드물게 변경되는 리소스들이 변경되는 경우 자주 변경되는 리소스에 추가적인 변경을 합니다. 이런 리소스들이 읽혀지는 경우, 다른 리소스들의 새로운 버전들도 읽혀지게 됩니다.

  • 이 기술은 장점은 캐시된 두 개의 리소스를 동시에 갱신해도 한 리소스의 오래된 버전이 다른 리소스의 새로운 버전과 함께 혼합되어 사용되는 경우를 초래하지 않을 것입니다.

    • 이것은 웹 사이트가 상호 간의 의존성을 가지고 있는 CSS 스타일시트와 자바스크립트를 가지고 있는 경우 (같은 HTML 요소를 참조하기에 서로 의존하게 됩니다) 매우 중요합니다.


나름의 해석

사실 위 내용은 이해하기 상당히 힘든 것 같습니다.. 저도 완벽히 이해가 되지 않아서 나름의 해석한 내용을 적어보겠습니다.

  • 캐시를 최적화 하기 위해서는 가능한 먼 미래로 만료 시간을 설정하고 캐시데이터를 사용하는 것 입니다.
  • 하지만 드물게 업데이트 되는 리소스의 경우에는 문제가 됩니다 => 드물게 업데이트 되는 리소스는 용량이 큰가 ? 업데이트가 힘들다고 합니다.
  • 이부분을 개선하기 위해 revving이라는 기술을 발명하였습니다.
    • 이 기술은 드물게 업데이트 되는 파일의 URL에 (일반적으로 파일 이름)에 버전 번호가 추가됩니다. ex) CSSv1 => CSSv2
  • 웹 서버의 리소스가 변경되고, 캐시의 리소스가 stale 상태가 되면 Web Server로 부터 revalidation이 이뤄집니다.
  • 이때 Cache의 해당 리소스와 모든 연결은 전부 변경되어 HTML -> HTML*로 링크가 변경되고 CSSv1은 사라지지 않고 존재합니다.(expire time동안)
  • 또한 매번 JS, CSS가 변경될 때마다 HTML과 함께 링크되어 변경되기 때문에 오래된 버전과 새로운 버전이 혼합되어 사용되는 경우가 초래되지 않습니다.


Varying responses

우선 Vary HeaderContent negotiation에 대해 알아보겠습니다.

Vary HTTP Header란 ?

  • Vary 헤더는 캐시 된 응답을 향후 요청들에서 오리진 서버로 새로운 요청 헤더를 요청하는 대신 사용할 수 있는지 여부를 결정합니다. 이것은 서버에서 Content negotiation Algorithm에 어떤 리소스를 선택을 할 것인지를 가르킵니다.
  • Vary 헤더는 원 서버로부터 새로운 리소스를 요청해야 하는지 캐시된 응답이 사용될 수 있는지를 결정하기 위해 이후의 요청 헤더를 대조하는 방식을 결정합니다.

그렇다면 Content negotiation이란?

  • HTTP에서, 컨텐츠 협상이란 동일한 URI에서 리소스의 서로 다른 버전을 서브하기 위해 사용되는 메커니즘으로, 사용자 에이전트가 사용자에게 제일 잘 맞는 것이 무엇인지를 명시할 수 있습니다. ex) 문서의 언어, 이미지 포맷 혹은 컨텐츠 인코딩에 있어 어떤 것이 적절한지 명시 하는 것
  • 즉 요청 헤더에 언어, 이미지 포맷, 인코딩 등의 정보를 함께 보내어, 어떤 형식으로 받을지 결정하는 것 입니다.
  • 자세한 정보는 여기에서 확인해주세요.

  • 위 과정 처럼 캐시가 Vary 헤더 필드를 지닌 요청을 수신한 경우, Vary 헤더에 의해 지정된 모든 헤더 필드들이 원래의 (캐시된) 요청과 새로운 요청 사이에서 일치하지 않는다면 그 캐시된 응답을 사용해서는 안되고 서버로부터 요청을 보내야합니다.
  • 서버는 Vary: Accept-Encoding을 설정하여 특정한 집합의 인코딩을 지원하는 모든 요청들에 대해 각각 다른 버전의 리소스를 캐시하도록 할 수 있습니다. ex) br, gzip
  • Vary: User-Agent 헤더를 사용해서 데스크탑과 모바일 사용자에게 서로 다른 컨텐츠를 제공하거나, 검색 엔진에게 페이지의 모바일 버전을 발견할 수 있게 하는 데에도 유용합니다.
    • User-Agent (en-US) 헤더 값이 모바일과 데스크탑 클라이언트 간에 서로 다르기 때문입니다.


마치며

오늘은 캐시에 대해 알아봤다. 기본적으로 SWR을 사용하면서 내부적으로 사용하게 되는 것이 Cache인데 그저 기본적인 내용만 숙지하고 SWR이 제공해주는데로 사용하고 있다가 캐시 정책에 대해 알고싶어 학습하게 되었다. 이 과정을 진행하면서 HTTP HEADER에 대한 정보도 아직 미흡하다는 것을 깨달았고, 다음은 HTTP Header에 대해 정리해보겠다 ! + Revved resources에 대해서도 명확히 정리가 되지않아 더 찾아봐야겠다.

출처: https://hahahoho5915.tistory.com/33 [넌 잘하고 있어]
출처: https://developer.mozilla.org/ko/docs/Web/HTTP/Caching

profile
부지런한 웹개발자🌙

0개의 댓글