적용하게 된 계기
현재 개발중인 프로젝트의 프론트엔드 서버는 두 서버로 분리되어 있습니다. 그리고 사용자는 분리된 서버 간 이동을 자주 경험하고 있습니다.
근데, 두 서버 중 한 서버에서 웹 캐싱이 이루어지지 않고 있다는 사실을 발견하게 되었고, 그동안 사용자가 두 서버 간 이동을 할 때 이전 상황이 캐싱되지 않아 페이지 전환 시마다 맨 처음화면으로 돌아가는 현상을 겪고 있다는 것을 알게 되었습니다.
원인은 Cache-Control값에 따른 Back/Forward Cache 적용 여부에 차이가 있다는 것이었고, 해당 글을 통해 Back/Forward Cache 적용방법을 공유하고자 합니다.
Back/Forward Cache란?
Back/Forward Cache는 브라우저의 뒤로가기/앞으로가기 시 즉각적인 페이지 로드가 가능하게 하는 브라우저 최적화 방식이다.
느린 네트워크를 사용하는 사용자의 경우 검색 경험을 크게 향상시킬 수 있다.- web.dev 문서 중
Back/Forward Cache(BF Cache)를 활용하게 되면 브라우저의 단일 탭 내에서 뒤로가기/앞으로가기를 통해 전에 사용하던 페이지로 돌아가는 경우, 해당 페이지를 빠르게 로드할 수 있게 됩니다.
firefox나 safari는 예전부터 지원해오던 기능이며, chrome은 2021년 경부터 96 버전을 통해 정식으로 지원하기 시작했습니다.
https://developer.chrome.com/blog/new-in-chrome-96/#more
그렇다면, BF Cache를 적용했을 때 얼마나 빨라지는 걸까요?
해당 영상의 10초 부분을 참고해주시기 바랍니다 :)
https://youtu.be/cuPsdRckkF0
Cache의 생명주기
Cache를 적용하기 전에 먼저 HTTP에서 Cache의 생명주기가 어떻게 구성되는지 알아봅시다.
HTTP에서 리소스란 웹 브라우저가 HTTP 요청으로 가져올 수 있는 모든 종류의 파일을 말합니다. 대표적으로 HTML, CSS, JS, 이미지, 비디오 파일 등이 리소스에 해당합니다.
웹 브라우저가 서버에서 지금까지 요청한 적이 없는 리소스를 가져오려고 할 때, 서버와 브라우저는 완전한 HTTP 요청/응답을 주고받습니다. HTTP 요청도 완전하고, 응답도 완전합니다. 이후 HTTP 응답에 포함된 Cache-Control값에 따라 받은 리소스의 생명주기를 결정합니다.
그리고 Cache-Control 값에 따라 Cache 적용여부가 결정됩니다.
Cache-control의 주요 value에 대해서도 알아보겠습니다.
max-age : max-age=<second>
식으로 값을 지정하면 해당 리소스의 캐시의 유효기간을 설정할 수 있습니다. 해당 캐시의 유효기간이 지나지 않았다면, 서버에게 캐시 사용 검증를 보내지 않고도 사용할 수 있습니다. 만약에 유호기간이 지났다면 서버에게 재검증을 요청하게 됩니다. 서버에게 재검증 요청을 보낸다는 것은, 쉽게말해 서버에게 해당 캐싱된 데이터를 사용해도 되는지 물어보는 과정입니다.
no-cache : 대부분의 브라우저에서 max-age=0 과 동일한 뜻을 가집니다. 즉, 캐시는 저장하지만 max-age가 0이기 때문에 사용하려고 할 때마다 서버에 재검증 요청을 보내야 합니다.
no-store : 캐시를 절대로 해서는 안 되는 리소스일 때 사용합니다. 캐시를 만들어서 저장조차 하지 말라는 가장 강력한 Cache-Control 값입니다. no-store를 사용하면 브라우저는 어떤 경우에도 캐시 저장소에 해당 리소스를 저장하지 않습니다.
따라서, 일반적인 경우, 페이지의 캐싱 여부를 결정짓는 것은 no-store의 유무라고 볼 수 있겠습니다. 일반적인 브라우저의 경우, no-store의 유무에 따라 Back/Forward Cache의 유무를 결정짓고 있습니다.
그리고 사용자 개인의 정보가 담겨져있는지 유무에 따라 public, private값을 설정할 수 있습니다.
Back/Forward Cache 적용
서버에서 페이지를 요청할 때 요청 헤더에 cache-control를 설정할 수 있습니다.
NextJS 기준 cache-control 설정하는 방법은 app.js에서 설정할 수도 있고, next.config.js에서도 설정이 가능합니다. 이번에는 next.config.js에서 cache-control을 설정하는 방법을 소개하겠습니다.
// next.config.js
const NEXT_CONFIG = {
headers: async () => {
return [
{
headers: [
{
key: 'Cache-Control',
value: 'no-cache, private',
},
],
source: '/:path*',
},
];
},
// .....
}
이처럼, 요청 headers에 Cache-Control을 설정할 수가 있습니다.
저는 Cache-Control의 value로 no-cache와 private를 설정해주었습니다.
no-cache는 앞에서 언급했듯이, 캐싱된 데이터 사용을 위해 항상 서버에게 검증을 요청하는 값입니다.
그리고 서비스가 로그인을 요구한다면 개인의 정보를 담고 있겠죠? 따라서, private값도 추가해주었습니다.
Back/Forward Cache 적용 여부 확인
적용을 했으니, 적용이 잘 되는지 확인 해봅시다.
개발자 도구 → 네트워크탭 → 애플리케이션 → 뒤로-앞으로 캐시(Back/Forward Cache) 확인
❗️ 참고로, 프로젝트를 개발환경으로 실행 시 BF Cache가 적용되지 않습니다.
- 왜냐하면 개발환경은 개발자가 변경 사항을 바로 확인하기 위해 브라우저가 모든 캐시를 무효화시키고 있기 때문입니다. (즉, 개발환경에서는 항상 no-store가 적용됩니다.)
- 따라서, 로컬에서 BF Cache 적용을 확인해주기 위해서는 production환경으로 실행시켜주어야 합니다.
브라우저마다 다른 캐시정책
Back/Forward Cache를 적용할 때 유의해야할 점에 대해서도 살펴보겠습니다.
브라우저마다 캐싱정책이 다르니, 이점 유의해주며 작업해야합니다.
microsoft edge의 경우, Back/Forward Cache를 기본적으로 방어하고 있습니다. 따라서, 설정을 통해 Back/Forward Cache를 허용해주어야 합니다.
edge://flags/#back-forward-cache
해당 주소에서 설정이 가능하오니, edge 작업이 필요하신 분들은 참고해주세요.
📚 참고자료
https://web.dev/bfcache/
https://toss.tech/article/smart-web-service-cache
https://developer.mozilla.org/ko/docs/Web/HTTP/Caching
'FrontEnd' 카테고리의 다른 글
[Typescript] 커스텀 훅에서 제너릭 활용하기 (0) | 2023.02.08 |
---|---|
[JavaScript] 클로저(Closure)란? (스코프, 클로저 개념, 클로저 활용) (0) | 2022.09.13 |