네트워크를 통해 리소스를 가져오는 것은 무겁고 비쌉니다.
- 큰 응답은 브라우저와 서버 간 많은 왕복이 필요합니다.
- 페이지는 모든 필수 리소스가 완전히 다운로드 되기 전에 로드되지 않습니다.
- 제한된 데이터 플랜을 가진 모바일 폰으로 웹사이트 접근 시, 불필요한 네트워크 요청은 돈낭비가 될 것입니다.
Browser compatibility
모든 브라우저에서 아래 API를 모두 지원합니다.
- Cache-Control
- ETag
- Last-Modified
이전의 가져온 리소스들을 재사용하면 웹 사이트와 애플리케이션의 성능을 향상시킬 수 있습니다. HTTP 캐싱은 웹 사이트가 좀 더 빠르게 반응하도록 만들 수 있습니다.
캐싱: 주어진 리소스의 복사본을 저장하고 있다가 요청시에 제공하는 기술
⇒ 서버의 부하 완화, 성능 향상
⇒ but 리소스가 변할 수 있기 때문에 변하기 전에만 캐싱하고 변한 이후에 더 이상 캐싱하지 않는 것이 중요
캐싱 동작의 대상
- 검색 요청의 성공적인 결과: HTML 문서, 이미지 혹은 파일과 같은 리소스를 포함하는 GET 요청에 대한 200(OK) 응답
- 영구적인 리다이렉트: 301(Moved Permanently) 응답
- 오류 응답: 404 (Not Found)
- 완전하지 않은 결과: 206(Partial Content)
- 캐시 키로 사용하기에 적절한 무언가가 정의된 경우의 GET 이외의 응답
캐싱 제어
Cache-Control 헤더
Cache-Control 헤더 필드는 요청과 응답 양쪽에 있어 캐싱 메커니즘을 위한 디렉티브를 지정하는데 사용합니다.
// 클라이언트 요청, 서버응답 모두 저장 안함, 요청은 매번 서버로 전송되고 전체 응답은 매번 다운로드
Cache-Control: no-store
// 캐시된 복사본을 사용하지만 먼저 서버에 요청해 유효성 검사하도록 강제
Cache-Control: no-cache
// 리소스가 공개적으로 캐싱될 수 있음
Cache-Control: public
// 단일 사용자만을 위한 것이고 공유 캐시에 의해 저장되서는 안된다.
Cache-Control: private
// 유효하다고 판단되는 최대 시간
Cache-Control: max-age=31536000
// 상태를 확인하고 만료된 리소스는 사용 안함, HTTP는 특정상황에서 fresh하지 않은 데이터도 사용하는 경우가 있는데 이를 막기위해 사용
Cache-Control: must-revalidate
유효성
어떤 리소스들은 서버 상에서 변경될 수 있고 캐시가 갱신되어야 합니다. 서버는 리소스에 대한 max-age를 리턴합니다. max-age 이전의 리소스는 fresh하고, 이후의 리소스는 stale하다고 합니다. stale된 리소스에 대한 요청을 받은 경우, 이 리소스가 현재 유효한지 여부를 판단하기 위해 If-None-Match(en-US)와 함께 요청을 전달하고 서버는 304 (Not Modified) 헤더를 돌려보내 대역폭을 절약합니다. max-age는 Cache-control: max-age=N 헤더 ⇒ Expires 헤더 ⇒ Last-Modifed 헤더 순으로 결정됩니다.
ETags
Etag Response 헤더는 사용자가 알 수 없는 값으로, 리소스에 대한 응답에 포함된다면 클라이언트는 이후 Request의 헤더 안에 If-None-Match(en-US)를 줄 수 있습니다.
Last-Modified
Last-Modified Response 헤더는 약한 검증을 위해 사용됩니다. Response 내에 Last-Modified 헤더가 존재하면 클라이언트는 캐시된 문서를 검증하기 위해 if-Modified-Since Requset 헤더를 줄 수 있습니다.
versioned URL들을 위한 장기간 캐싱
fingerprint나 버전 정보가 포함된 URL을 위한 요청에 응답할 때, 그리고 컨텐츠가 변경되지 않을 거라고 예상된다면 응답에 Cache-Control: max-age=31536000 를 추가할 수 있습니다. 31,536,000초(1년)는 지원하는 최대 값입니다. 웹팩에서 아래 설정을 통해 asset의 URL에 hash fingerprint를 할당할 수 있습니다.
output: {
// filename: 'bundle.js',
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
파일 내용이 변경되지 않더라도 [hash]값이 변경될 수 있는데, 웹팩에서 빌드 시에 항상 초기화 코드를 포함하기 때문입니다. 웹팩에서는 runtime 코드를 분리하기 위해 optimization.runtimeChunk option을 사용할 수 있는데요. single로 설정하면 모든 chunk들을 위한 하나의 runtime 번들을 생성합니다.
optimization: {
runtimeChunk: 'single',
},
자세한 내용은 https://webpack.js.org/guides/caching/#output-filenames 에서 확인할 수 있습니다.
unversioned URL들을 위한 서버 재검증
모든 URL이 버전 정보를 포함할 수 없습니다. Cache-Control 값을 통해 캐시 정책을 튜닝 할 수 있습니다.
Summary
- 캐시를 사용하면 서버의 부하를 줄이고, 성능을 높힐 수 있다.
- GET 요청의 200 응답, 301 응답, 404 응답, 206응답을 대상으로 동작한다.
- 버전 정보가 포함된 URL은 재검증이 필요없으므로 신뢰성과 속도를 모두 얻을 수 있다. Webpack에서 output파일에 output filename에 hash를 사용하여 최적화 할 수 있다.
Reference
'기타 > 네트워크' 카테고리의 다른 글
L4 switch L7 switch (0) | 2021.08.23 |
---|---|
최신 메시지 큐(Messgae Queue) MQ 기술 (0) | 2019.09.02 |