[FRONT] Web cache

Posted by lim.Chuck on September 3, 2024

[FRONT]

  1. [FRONT] 프론트엔드 쿠키 이슈 해결하기
  2. [FRONT] Nuxt Proxy 설정과 활용
  3. [FRONT] 웹 캐시 전략과 구현
  4. [FRONT] Next.js와 Nuxt.js 비교 분석
  5. [FRONT] Monorepo vs Multi-repo vs Monolith 아키텍처
  6. [FRONT] mitmproxy를 활용한 디버깅
  7. [FRONT] Storybook 활용 가이드
  8. [FRONT] Vercel Turbopack 소개
  9. [FRONT] 캐시와 캐싱 전략
  10. [FRONT] SWC 컴파일러 이해하기
  11. [FRONT] 인터섹션 옵저버로 인터섹션 여부 감지하기
  12. [FRONT] BroadcastChannel 사용해서 같은 도메인 브라우저 간 통신하기
  13. [FRONT] DOM이벤트 버블링(Bubbling)과 캡처링(Capturing)
  14. [FRONT] XSS와 CSRF
  15. [FRONT] 웹 성능 최적화
  16. [FRONT] 브라우저 렌더링 과정
  17. [FRONT] 웹 접근성
  18. [FRONT] URL과 Domain 정확히 이해하자 (url구조)
  19. [FRONT] HTTP 헤더 이해하기

캐시가 날라가지않는 현상이 발생하여 cache 공부점

캐시와 캐싱의 차이

구분 캐시(Cache) 캐싱(Caching)
정의 데이터를 임시로 저장하여 빠르게 액세스할 수 있도록 하는 저장소 데이터를 효율적으로 저장하고 재사용하기 위한 과정 및 기술
형태 하드웨어(예: CPU 캐시, 디스크 캐시) 또는 소프트웨어(예: 메모리 캐시) 작업 방식이나 전략(예: 캐싱 알고리즘, 정책)
목적 특정 데이터를 빠르게 제공하기 위한 저장소 데이터 요청을 최소화하여 성능을 향상시키는 것
예시 브라우저 캐시, Redis, CDN 캐시 LRU(Least Recently Used) 알고리즘, 프리페칭(prefetching)
시간적 특성 데이터 저장소로 지속적 유지 데이터 저장 및 갱신 과정을 포함
사용 주체 개발자가 구현하거나 사용하는 도구 개발자가 구현하는 방법 또는 전략

Cache?

컴퓨터 과학에서 캐싱은 데이터를 고가용성 및 쉽게 액세스할 수 있는 리소스에 저장하여 해당 데이터 검색 시간을 줄이는 절차를 말합니다. 캐싱의 중요성은 1960년대 중반으로 거슬러 올라가는데, 당시 컴퓨터 프로세서는 메모리에서 해당 명령을 검색하는 데 걸리는 시간에 비해 더 높은 밀도의 명령을 더 짧은 시간에 처리할 수 있었고, 이는 프로세서가 특정 시간 동안 유휴 상태여야 한다는 것을 의미했습니다.

이 문제는 Maurice Vincent 경이 프로세서에서 쉽게 사용할 수 있는 메모리 시스템을 설명하면서 해결했습니다 . 원래 이 솔루션은 저수준 시스템(하드웨어)을 위해 설계되었지만 나중에 웹사이트와 같은 인터넷의 성능 애플리케이션을 높이기 위해 유사한 원리가 제안되었습니다.

캐싱 메커니즘을 통해 웹사이트의 성능을 어떻게 향상시킬 수 있는지 알아보기에 앞서, 웹사이트가 사용자에게 서비스를 제공하는 방식부터 간략하게 살펴보겠습니다.

어떻게 작동하나요?

