브라우저 캐싱 이해하기

2023년 12월 25일

TL;DR:

브라우저의 캐싱은 서버가 HTTP 응답 헤더의 Cache-Control 속성을 통해 제어합니다.

브라우저에서 서버에 요청을 보냈을 때 [개발자 도구 → Network 탭 → Size 항목]에 (memory cache) 혹은 (disk cache)라는 문구가 뜨는 걸 본 적 있으신가요?

혹시 한 번도 본 적이 없다면, 지금 당장 구글에 접속해서 개발자 도구를 열어보세요. Network 탭에서 새로고침을 한 번 해보면 Size 항목에 (memory cache) 혹은 (disk cache)가 표시되는 걸 확인할 수 있을 거예요.

(memory cache) 혹은 (disk cache)가 표시됐다는 건, 서버로부터 데이터를 가져온 게 아니라 브라우저의 memory 또는 브라우저에 접속한 host의 disk로부터 캐싱된 데이터를 가져왔다는 뜻입니다.


브라우저 캐싱은 누가, 어떻게 제어할까?

바로 서버가 HTTP 응답 헤더의 Cache-Control 속성을 통해 제어합니다.

예컨대 Express.js 서버에서는 아래와 같이 Cache-Control 속성에 max-age={seconds}라는 지시어를 넣어서 응답 데이터를 캐싱할 수 있어요.

const app = express();

app.get("/api/data", (_, res) => {
  res.set("Cache-Control", "max-age=3600");

  res.status(200).json({ message: "success" });
});

여기서 max-age=3600은 "일단, 3600초만큼 데이터를 캐싱해두겠다"라는 말입니다.


3600초가 지나면 캐싱된 데이터가 사라질까?

제가 위에서 일단이라고 한 이유는 3600초가 지났을 때 곧바로 캐싱된 데이터가 사라지는 건 아니기 때문인데요, 이는 3600초가 지난 뒤 진행되는 재검증 요청과 관련이 있습니다.

재검증은 서버 측에서 해당 데이터를 그대로 사용해도 되는지 확인하는 작업을 말하는데요, 3600초가 지나면 서버로 재검증 요청을 보낸 뒤 사용해도 된다는 응답이 오면 그때 다시 캐싱된 데이터를 사용할 수 있게 됩니다. 다시 말해, 계속해서 재검증을 해도 데이터가 변경되지 않는다면 캐싱된 데이터는 끝까지 사라지지 않는다는 거예요.

위 내용이 조금 복잡하다면, 당장은 그냥 "Cache-Control 속성에 max-age={seconds}라는 지시어를 넣으면 {seconds}초만큼 데이터가 캐싱된다" 정도로만 이해하셔도 무방할 것 같습니다.


기억하면 좋을 Cache-Control 기본 지시어들

  • no-store: 데이터를 캐싱하지 않음
  • no-cache: 데이터를 캐싱하긴 하지만, 매 요청마다 서버 측에서 유효성 검사를 해야 함
  • max-age={seconds}: {seconds} 동안은 캐싱된 데이터를 사용하며, {seconds}가 지나면 서버 측에서 유효성 검사를 해야 함
  • public: 브라우저, 프록시 서버 등 어디에서든 데이터를 캐싱 가능
  • private: 브라우저에서만 데이터를 캐싱 가능
  • s-maxage={seconds}: 프록시 서버 등 중간 서버에서만 적용되는 속성으로 {seconds} 동안은 캐싱된 데이터를 사용하며, {seconds}가 지나면 서버 측에서 유효성 검사를 해야 함