티스토리 뷰

프론트엔드

캐시(cache)

jfmam 2023. 3. 10. 12:26

캐시 란?

캐시는 자주쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치다.

리소스 요청시의 문서의 사본이 존재하면 원 서버가 아니라 캐시로 부터 제공이 된다.

  • 불필요한 데이터 요청을 줄인다. → 네트워크 요금 비용을 줄인다
  • 병목현상을 해결한다 → 대역폭을 늘리지 않고 페이지를 빨리 불러온다.
  • 원서버 요청을 줄여준다 → 서버의 부하를 줄이면서 더 빨리 response한다.
  • 거리로 인한 지연을 줄여준다.

적중과 부적중

  • 적중: 유효한 사본이 있을 경우 캐시적중이라고 하며 해당 사본으로 응답한다.
  • 부적중: 유효한 사본이 없을 경우 원서버에 요청하여 새로운 사본을 받아 응답한다.
  • 에러: 유효한 사본이 없을경우 원서버에 요청하는데 새로운 사본이 없을 경우 에러 발생

재검사

💡 신선도검사: 캐시의 경우 원서버의 데이터와 일치하는지 사본을 점검해야 한다.

  • 콘텐츠가 변경되지 않을 경우 304 not modified 스테이터스 반환
  • 신선한지의 여부를 어떻게 알 수 있을까? → IMS (if- modified-since) 헤더를 통해 재검사를 진행한다.
  • 오늘날 적중률이 40프로만 되도 좋은편에 속한다. 캐시를 잘 활용하면 상당한 트래픽을 줄이고 더 빠른 응답을 기대할 수 있다.

적중과 부적중 구별

  • Date 헤더: Date헤더를 이용해 단순 날짜 비교
  • Age 헤더: 얼마나 오래 되었는지 파악할 수 있다. 초 단위 사용

캐시 토폴로지

캐시의 경우 전용캐시와 공용캐시로 나뉘며 이를 나누는 기준은 캐시를 공유하는지의 여부에 따라 나뉜다.

전용캐시

  • 웹브라우저는 개인전용캐시를 내장하고 있다.
  • 브라우저는 자주쓰이는 문서를 컴퓨터디스크와 메모리에 캐시해 놓는다.

프락시캐시

  • 프락시를 이용하여 공용된 캐시를 사용한다.
  • 깊게 다루진 않겠다.

캐시 처리단계

  1. 요청받기
  2. 파싱
  3. 검색
  4. 신선도 검사
  5. 응답 생성
  6. 발송
  7. 로깅

요청받기

클라이언트의 요청을 받아들여 트랜잭션처리를 실행한다.

파싱

헤더 부분을 조작하기 쉬운 자료구조에 담아 캐싱을 더 처리하기 쉽게 만들어준다.

검색

  • URL을 알아내여 로컬 사본이 있는지 검사한다. (메모리나 디스크 확인)
  • 사본에 없는 경우 원서버나 프락시에 요청

신선도 검사

  1. 먼저 정해진 기간이 지났는가? → 안 지났으면 신선하다.
  2. 정해진 기간이 지나면 재검사를 실행한다
  3. 재검사 시 기존 사본과 차이가 있는가> -? 차이가 있으면 새로운 사본을 보내준다.
    1. ETag 이용 시 기존 사본과의 차이 여부를 알 수 있다. 그래서 새로운 사본 대신 기존 사본을 이용할 수 있다.
    2. IMS 사용 시 기존 사본과의 차이 여부를 알 수 없어 무조건 새로운 사본을 보내준다

응답 생성

  • 캐시된 서버 응답헤더를 토대로 응답헤더 생성
  • Date 헤더 건드리지 말 것
  • 신선도 정보 삽입 (cache control age expires)

전송

  • 클라이언트에 돌려줌

로깅

  • 캐시적중과 부적중 횟수에 대한 통계를 갱신한다
  • 로그파일에 어떤 종류의 요청이 왔고 무슨일이 일어났는지를 기록한다.

유효기간과 나이

Cache-Control: max- age - 초단위의 값이 들어간다.
- 문서의 최대 나이를 정의하고 해당 초가 지나면 더이상 신선하지 않다고 판단한다.
Expires - 절대유효기간을 명시한다.
- 명시한 기간을 넘어가면 신선하지 않다고 판단한다.

서버 재검사

문서가 변경되었는지의 여부를 물어볼 필요가 있음을 의미한다.

  • 콘텐츠가 변경되었을 경우 새로운 사본을 가져와 갱신한 후 클라이언트에게 보내준다.
  • 콘텐츠가 변경되지 않았다면 새 만료일을 포함한 헤더들만 가져와서 캐시안의 헤더들만을 갱신한다