사용자가 브라우저에 URL이나 웹사이트 주소를 입력하면 브라우저에서 최소한 다음과 같은 일련의 동작이 수행됩니다.

  1. 도메인 이름 서버(DNS)를 사용하여 대상 인터넷 프로토콜(IP) 주소를 찾습니다. DNS는 기본적으로 웹사이트 주소를 입력하고 웹사이트가 있는 서버의 IP 주소를 출력합니다.

  2. 브라우저는 서버로 HTTP 또는 HTTP 2.0 요청을 보냅니다. 이 요청은 네트워크 계층을 통해 전송되지만 그 부분의 세부 사항만 추상화해 보겠습니다.

  3. 서버는 HTTP 또는 HTTP 2.0 응답을 다시 보냅니다.

  4. 브라우저는 위에서 아래로, 왼쪽에서 오른쪽으로 응답을 렌더링하기 시작하고 필요에 따라 추가 HTTP/HTTP 2 요청(즉, 웹 페이지 자산)을 전송합니다.

생각해 보면, 이러한 각 단계는 한 리소스 또는 다른 리소스에서 어떤 종류의 데이터를 검색하려고 합니다. 데이터 전달을 담당하는 리소스, 예를 들어 DNS 서버는 해당 요청에 대한 답변을 찾는 데 일정 시간이 필요합니다. 그 다음에는 항상 해당 답변을 전달하는 데 추가 시간이 있습니다.

따라서 이러한 단계가 효율성과 관련하여 강조하는 문제는 프로세서가 보조 메모리에서 명령어를 검색하려는 문제와 유사할 뿐만 아니라 유사합니다. 이것이 동일한 캐싱 메커니즘이 웹 애플리케이션의 성능을 높이는 데 효과적인 근본적인 이유입니다.

다양한 종류의 캐시

1. DNS 캐싱

이는 DNS 조회 중에 사용됩니다.
즉, 브라우저(또는 운영 체제)는 대상 사이트의 IP 주소를 캐시하므로 DNS 서버에 요청할 필요가 없습니다.

2. 서버 측 캐싱

서버가 웹 페이지를 요청할 때마다 어떤 종류의 계산을 수행해야 합니다. 이 계산은 데이터베이스에서 어떤 데이터를 검색하는 것일 수 있습니다. 즉, 누군가가 주문한 제품일 수도 있고, 이 계산은 고수준 코드(즉, PHP)를 기계 코드(저수준)라고 하는 것으로 해석하는 것일 수도 있습니다.

이러한 작업의 시간 복잡도를 줄이기 위해 프로그래머는 종종 캐시를 사용하여 빈번한 계산을 다시 하지 않도록 합니다. 예를 들어, 코드 조각(예: PHP 스크립트)이 두 정수의 합을 계산하도록 작성되면 각 요청마다 반복적으로 기계 코드로 변환할 필요가 없으므로 프로그래머는 한 번 해석한 코드를 캐시( PHP의 경우 OPcache 라고 함 )로 변환하여 다시 해석할 필요가 없도록 합니다.

마찬가지로, 데이터베이스 엔진은 자주 검색되는 콘텐츠의 인덱스를 캐시하여 즉시 응답할 수 있도록 하려고 합니다.

3. 브라우저 기반 캐싱

개발자에게 “최신 변경 사항을 보려면 캐시를 지워주세요”라고 요청받은 적이 있나요? 그렇다면 개발자가 업데이트된 코드를 보려면 브라우저 캐시를 지워달라고 요청할 가능성이 큽니다. 브라우저는 렌더링 시간과 복잡한 리소스를 계산하는 모든 힘든 작업을 해야 하므로 이러한 리소스를 캐시하여 응답 시간을 더 빠르게 만드는 경향이 있습니다. 이러한 리소스에는 스타일시트, 글꼴, 이미지 또는 JavaScript 라이브러리가 포함될 수 있지만 이에 국한되지는 않습니다.

