웹 캐시에 대해 알아보자 (feat. 토스테크)

Sheryl Yun·2023년 10월 30일
0

개발 상식 쌓기

목록 보기
10/11

스터디 팀원에게 추천받은 자료 공부 후 정리

서론

  • HTTP 캐시(웹 캐시)는 웹 성능을 최대한으로 높일 때 사용된다.

웹 캐시를 잘못 관리하면?

  • 원하는 시점에 캐시가 안 사라지거나 (새로 요청을 받아와야 하는데)
  • 필요 이상으로 HTTP 요청을 하게 되는 비용 발생

캐시의 생명 주기

  • HTTP에서의 리소스(Resource)
    • 웹 브라우저가 HTTP 요청으로 가져오는 모든 파일
    • 예: HTML, CSS, JS, 이미지, 비디오 파일
  • 웹 브라우저가 새로운(지금까지 요청한 적 없는) 리소스를 받아오려고 할 때, 서버와 브라우저는 '완전한'(캐시가 관여되지 않는) HTTP 요청 및 응답을 주고 받는다.
    • 이후에는 HTTP 응답에 포함된 캐시 관련 헤더(Cache-Control)로 요청/응답의 데이터 조절

max-age: 캐시의 유효 기간

  • 해당 리소스의 캐시가 유효한 시간
  • Cache-Control 헤더(key)의 값(value)으로 지정됨
  • 형태: max-age=<초>

max-age가 지나기 전

  • 이전에 받아온 리소스의 max-age가 지나지 않았다면
    • 아직 '캐시'가 남아 있는 상태
  • 브라우저가 서버에 요청을 보내지 않고 디스크나 메모리에 있는 '캐시'를 사용

  • 가운데 있는 (from memory cache)를 통해 메모리 캐시에서 불러왔다는 걸 알 수 있다.
  • cache-control: max-age=31536000
    • 이 리소스의 캐시의 유효 기간은 1년(31536000초)이라는 뜻
  • 캐시가 이렇게 한번 브라우저에 저장되면 max-age 기간으로 만료될 때까지 브라우저에 계속 남아 있게 됨
    • 이는 CDN Invalidation을 포함하여 서버에서 어떤 작업을 해도 브라우저에 있는 캐시를 지우기는 어려움

Cache-Control 헤더의 max-age 대신 Expires 헤더로 캐시의 만료 시간을 초가 아닌 구체적인 시간으로 설정 가능

max-age가 지나면? => 재검증

  • max-age가 지났다고 해서 캐시가 바로 완전히 사라지지는 않음
    • 이때 브라우저는 서버에 조건부 요청(Conditional Request)을 통해 캐시가 유효한지를 '재검증(Revalidation)'하는 과정 수행
  • 재검증의 결과로 브라우저의 캐시가 여전히 유효하다면 새로 받아오지는 않고 서버에서 [304 Not Modified]를 내려줌
    • 이 응답은 HTTP 본문(body)이 없기 때문에 매우 빠름 (필요 크기: 324바이트)

캐시 재검증(조건부 요청)을 위한 헤더: If-None-Match와 If-Modified-Since

If-None-Match

브라우저에 캐싱된 리소스의 ETag 값과 서버에 있는 리소스의 ETag 값이 동일한지 확인

If-Modified-Since

캐싱된 리소스의 Last-Modified 시점 후에 서버의 해당 리소스가 변경되었는지 확인

ETagLast-Modified의 값은 기존에 받았던 리소스의 응답 헤더에 있는 값을 사용

=> 이러한 재검증(조건부 요청) 과정을 거쳤을 때 캐시가 유효하지 않으면 서버는 새로운 데이터(body)와 적절한 상태 코드를 바로 내려줌

  • 추가 HTTP 요청 필요 없이 조건부 요청으로 확인한 후 바로 내려주기 때문에 효율적
  • 만약 max-age가 0초라면 서버에서 의도한 것은 브라우저가 새로운 리소스를 매번 내려 받는 것
  • 하지만 일부 '모바일 브라우저'의 경우 브라우저를 껐다 켜야만 리소스가 만료되게 하는 경우가 있음
    • 이는 네트워크 요청을 아끼고 사용자에게 더 좋은 웹 경험을 제공하기 위해서라고 함