조건부 메소드와 재검사

캐시 재검사를 할 때 IMS와 INM 헤더를 이용한다.

If-Modified-Since : <date> - 주어진 날 이후로 수정되었다면 요청 메소드를 처리한다. -Last Modified 응답헤더와 함께 사용한다.
If-None-Match : <tagsa> - 문서에 대한 일려번호와 같이 동작하는 Etag와 함께 사영한다.
- Etag가 다를 경우에 문서를 갱신한다.

 

약한검사기와 강한검사기

W/ 를 이용하여 약한검사기와 강한검사기를 구분한다.

약한검사기

  • 콘텐츠가 조금 변경되더라도 ‘그정도면 같은것’(주석 등)이라고 서버가 주장할 수 있는 약한 검사기를 지원한다.

강한검사기

  • 콘텐츠가 바뀔때마다 변경된다.

캐시 최적화 방법

  • 캐시 최적화는 response header에 담아야 하는 것이기 때문에 웹서버에서 설정을 해주어야한다.
  • aws에서는 cloudfront에서 설정하면 될 거같은데 좀 더 알아봐야 한다

캐시 종류

  • no cache: 캐시를 사용하기 전에 서버에 먼저 검사 한다.
  • no store: 캐시 사용x
  • public: 모든환경에서 사용가능
  • private: 서버에서 서버간으로 이동할 때 외부서버에서도 캐싱을 적용하는데 private로 하면 브라우저에서만 캐시가 가능하다
    예를들어 개인정보에 민감한거나 공유가 되면 안되는 경우에 사용한다!
  • max-age: 캐시의 유효기간이며 초 단위이다.
ex)
cache-control: max-age=60
cache-control: private, max-age=600
cache-control: no-cache (=max-age=0)

리소스 별 효율적인 캐시 설정

💡 캐시는 항상 설정을 할 것, (단 리소스가 변경되지 않는다는 조건하에, 만약 리소스가 변경되는 경우엔 캐시를 적용하면 최신화가 되지 않는 문제가 발생할 수 있다.)

ex) 캐시의 기간이 1일 인경우
→ 이미지가 변경되었더라도 하루동안은 계속 똑같은 사진을 보내주게 됌, 문제점으로 변경사항이 발생해도 변경이 되었는지 클라이언트는 경험할 수 없음

HTML파일

  • html이 만약 변경되었으나 캐시가 설정되어 있으면 변경사항이 발생해도 기간동안 변하지않는다. 실제로 회사에서 서비스를 만들었을 때 배포후에도 변경되지 않았다고 컴플레인이 들어오기도 했었다.
  • no-store또는 no-cache를 사용한다. 상황에 맞게 선택해서 써야하지만 no-cache를 사용하면 변경사항이 없을 때 캐쉬를 사용할 수 있음으로 일반적인 경우에는 no-cache를 사용하는 것을 권장함JS파일
  • 자바스크립트의 경우 webpack으로 번들링을 하는 과정에서 파일에 해쉬값이 붙어 새롭게 배포를 하게되면 항상 새로운 파일로 생성하게된다.
  • 변경사항이 생기면 항상 새로운 파일로 생성이 되어 캐쉬값을 무한대로 걸어주어도 된다.
    • 파일명 main.31a12.js → main.132wqq.js 같이 변경
  • CSS파일
    • 자바스크립트와 동일
  • img 파일
    • 변경되지 않는 이미지는 무한으로 걸어준다.
    • 변경되는 이미지에는 해쉬값을 설정하며 자바스크립트파일처럼 변경되었을 때 최신데이터로 업데이트가 될 수 있게 해주는 것이 좋다

결론

html만 no-cache를 권장하고 js,css,img는 해쉬파일로 만들고 캐쉬를 최대한 길게 설정하는 것이 좋다.

html no-cache
js,css,img public,max-age=31536000(1y)

setHeaders: (res, path) => {
    if (path.endsWith(.html)) {
        res.setHeader('Cache-Control', 'no-cache')
    } else if (path.endsWith(.js) || path.endsWith(.css) || path.endsWith(.webp)) {
        res.setHeader('Cache-Control', 'public, max-age=3156000')
    } else {
        res.setHeader('Cache-Control', 'no-store')
    }
}

출처

  • http완벽가이드
  • 웹 성능 최적화 by 유동균
  • 웹 성능 최적화 기법

'프론트엔드' 카테고리의 다른 글

yarn berry로 monorepo 만들기  (2) 2023.03.10
브라우저 최적화 -Reflow, Repaint  (0) 2023.03.09
브라우저 렌더링 최적화 - LCP  (0) 2023.03.09