4. 콘텐츠 전송 네트워크(CDN)

  • CDN 사용: CDN은 캐시된 콘텐츠 버전을 다양한 지리적 위치에 분산된 서버에 저장합니다. 사용자가 콘텐츠를 요청하면 가장 가까운 서버에서 서비스를 제공하므로 전달 속도가 빨라집니다.
  • CDN 캐싱 규칙 구성: CDN에서 캐싱 규칙을 설정하여 콘텐츠를 캐시해야 하는 기간과 새로 고쳐야 하는 시기를 결정합니다. 많은 CDN은 웹 사이트를 업데이트할 때 캐시된 콘텐츠 제거도 지원합니다.

5. 데이터베이스 캐싱

쿼리 캐싱: 동일한 쿼리를 반복적으로 실행하지 않도록 비용이 많이 드는 데이터베이스 쿼리의 결과를 캐시합니다. 이는 Redis와 같은 도구나 데이터베이스 관리 시스템에 내장된 캐싱 메커니즘을 사용하여 수행할 수 있습니다. 개체 캐싱: 빠른 액세스를 위해 메모리에 개체 또는 데이터 구조를 캐시합니다. 예를 들어 페이지에 여러 데이터베이스 쿼리의 데이터가 필요한 경우 매번 검색하고 처리하는 대신 수집된 데이터 개체를 캐시할 수 있습니다.

6.캐시 무효화 구현

만료 정책 설정: 캐시된 데이터를 오래된 것으로 간주하고 소스에서 다시 가져와야 하는 시기를 정의합니다. 이는 사용자가 업데이트된 콘텐츠를 받을 수 있도록 하는 데 중요합니다. 수동 캐시 지우기: 때로는 캐시를 수동으로 무효화하거나 지워야 할 수도 있습니다. 특히 새 업데이트를 배포한 후나 즉시 반영해야 하는 콘텐츠 변경 사항이 있는 경우에는 더욱 그렇습니다.

7. 모니터링 및 최적화

캐시 성능 모니터링: 캐시가 예상대로 작동하는지 정기적으로 모니터링하세요. Google Analytics, Lighthouse 또는 서버 로그와 같은 도구는 캐시 적중/실패를 추적하고 문제를 식별하는 데 도움이 될 수 있습니다. 캐시 전략 최적화: 사용자 행동, 트래픽 패턴, 콘텐츠 업데이트 빈도에 따라 캐싱 전략을 조정합니다. 이렇게 하면 오래된 콘텐츠를 제공하지 않고도 캐시가 효과적이게 됩니다.

중요한 것은 무엇일까요?

캐싱이 아무리 좋더라도 불행히도 다음과 같은 이유로 모든 것을 캐싱할 수는 없습니다.

  1. 때때로 웹 애플리케이션의 요구 사항은 날씨 정보나 주식 가치와 같은 동적 데이터를 확인하는 것입니다.

  2. 타사 라이브러리, 예를 들어 애플리케이션이 다른 사람의 코드를 애플리케이션의 일부로 사용하고 해당 코드에 보안 업데이트가 있다고 가정해 보면 해당 코드가 캐시되면 업데이트되지 않아 치명적인 문제가 발생할 수 있습니다.

하지만 모든 것을 캐싱하지 않으면 문제가 더 커집니다.

캐시는 성공과 실패가 반복됩니다!

캐시 적중률 및 미스율

캐시 적중은 사용자 또는 시스템이 어떤 콘텐츠/리소스에 접근하려 했고, 그 콘텐츠가 캐시에 있었고 관련 사용자 또는 시스템에 즉시 제공되었다는 것을 의미합니다. 반면에 “캐시 미스”는 어떤 콘텐츠가 요청되고 캐시에 관련 데이터가 없고 요청을 지시해야 하는 경우입니다.

캐시 적중률이란 캐시에서 콘텐츠가 발견된 횟수를 데이터를 회수한 총 횟수로 나눈 값입니다.