=> 이 경우에는 브라우저를 껐다 켜거나, 아래에서 소개할 no-store를 사용한다.

no-cache와 no-store

no-cache

대부분의 브라우저에서 max-age=0과 동일
캐시를 저장은 하지만 캐시를 사용할 때마다 서버에 재검증(유효한지 검증) 요청을 보내야 함

no-store

캐시를 절대 하지 말라는 뜻
캐시를 만들어서 저장조차 하지 말라는 가장 강력한 Cache-Control 값
no-store를 사용하면 브라우저는 어떤 경우에도 저장소에 리소스를 저장하지 않음

캐시가 위치하는 곳

  • CDN과 같은 중간 서버를 사용하면 캐시가 여러 곳에 생길 수 있음
    • 예: 서버가 가지고 있는 응답을 CDN이 캐시, CDN의 캐시된 응답을 브라우저가 다시 캐시
  • 가끔 중간 서버나 CDN이 여러 개 있는 경우도 발생
    • 이때 전체 캐시를 날리려면 중간 서버의 각각에 대해 캐시를 삭제해주어야
      => 이렇게 한번 저장된 캐시는 삭제가 어렵기 때문에 Cache-Control의 max-age 값은 신중히 설정해야 함

Cache-Control 헤더의 public과 private

  • 중간 서버(예: CDN)가 특정 리소스를 캐시 가능한지 여부 지정

public

모든 중간 서버와 모든 사람이 캐시를 저장할 수 있음

private

가장 끝에 있는 사용자 브라우저만 캐시를 저장할 수 있음

기존의 max-age와 조합해서 사용하기 위해 컴마(,)로 연결해서 Cache-Control: public, max-age=86400 식으로 조합 가능

s-maxage

  • 중간 서버에서만 적용되는 max-age 값 설정 시 사용
    • 예: Cache-Control: s-maxage=31536000, max-age=0
      • 중간 서버인 CDN에서는 1년 캐시되지만, 브라우저에서는 매번 재검증 요청 보내도록 설정

Cache-Control 사용 예시 (토스)

리소스의 성격에 따라 Cache-Control 헤더 값 조절

HTML 파일

  • 배포가 새로 될 때마다 내용이 바뀌는 경우

  • 이때 브라우저는 이 HTML 파일을 불러올 때마다 배포가 새로 되었는지 확인해야 함 => 매번 서버에 재검증 요청 필요

    • 하지만 새로 배포된 게 없다면 기존 것을 그대로 사용해야 함 => 캐시도 필요
      => Cache-Control 값으로 max-age=0, s-maxage=3153600 설정
  • 1년 간 캐시하되, 새 배포를 대비해서 HTML 파일을 가져올 때마다 서버에 재검증을 요청, 그 사이에 새 배포가 있었다면 캐시를 쓰지 않고 새로운 HTML 파일을 내려받음

  • CDN은 HTML 파일에 대한 캐시를 계속 가지고 있으면서 새 배포가 있을 때마다 CDN Invalidation을 진행해서 CDN도 서버에서 새로운 HTML 파일을 받아오도록 함

JS, CSS 파일

  • Javascript나 CSS 파일은 웹 서비스를 새로 빌드할 때마다 생김
  • 관리 방식: 임의의 버전 번호를 URL에 포함시켜 각 빌드 결과물마다 고유한 URL을 가지도록 설정

  • 이렇게 해두면 같은 URL을 가진 리소스의 경우 새로 배포가 일어나지 않는 한 내용이 바뀔 수 없음
    • 이러한 경우 max-age의 최대치인 1년(31536000)을 설정해두고 캐시에 저장된 JS 파일을 계속 사용

자세한 캐시 설정의 장점

  • 사용자 브라우저가 HTTP 리소스를 더 빠르게 로드 가능
  • 개발자는 요청/응답 사이에서 트래픽 비용 절감

참고자료

웹 캐시 똑똑하게 다루기: 토스테크

profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글