웹 서비스 캐시 다루기

2025. 5. 2. 03:20·⭐FE

📌배경

웹 성능을 높이는 데 있어 HTTP 캐시 전략은 굉장히 중요하다. 캐시를 잘못 설정하면 불필요한 요청이 발생하거나, 반대로 변경된 리소스를 사용하지 못해 사용자 경험을 해치는 일이 발생할 수 있다.

 

📌캐시의 생명주기 

HTTP 캐시 전략에서 핵심은 리소스의 유효 기간을 얼마나, 어떤 조건으로 설정할지를 결정하는 것이다. 대표적인 설정값은 다음과 같다.

  • max-age=<seconds>: 캐시 유효 시간, 이 시간 동안은 서버에 요청하지 않고 캐시 사용
  • no-cache: 캐시를 저장하지만, 사용할 때마다 서버에 재검증 요청을 보냄
  • no-store: 캐시를 저장하지 않음. 로그인 정보나 민감한 리소스에 적합함

로컬에서 간단하게 express 서버로 `./public/script.js` 를 1시간 ( max-age=3600 ) 동안 캐시처리해 봤다. 

// 정적 파일: 1시간 캐시 (3600초)
app.use(
    "/static",
    express.static(path.join(__dirname, "public"), {
        setHeaders: (res, filePath) => {
            res.setHeader("Cache-Control", "public, max-age=3600");
        },
    })
);

 

처음에 `http://localhost:3000/static/script.js`를 들어가면 `http://localhost:3000/static/script.js` 자원에 대한 response가 200이 뜨지만 F5를 눌러 네트워크탭에서 다시 해당 자원을 확인해보면 200 OK(디스크 캐시에서) 가 뜸을 확인할 수 있다. max-age=3600 으로 설정했기 때문에 1시간동안은 캐시를 이용한다.

 

이번엔 max-age=3600 이 아닌 max-age=0으로 처리해봤다. 서버를 껏다가 킨 뒤 다시 `http://localhost:3000/static/script.js` 로 접속한 뒤 F5를 눌러 리로드 했을 시 304 Not Modified가 나타난다. 이는 요청한 자원을 검증해봤는데 달라진게 없기때문에 그대로 캐시를 이용한다는 의미이다. max-age=3600과 다르게 `검증` 단계를 거쳤다는 것을 알 수 있다. max-age=0은 사실상 `no-cache`와 동일하다 

 

이번엔 `no-store` 로 설정하고 같은 동작을 반복해보았다. `no-store`는 `no-cache`와 검증 조차 하지 않고 매 요청마다 리소스를직접 서버로 요청하고 이를 로드한다. 그러기에 304 not-modified 도 200 ok ( 디스크 캐시에서 ) 도 뜨지 않고 200 OK만 뜬다.  

 

📌캐시 이후의 동작: 재검증

max-age 시간이 지난 후 브라우저는 서버에 재검증 요청을 보낸다. 이 때 조건부 요청 헤더인 If-None-Match (ETag 기반) 또는 If-Modified-Since (Last-Modified 기반)를 사용한다. 서버는 변경이 없으면 304 Not Modified 응답을 내려주어 빠르게 응답할 수 있다. 

📌브라우저 vs CDN 캐시

HTTP 캐시는 여러 레이어에 저장된다.

  • 브라우저 캐시: 사용자의 디바이스에 저장됨
  • CDN 캐시: 중간 서버가 응답을 저장함

이중 CDN 캐시는 CDN Invalidation을 통해 지울 수 있지만, 브라우저 캐시는 제어가 어렵기 때문에 Cache-Control 설정이 훨씬 더 중요하다.

📌캐시 전략 예시

➕HTML 파일

HTML은 배포마다 변경 가능성이 높기 때문에 항상 최신 파일을 받아야 한다. 하지만 CDN에서는 캐시할 수 있도록 아래처럼 설정한다.

Cache-Control: max-age=0, s-maxage=31536000
  • 브라우저는 항상 재검증 요청을 보냄
  • CDN은 1년 동안 캐시 유지, 배포 시 CDN Invalidation으로 새 THML 확보

➕JS/CSS파일

빌드 시 해시가 붙은 고유 파일명을 사용하기 때문에, 변경 가능성이 없다고 가정하고 아래처럼 강하게 캐시한다.

Cache-Control: public, max-age=31536000
  • 브라우저와 CDN 모두 1년 동안 캐시 사용 가능
  • 변경 시 URL이 바뀌므로 캐시 충돌 없음

➕정리

캐시는 강력한 도구이지만, 설정이 잘못되면 오히려 문제를 일으킬 수 있다. 리소스의 특성에 맞게 Cache-Control 헤더를 조절하면, 성능도 높이고 비용도 줄일 수 있다. 

  • 변경 가능성이 높은 HTML은 짧은 캐시 + CDN 캐시 분리
  • 내용 고정된 JS/CSS는 긴 캐시 +URL 버저닝
  • no-cache vs no-store의 차이를 명확히 이해하기

📌참고

https://toss.tech/article/smart-web-service-cache

 

웹 서비스 캐시 똑똑하게 다루기

웹 성능을 위해 꼭 필요한 캐시, 제대로 설정하기 쉽지 않습니다. 토스 프론트엔드 챕터에서 올바르게 캐시를 설정하기 위한 노하우를 공유합니다.

toss.tech

 

'⭐FE' 카테고리의 다른 글

Design System 기반 Component library 개발 및 배포 경험기  (0) 2025.05.27
Currying (커링)  (0) 2025.05.10
JWT ( Json Web Token )  (0) 2025.04.07
JavaScript의 소수점 오차 생기는 이유  (0) 2025.04.06
Event bubbling(버블링), Event Capturing(캡처링)  (0) 2025.04.03
'⭐FE' 카테고리의 다른 글
  • Design System 기반 Component library 개발 및 배포 경험기
  • Currying (커링)
  • JWT ( Json Web Token )
  • JavaScript의 소수점 오차 생기는 이유
devWarrior
devWarrior
  • devWarrior
    devWarrior
    devWarrior
  • 전체
    오늘
    어제
    • 🧩Dev (263)
      • ⭐FE (34)
      • 🔒Algorithm (155)
      • ➕Etc. (11)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    node.js
    오블완
    dp
    실버3
    실버4
    코테
    javascript
    실버2
    프론트엔드
    구현
    자스
    Easy
    골드5
    FE
    그리디
    js
    프로그래머스
    Lv2
    react
    알고리즘
    백준
    티스토리챌린지
    BFS
    코딩테스트
    실버1
    자바스크립트
    Algorithm
    leetcode
    DFS
    nodejs
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
devWarrior
웹 서비스 캐시 다루기
상단으로

티스토리툴바