효율적인 시스템은 캐시 적중률을 높이고 캐시 미스율을 낮추려고 시도합니다.

캐시 제어 정책 및 검색 엔진 최적화(SEO)

HTTP나 Cloudflare와 같은 콘텐츠 전송 네트워크와 같은 시스템은 리소스를 임의로 캐시하기 때문에 이러한 시스템에 캐시해야 할 내용과 캐시 기간을 알려야 합니다. 다른 프레임워크는 캐시 정책 이라는 개념을 다르게 처리하지만, 즉 .NET은 이를 처리하는 자체 프로그램 집합을 가지고 있지만 이러한 모든 프레임워크의 공통 분모는 HTTP입니다. HTTP는 ‘ 캐시 요청 및 응답 지시문 ‘ 이라는 것을 사용하여 캐시 정책을 제어합니다.

예를 들어, 누군가가 게시물을 추가할 때마다 업데이트가 필요한 웹사이트 구성 요소가 있는 경우 누군가가 해당 게시물을 업데이트할 때마다 "Cache-Control: must-revalidate"라는 지시문을 사용해야 합니다. 검색 엔진은 정보를 지속적으로 크롤링하고 검색하기 때문에 그들이 권장하는 것 중 하나는 정적 콘텐츠에 더 나은 HTTP 캐시 정책을 사용하는 것입니다. 좋은 캐시 정책을 사용하면 더 나은 사용자 경험을 제공할 뿐만 아니라 웹사이트의 SEO를 돕는 핵심 요소가 될 수 있습니다.

사용방법

1.설정

  1. 브라우저 캐싱 설정
  • Cache-Control 헤더 설정: 서버에서 Cache-Control과 같은 HTTP 헤더를 설정하면 브라우저가 특정 리소스를 얼마나 오래 캐시할지 결정할 수 있습니다. 이를 통해 사용자 브라우저가 리소스를 다시 다운로드할 필요 없이 캐시된 버전을 사용할 수 있습니다.
    • 예: Cache-Control: max-age=3600 (브라우저가 리소스를 1시간 동안 캐시하도록 설정).
  • ETag 사용: ETag는 브라우저가 서버에서 리소스가 변경되었는지 확인할 수 있도록 해줍니다. 리소스가 변경되지 않았다면 브라우저는 캐시된 버전을 사용할 수 있습니다.
  1. 프론트엔드 프레임워크에서 캐싱 활용
  • 서비스 워커 사용: PWA(Progressive Web App)를 개발할 때 서비스 워커를 사용하면 앱의 일부 또는 전체를 오프라인 상태에서도 사용할 수 있도록 캐시할 수 있습니다.
    • 예: workbox 같은 라이브러리를 사용해 네트워크 요청을 캐시하고, 오프라인 상태에서 캐시된 콘텐츠를 제공.
  • 로컬 스토리지 활용: 로컬 스토리지에 자주 사용하는 데이터를 저장하여 웹 페이지를 재로딩할 때 빠르게 데이터를 가져올 수 있습니다.
  1. 프론트엔드 캐시 최적화
  • 파일 이름에 해시 사용: 빌드 과정에서 파일 이름에 해시를 추가하여 새로운 버전이 배포될 때마다 브라우저가 최신 파일을 다운로드하도록 할 수 있습니다. 예를 들어, app.js 대신 app.abc123.js와 같은 이름을 사용합니다.
  • 캐시 무효화 관리: 브라우저 캐싱으로 인해 오래된 파일이 사용자에게 제공되지 않도록 주기적으로 캐시를 무효화하거나, 파일 버전을 관리합니다.
  1. 콘텐츠 전송 네트워크(CDN) 설정
  • CDN 사용: CDN은 사용자와 가까운 서버에서 리소스를 제공하여 로딩 시간을 줄여줍니다. CDN을 설정하여 이미지, CSS, JavaScript 파일 등을 캐시하고, 브라우저에서 더 빠르게 로드될 수 있도록 합니다.
  • CDN 캐싱 규칙 설정: CDN에서 제공되는 리소스의 캐시 기간을 설정하고, 콘텐츠 업데이트 시 캐시를 자동으로 무효화하는 규칙을 설정합니다.
  1. 캐시 모니터링 및 조정
  • 캐시 성능 모니터링: 브라우저 개발자 도구(DevTools)를 사용하여 캐시가 제대로 작동하는지 확인하고, 캐시 히트/미스 비율을 분석하여 성능을 최적화합니다.
  • 사용자 행동에 따른 캐시 최적화: 사용자 행동과 트래픽 패턴을 분석하여 캐시 정책을 조정하고, 사용자에게 최상의 성능을 제공할 수 있도록 합니다.

