Cache Busting

2022. 12. 12. 13:19Frontend

Caching

  • 웹 캐시는 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치이다. 웹 요청이 캐시에 도착 했을 때, 캐시된 로컬 사본이 존재한다면 서버가 아니라 캐시로부터 응답이 제공된다.
  • 매번 새로고침할 때마다 서버에서 데이터를 새롭게 로딩하는 것은 웹사이트의 속도 저하를 불러온다. 따라서 이러한 문제를 해결하기 위해 브라우저의 캐시 메모리에 자주 사용되는 파일들을 저장해 두는 것이다. 캐시 메모리에 접근할 경우 서버로부터 매번 데이터를 불러오는 것보다 속도가 빠르다. 이러한 과정을 캐싱이라고 부른다.
  • 참고 : Next.js에서의 Caching (https://nextjs.org/docs/going-to-production#caching)
    • JavaScript, CSS, 정적 이미지들을 포함해  /_next/static 에서 자동으로 헤더를 사용한다.next.config.js 에서 세팅된 헤더는 정적 에셋들을 덮어씌운다. 정적으로 생성된 페이지의 캐시를 갱신하고 싶다면 [getStaticProps](<https://nextjs.org/docs/basic-features/data-fetching/get-static-props>) 함수에서 revalidate를 세팅할 수 있다. next/image 를 사용할 경우 이미지 최적화 로더 (Image Optimization loader)를 위한 캐싱 법칙이 존재한다. (specific caching rules)
      Cache-Control: no-cache, no-store, max-age=0, must-revalidate
      
      
      getServerSideProps 안과 API 경로에서 캐싱 헤더를 쓸 수 있다. [stale-while-revalidate](<https://web.dev/stale-while-revalidate/>).기본적으로, Cache-Control 헤더는 페이지가 데이터를 어떻게 패칭하느냐에 따라 다르게 세팅된다.
      • getServerSideProps 또는 getInitialProps 를 이용하는 페이지에서  next start 시 Cache-Control 헤더의 디폴트 값을 사용한다.  getServerSideProps 를 사용하면서 다른 캐싱을 원할 경우 use res.setHeader('Cache-Control', 'value_you_prefer') 를 사용해야한다.
      • 페이지에서 If the page is using getStaticProps, 를 사용할 경우 Cache-Control 헤더의 s-maxage=REVALIDATE_SECONDS, stale-while-revalidate 또는 revalidate 값은 사용되지 않는다. s-maxage=31536000, stale-while-revalidate
    • // This value is considered fresh for ten seconds (s-maxage=10). // If a request is repeated within the next 10 seconds, the previously // cached value will still be fresh. If the request is repeated before 59 seconds, // the cached value will be stale but still render (stale-while-revalidate=59). // // In the background, a revalidation request will be made to populate the cache // with a fresh value. If you refresh the page, you will see the new value. export async function getServerSideProps({ req, res }) { res.setHeader( 'Cache-Control', 'public, s-maxage=10, stale-while-revalidate=59' ) return { props: {}, } }
    • 참조: next dev 를 로컬에서 진행할 경우 헤더는 다음으로 덮어씌워지며 로컬에서 캐싱되는 것을 방지한다.
    • Cache-Control: public, max-age=31536000, immutable

Caching의 문제점

정적 파일(static file)은 캐시에 저장되어 만료 될 때까지 오랜시간 동안 존재할 수 있다. 만약 사이트를 업데이트 하는 경우 이전 버전의 파일들이 캐시에 남아 변경사항을 알아차리지 못할 수 있다. 그 경우 사용자에게 변경되지 않은 문서를 보여주게 되어 문제가 생긴다.

Cache busting

Cache busting은 unique file version identifier를 사용해 브라우저에게 새로운 버전의 파일이 있음을 알려준다. 이를 통해 브라우저는 새로운 버전의 파일을 서버로부터 받아와 사이트를 업데이트한다.

방법1. Filepath versioning

예시: /v2/style.css

cache busting을 하려는 파일 경로의 이름을 변경한다.

방법2. Filename versioning

예시 : style.v2.css

해당 파일 이름을 새로운 버전에 따라 이름을 바꿔 업데이트한다.

방법3. Webpack 설정

모듈 번들러인 Webpack의 치환(substitutions)을 통해 파일 이름에 고유 해시값을 넣을 수 있다. 파일과 콘텐츠가 바뀌면 해시값 또한 바뀐다.  contenthash 치환에서 에셋에 기반하여 고유 해시값을 붙인다. 예를 들어 style.css 란 이름의 파일이  style-67bde1.css 로 바뀌는 식이다. 여기서 67bde1 는 웹팩에서 생성한 것이다.

webpack.config.js 파일 설정 예시

  const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
    entry: './src/index.js',
    plugins: [
      new HtmlWebpackPlugin({
       title: 'Output Management',
       title: 'Caching',
      }),
    ],
    output: {
     filename: 'bundle.js',
     filename: '[name].[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
  };

업데이트된 파일의 경로를 설정할 필요 없이 HtmlWebpackPlugin 에서 자동으로 제공해준다.

방법4. Query Strings (추천하지 않음)

예시 : style.css?v=1 , style.css?v=2

Query strings은 몇몇 프록시나 CDN에서 파일을 캐시할 수 없기 때문에 추천되지 않는 방식이다. 따라서 캐시 버스팅을 할 경우에 파일 이름을 바꾸거나 파일 경로를 버전에 따라 바꾸는 것이 추천된다.

참고자료

'Frontend' 카테고리의 다른 글

딥 링크, 앱 링크, 유니버설 링크  (1) 2023.11.14
웹폰트 사용과 최적화  (0) 2022.12.28
MJML  (1) 2022.08.24
2022/06/02 프론트엔드 개발환경의 이해  (0) 2022.06.02
2022/05/26 radio 버튼 체크 막기 (disabled 설정)  (2) 2022.05.26