본문 바로가기
HTTP

[HTTP] HTTP 헤더 캐시 이해하기

by 개미가되고싶은사람 2024. 3. 18.

HTTP 캐시(Cashe)의 등장 이유

사용자가 브라우저를 열람 시 많은 리소스(이미지, css, script 등등)들이 필요하다 이런 리소스들을 항상 서버에서 다운받고 이를 사용자한테 서비스를 제공한다면, 사용자들은 페이지 로딩 시 많은 시간을 보냄으로써 안좋은 서비스 경험을 만들수 있다 또 네트워크 사용량이 증가해서 서비스 제공자한테는 금전적으로 부담이 된다. 이런 걸 해결하기 위해서 무조건 필요한 리소스들을 매 번 서버에서 받아오는게 아니라 어느 저장소에 저장하고 같은 요청이오면 저장소에서 리소스들을 꺼내면 되지 않을까 해서 만들어진게 바로 cashe라는 개념이다

 

 

캐시(Cashe)의 개념

캐시는 사용자가 서비스를 이용하는 과정에서 재사용할 수 있는 리소스들을 캐시 저장소에 임시로 저장하는 공간이다
캐시를 이용하는데 가장 중요한 Cache-Control 헤더는 네트워크 통신 기간과 클라이언트의 전체 트래픽 양을 줄일 수 있다

 

 

그럼 캐시를 왜 사용해야 할까?

  • 성능 향상: 서비스에 필요한 리소스들을 재사용함으로써 브라우저 로딩 속도가 빨라진다.
  • 데이터 전송량 감소: 다시 다운 받지 않기 때문에 네트워크 사용량을 줄일 수 있다.
  • 서버 부하 감소: 서버는 해당 자원들에 대한 요청을 처리하는 데 드는 부담을 줄일 수 있다.

 

이런 캐시를 제어할 수 있는 HTTP 헤더 종류를 알아보자

 

캐시 제어 헤더 종류

  • Cache-Control: 캐시 제어
  • Pragma: 캐시 제어(하위 호환)
  • Expires: 캐시 유효 기간(하위 호환)
더보기

Expires

  • 이 헤더는 캐시의 만료일을 지정하는 데 사용
  • 정확한 시간을 지정하는 대신, 특정 날짜와 시간을 사용하기 때문에 이를 유지하기가 어려움
  • 캐시 갱신에 대한 유연성이 부족하고, 캐시된 콘텐츠가 적절히 갱신되지 않을 수 있음.

Pragma

  • HTTP/1.0에서 사용되던 캐시 제어 헤더
  • Cache-Control 헤더는 Pragma 헤더보다 더 포괄적인 캐시 제어 기능을 제공하며, 더욱 유연하고 표준화된 방식으로 동작함
  • Pragma 헤더는 오래된 버전의 HTTP 프로토콜과의 호환성을 유지하기 위해 사용되지만, 대부분의 경우에는 Cache-Control 헤더를 사용하는 것이 권장됨.
  • Pragma 헤더에는 "no-cache"라는 값이 주로 사용되는데, 이는 캐시된 콘텐츠를 재사용하지 않고 항상 서버로부터 새로운 콘텐츠를 가져와야 함을 나타냄.
    • 그러나 이 값은 Cache-Control 헤더의 "no-cache" 지시자와 다르게 작동할 수 있고, Pragma 헤더를 해석하지 않는 캐시 서버가 있을 수 있다
    • "no-cache" 기능을 구현하려면 Cache-Control 헤더를 사용하는 것이 더 일반적이고 신뢰할 수 있는 방법
  • 현재 Pragma 헤더는 오래된 버전의 HTTP와의 호환성을 위해 사용되거나 특정한 상황에서만 필요한 경우에 사용한다

 

Cache-Control

파라미터 종류

  • max-age : 캐시 유효 시간을 초 단위로 지정
  • no-cache : 데이터는 캐시해도 되지만, 항상 원(Origin) 서버에 검증후 사용
  • no-store : 주로 데이터에 민감한 정보가 포함되어 있는 경우에 사용하며, 저장하지 않고 최대한 빨리 삭제
  • public : public 캐시에 저장 및 프록시 캐시 서버 저장 가능
  • private : public 캐시에 저장 불가
  • s-maxage : 프록시 캐시 서버에 적용되는 max-age
  • must-revalidate : 캐시 만료 후 최초 조회 시 원 서버에 검증해야 할 때 설정합니다. 즉, 만료된 캐시만 서버에 확인을 받도록 합니다. 

 

캐시 기본 동작

1. 클라이언트에서 이미지를 요청한다. 
2. 서버에서는 해당 이미지를 응답해준다. 이때 서버는 HTTP 메시지에 Cache-Control 헤더를 추가하고 max-age를 사용하여 유효 시간을 설정
3. 서버로부터 응답을 받게되면, 클라이언트에서는 cache-control 헤더를 이해하고 웹브라우저 캐시에 응답 결과를 미리 지정한 시간 동안 저장하게 된다.
4. 클라이언트가 이미지를 재차 요청하면 이때 서버에게 가는 것이 아닌 우선 캐시 저장소를 조회하게 된다.
5. 만약 캐시가 아직 보관된 상태라면, 캐시에서 자료를 가져오게 된다.

 

그런데 캐시 유효 기간이 만료된 후에 클라이언트가 다시 같은 자료를 요청할 경우 어떻게 될까요?

 

 

캐시 유효 시간이 초과해서  다시 요청할 때 2가지 상황이 존재한다...

  1. 기존 데이터를 변경하지 않은 경우(Last-modified, if-modified-since) 
  2. 서버에서 기존 데이터를 변경하는 경우(Etag, If-None-Match) 

첫번째 상황

이 경우에는 서버에서 데이터를 변경하지 않았다는 검증이 필요하다 그래서 검증 헤더(Last-Modified)라는게 존재한다.

Last-Modified속성는 해당 데이터의 최종 수정일을 기록하는 속성이다.

브라우저가 요청 헤더에 if-modified-since 라는 속성을 보낸다.

서버가 해당 요청 헤더를 받으면 if-modified-since속성이랑 Last-Modified 이랑 비교 후 판단을 한다.

서버가 수정이 안됬다고 판단하면 Http 응답을 할 때 304 Not Modefied라고 보낸다. 이렇게 반응하면 HTTP Body가 없다.

 

이렇게 Body를 빼고 전송을 한다. 그렇게 되면 헤더 부분만 전송하고 Body 부분을(데이터 용량) 전송하기 않기 때문에 네크워트에 부담이 줄어들게 된다. 이제 다시 캐시 저장소에서 해당 캐시를 다시 사용해도 된다고 판단해 해당 캐시를 다시 세팅한다. 하지만 이 방법에도 단점이 있다. 데이터를 수정하다가 최종적으로 그 전 데이터 결과가 같은 경우 다시 다운을 받아야 된다.

 

두번째 상황

캐시용 데이터에 임의의 고유한 버전 이름을 ETag에 주어서 If-None-Match랑 비교해서 같으면 유지, 다르면 다시 다운 받는다

 

 

참조: 모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한