사이트마다 캐시가 다른 이유? 이중 키 캐싱(Double-keyed Caching) 완벽 이해!

이중 키 캐싱(Double-keyed Caching) 이해하기: 왜 사이트 간 캐시가 공유되지 않을까요?

혹시 이런 궁금증을 가져본 적 있으신가요.

"왜 어떤 웹사이트에서는 정적 리소스(static resource)가 캐시(cache)되어 잘 남아있는데, 다른 사이트에서 똑같은 리소스(resource)에 접근하면 다시 다운로드해야 할까?".

이 현상의 근본적인 원인은 바로 이중 키 캐싱(Double-keyed Caching) 때문입니다.

그래서 오늘은 이중 키 캐싱(Double-keyed Caching)이 무엇인지, 어떻게 작동하는지, 그리고 우리는 이를 어떻게 최적화할 수 있을지에 대해 깊이 알아보겠습니다.

이중 키 캐싱(Double-keyed Caching)이란 무엇일까요

전통적인 브라우저(browser) 캐싱(caching) 방식에서는, 리소스(resource)를 주로 해당 리소스(resource)의 URL 주소를 기반으로 저장했습니다.

예를 들어, 여러분이 https://cdn.example.com/script.js 라는 주소에 방문하면, 브라우저(browser)는 이 script.js 파일을 캐시(cache)합니다.

그리고 다른 웹사이트에서 동일한 URL을 참조하게 되면, 브라우저(browser)는 다시 다운로드할 필요 없이 캐시(cache)된 버전을 직접 재사용했습니다.

이 전통적인 캐싱(caching) 방식은 우리가 기대하는 대로 작동합니다.

한 번 리소스(resource)가 캐시(cache)되면, 어떤 사이트든 해당 캐시(cache)에 접근할 수 있었죠.

하지만 이 방식에는 심각한 보안 위험, 즉 교차 사이트 추적(cross-site tracking)데이터 유출(data leakage)의 문제가 있었습니다

예를 들면 다음과 같습니다.

  • 어떤 웹사이트들은 공개 CDN 리소스(resource)의 캐시(cache) 상태를 확인하여 사용자가 특정 사이트를 방문했는지 여부를 추론할 수 있습니다.
    (예: 광고 추적 목적)

  • 해커(hacker)들은 캐시 포이즈닝(cache poisoning) 공격을 악용하여 사용자에게 손상된 리소스(resource)를 제공할 수도 있습니다.

이러한 보안 위험을 완화하기 위해, 많은 브라우저(browser)(예: 크롬(Chrome), 파이어폭스(Firefox))들은 이중 키 캐싱(Double-keyed Caching) 방식을 도입했습니다.

이중 키 캐싱(Double-keyed Caching)의 핵심 규칙은 다음과 같습니다.

리소스(resource)를 캐싱(caching)할 때, 단순히 URL 주소만 고려하는 것이 아니라 해당 리소스(resource)를 로드(load)한 사이트(Origin, 출처) 정보까지 함께 고려하는 것입니다.

즉, 이제 캐싱(caching)은 "사이트(Origin) + URL 주소"를 고유 식별자로 사용하게 됩니다.

다시 말해,

  • 이전에는 사이트 A에서 캐시(cache)된 리소스(resource)를 사이트 B가 재사용할 수 있었습니다 ✅
  • 이제는 사이트 A에서 캐시(cache)된 리소스(resource)를 사이트 B는 다시 다운로드해야 합니다 ❌

이중 키 캐싱(Double-keyed Caching)은 어떻게 작동할까요

이중 키 캐싱 = 사이트 출처(Origin) + 리소스 URL

예시를 통해 좀 더 자세히 살펴보겠습니다.

페이지 A와 페이지 B 두 곳을 방문한다고 가정해 봅시다.

두 페이지 모두 동일한 CDN 리소스(resource)인 https://cdn.example.com/script.js를 사용합니다.

전통적인 캐싱 (단일 키 캐싱, Single-keyed Caching)

  1. 페이지 A에서 script.js를 로드(load)하면, 브라우저(browser)는 이 파일을 캐시(cache)합니다.

  2. 페이지 B를 방문했을 때, 브라우저(browser)는 동일한 script.js를 요청하는 것을 확인하고 캐시(cache)에서 직접 파일을 로드(load)합니다.
    (네트워크 요청 감소 및 로딩 속도 향상)

이중 키 캐싱 (Double-keyed Caching)

  1. 페이지 A에서 script.js를 로드(load)하면, 브라우저(browser)는 이 파일을 오직 페이지 A를 위해서만 캐시(cache)합니다.

  2. 페이지 B를 방문했을 때, 비록 동일한 script.js를 요청하더라도 브라우저(browser)는 이를 완전히 새로운 리소스(resource)로 취급하고 새로 다운로드해야 합니다.