2. 삭제

프론트엔드 개발자가 웹 캐시를 삭제하는 방법은 여러 가지가 있습니다. 주로 코드나 설정을 통해 캐시를 무효화하거나 삭제할 수 있습니다. 다음은 개발자가 캐시를 삭제하는 몇 가지 방법입니다:

1. 캐시 무효화(Cache Invalidation)

  • 파일 이름에 버전 정보 추가: 자바스크립트, CSS, 이미지 파일 등 정적 자산의 파일 이름에 해시값이나 버전 정보를 추가합니다. 예를 들어, style.css 대신 style.v2.css 또는 style.abc123.css와 같이 사용합니다. 이렇게 하면 파일이 변경될 때마다 새로운 이름으로 배포되므로, 브라우저는 새 파일을 다운로드합니다.
1
2
<!-- 예시 -->
<link rel="stylesheet" href="style.abc123.css" />
  • Query String 사용: 리소스 URL에 쿼리 문자열을 추가하여 브라우저가 새로운 리소스로 인식하도록 할 수 있습니다.
1
2
<!-- 예시 -->
<script src="app.js?v=2.0"></script>

2. HTTP 헤더 설정

  • Cache-Control 및 Expires 헤더 변경: 서버에서 제공하는 리소스의 Cache-Control 헤더를 짧은 시간으로 설정하거나, no-cache 또는 no-store로 설정하여 브라우저가 캐시된 버전을 사용하지 않도록 할 수 있습니다.
1
2
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
  • ETag 헤더를 이용한 캐시 무효화: 서버에서 리소스를 제공할 때 ETag를 변경하여 브라우저가 새로운 버전을 다운로드하게 할 수 있습니다.

3. 서비스 워커(Service Worker) 캐시 삭제

  • 서비스 워커에서 캐시 무효화: 서비스 워커에서 캐시를 관리하는 경우, 새로운 버전이 배포될 때 이전 캐시를 삭제하거나 무효화하도록 코드를 작성할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
self.addEventListener("activate", (event) => {
  const cacheWhitelist = ["my-cache-v2"];
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames.map((cacheName) => {
          if (!cacheWhitelist.includes(cacheName)) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

4. CDN 캐시 퍼지(Purge)

  • CDN 캐시 삭제: CDN을 사용하는 경우, 관리 콘솔이나 API를 통해 특정 파일 또는 전체 사이트에 대해 캐시를 퍼지할 수 있습니다. 이렇게 하면 CDN 서버에 저장된 캐시된 콘텐츠가 삭제되고, 사용자는 최신 콘텐츠를 받게 됩니다.
1
2
3
4
5
#예시: Cloudflare API를 사용한 캐시 퍼지
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_identifier}/purge_cache" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything":true}'

5. 개발 환경에서 캐시 비활성화

  • 브라우저 개발자 도구 설정: 개발 중에는 브라우저의 개발자 도구에서 “Disable cache” 옵션을 활성화하여 캐시 없이 페이지를 로드할 수 있습니다. 이 옵션은 일반적으로 Network 탭에서 찾을 수 있습니다.