서로 다른 사이트는, 설령 동일한 리소스(resource)를 요청하더라도, 각각 별도로 캐시(cache)해야만 합니다!

이 방식은 보안을 강화하지만, 동시에 글 서두에서 언급했던 혼란, 즉 리소스(resource)가 사이트 간에 공유되지 않고 여러 번 다운로드되어야 하는 상황을 야기합니다.

이중 키 캐싱(Double-keyed Caching)의 단점

이중 키 캐싱(Double-keyed Caching)은 보안을 개선하는 반면, 몇 가지 문제점도 안고 있습니다.

  • 낮아진 캐시 재사용률: 동일한 리소스(resource)라 할지라도, 다른 사이트에서는 반드시 다시 다운로드해야 합니다.

  • 공개 CDN 효율성 감소: 전통적으로 jsDelivr나 UNPKG 같은 CDN(콘텐츠 전송 네트워크)은 여러 사이트가 캐시(cache)된 리소스(resource)를 공유함으로써 얻는 이점이 컸습니다.
    이제 이 장점이 크게 줄어들었습니다.

  • 높아진 첫 방문 비용: 사용자가 어떤 사이트를 처음 방문할 때, 설령 다른 사이트에서 동일한 리소스(resource)의 캐시(cache)된 복사본을 가지고 있더라도 여전히 다시 다운로드해야 합니다.
    이는 초기 페이지 로딩 속도를 느리게 만들 수 있습니다.

이중 키 캐싱(Double-keyed Caching)의 영향을 최적화하는 방법은 없을까요

이제 이중 키 캐싱(Double-keyed Caching)의 작동 방식과 잠재적인 단점을 이해했으니, 그 영향을 최적화할 수 있는 방법들을 알아보겠습니다.

서비스 워커(Service Worker) 활용하기

서비스 워커(Service Worker)는 클라이언트(client) 측에서 요청을 가로채고 로컬 캐시(local cache)를 활용하여 네트워크 요청 의존도를 줄일 수 있게 해줍니다.

예를 들어, 캐시 API(Cache API)를 사용하여 특정 리소스(resource)를 수동으로 저장함으로써 이중 키 캐싱(Double-keyed Caching)의 제약을 우회할 수 있습니다.

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      // 캐시에 응답이 있으면 그것을 반환하고, 없으면 네트워크에서 가져옵니다<br /><br />
      return response || fetch(event.request);
    })
  );
});




서비스 워커(Service Worker) 캐싱(caching)은 이중 키 캐싱(Double-keyed Caching)의 영향을 받지 않으므로, 자주 사용되는 정적 리소스(static resource) 관리에 HTTP 캐싱(caching)에만 전적으로 의존하는 대신 서비스 워커(Service Worker)를 활용할 수 있습니다.

HTTP/3를 사용하여 중복 요청 줄이기

이중 키 캐싱(Double-keyed Caching) 때문에 동일한 사용자라도 다른 웹사이트를 방문할 때마다 공통 CDN 리소스(resource)를 여러 번 다운로드할 수 있습니다.

하지만 만약 우리가 멀티플렉싱(multiplexing)과 0-RTT 연결을 지원하는 HTTP/3 (QUIC 프로토콜 기반)를 사용한다면 성능을 최적화할 수 있습니다.

비록 파일을 다시 다운로드해야 할 수도 있지만, 연결 설정 시간이 줄어들고 여러 요청을 동시에 효율적으로 처리할 수 있어 체감 속도를 개선할 수 있습니다.

사용하는 CDN이 HTTP/3를 지원하는지 확인하는 방법

  • 크롬 개발자 도구(Chrome DevTools)를 엽니다.

  • 네트워크(Network) 패널로 이동합니다.

  • 프로토콜(Protocol) 열을 확인합니다.

  • 만약 h3라고 표시된다면 해당 리소스(resource)가 HTTP/3를 사용하고 있다는 의미입니다.

중요한 리소스(Resource) 미리 로드(Preload)하기

브라우저(browser) 캐싱(caching)에 전적으로 의존할 수 없게 되었으므로, 중요한 리소스(resource)를 선제적으로 미리 로드(preload)하는 전략을 사용할 수 있습니다.

예를 들어, <link rel="preload"> 태그(tag)를 사용하여 폰트(font), 스크립트(script), 또는 CSS 파일을 미리 로드(preload)할 수 있습니다.

<link
  rel="preload"
  href="https://your-cdn.com/fonts/Roboto.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
/>

 
이렇게 하면 이중 키 캐싱(Double-keyed Caching) 때문에 리소스(resource)를 다시 다운로드해야 하는 상황이 발생하더라도, 미리 다운로드를 시작해 두었기 때문에 더 빠르게 로드(load)될 수 있습니다.

이러한 전략들을 적용함으로써, 우리는 보안과 성능 두 마리 토끼를 모두 잡으면서 이중 키 캐싱(Double-keyed Caching)의 영향을 줄일 수 있습니다.