CS

8. HTTP 헤더-캐시와 조건부 요청

wooweee 2023. 1. 23. 11:29
728x90
캐시 기본 동작

 

 

1. 캐시가 없을 때

    데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다. - 비용적으로 안좋다.

    브라우저 로딩 속도가 느리다. 

 

 

 

2. 캐시 적용

    첫 요청때 server한테 받은 data를 브라우저 캐시 보관함에 지정된 시간 만큼 보관한다.

    캐시 가능 시간 동안 서버에서 다시 data를 받는 네트워크를 사용하지 않아도 된다 - 비용 절감

 

 

문제점

    캐시 시간이 초과된 후 재요청시, 데이터의 변화에 없어도 서버를 통해 데이터를 다시 조회하고, 캐시를 갱신한다.

    = 다시 네트워크 다운로드가 발생

 

 

 

 

검증 헤더와 조건부 요청 1

 

 

검증

    캐시 만료후에도 서버에서 데이터를 변경하지 않음

    -> 데이터 전송 대신 저장해 두었던 케시 재사용 하는 것이 효율적

    -> client data와 server data 가 같음을 확인할 방법이 필요하다. (= 검증 헤더 필요)

 

 

작동원리

    첫 응답 때 표현헤더에 Last-Modified: 2020년 11월 10일 10:00:00 검증헤더 넣어서 보냄

   

    응답결과를 브라우저가 가지고 있는 캐시 저장소에 보관(캐시유효시간, 데이터 최종수정 시간 메타정보 가짐)

   

    재 요청 때 캐시유효시간이 초과 되었다.

    하지만 데이터 최종수정 시간 헤더를 받았기 때문에 요청을 보낼 때 조건부요청 헤더를 같이 넣어서 보낸다.

    조건부요청 : if-modified-since: 2020년 11월 10일 10:00:00 

    

    서버에서의 데이터 최종수정 시간동일할 때, 표현헤더만 다시 응답으로 돌려보냄, 응답에 HTTP Body 없다.

       1) 0.1M만 사용.   *(위의 예시에서 헤더: 0.1M, 바디: 1.1M   Total: 1.1M 네트워크 사용했었다.)

       2) 표현헤더는 304 Not Modified, cache-control: max-age=60를 보내서 캐시유효시간 갱신 redirection을 통해서 캐시 저장소의 캐시를 사용한다.

 

 

    결과

        네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드 하므로 매우 실용적인 해결책 이다.

 

 

 

 

검증 헤더와 조건부 요청 2

 

 

종류

    검증헤더           :  Last-Modified                                            ETag

    조건부 요청헤더:  If-Modified-Since: Last-Modified 사용, If-None-Match: ETag 사용

                               -> 조건이 true 일때, 200 OK 응답, false 일때, 304 Not Modified

 

 

If-Modified-Since: Last-Modified 단점

    1초 미만 단위로 캐시 조정이 불가능

    날짜 기반의 로직 사용 -> 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 동일할 경우 (A ->Aa -> A)

    서버에서 별도의 캐시 로직을 관리하고 싶은 경우(주석, 스페이스 같이 영향없는 변경에서 캐시 유지가 안됨)

 

 

If-None-Match: ETag

    위에 단점을 해결한 검증 방법

  

    작동원리는 동일하다 단지 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠 (날짜기반 대신 -> 고유 이름)
    ex) ETag: "v1.0", ETag: "a2jiodwjekjl3"

   

   데이터가 변경되면 이 이름을 바꾸어서 변경함(Hash를 다시 생성) = 서버에서 캐시 로직 관리 가능
    ex) ETag: "aaaaa" -> ETag: "bbbbb"

 

    진짜 단순하게 ETag만 보내서 같으면 유지, 다르면 다시 받기

    ex) 서버는 배타 오픈 기간 3일 동안 파일일 변경되어 변경되어도 Etag를 동일하게 유지 후 어플 배포 주기에 맞추어 ETag 모두 갱신

 

 

 

 

캐시 헤더

 

 

캐시제어 헤더

 

    Cache-Control : 캐시 제어(핵심)

        Cache-Control: max-age         캐시 유효 시간, 초 단위

        Cache-Control: no-cache        데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용 - (프록시 캐시와 관련)

        Cache-Control: no-store          데이터에 민감한 정보가 있으므로 저장하면 안됨 (메모리에서 사용하고 최대한 빨리 삭제)

 

        기타(프록시 캐시 서버 관련)

        Cache-Control: public         응답이 public 캐시에 저장되어도 됨 - 프록시 캐시 서버에 저장

        Cache-Control: private        응답이 해당 사용자만을 위한 것, private 캐시에 저장해야 함(기본값) - client browser 저장

        Cache-Control: s-maxage   프록시 캐시에만 적용되는 max-age

        Age: 60 (HTTP 헤더)              오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)

 

       기타(캐시 무효화): 이 페이지는 절대 캐시 되면 안될때 넣어줌

        Cache-Control: no-cacheno-storemust-revalidate    +  Pragma: no-cache : 이렇게 2개 작성하면 거의 다 해결됨.

       

        Cache-Control: must-revalidate

                                       캐시 만료후 최초 조회시 원 서버에 검증, 원 서버 접근 실패시 반드시 오류가 발생 - 504(Gateway Timeout)
     

 

 

    Pragma: 캐시 제어(하위 호환)  - 거의 사용X

        Pragma: no-cache

        HTTP 1.0 하위 호환

 

    Expires: 캐시 유효 기간(하위 호환)

        expires: Mon, 01 Jan 1990 00:00:00 GMT

        캐시 만료일 지정(하위 호환) - 캐시 만료일을 정확한 날짜로 지정

        HTTP 1.0 부터 사용

        Cache-Control: max-age 권장 - Cache-Control: max-age와 함께 사용하면 Expires는 무시

 

 

 

프록시 캐시
더보기
 

 

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

Cache-Control: public과 private

CDN과 같은 중간 서버가 특정 리소스를 캐시할 수 있는지 여부를 지정하기 위해 Cache-Control 헤더 값으로 public 또는 privat을 추가할 수 있습니다.

public은 모든 사람과 중간 서버가 캐시를 저장할 수 있음을 나타내고, private은 가장 끝의 사용자 브라우저만 캐시를 저장할 수 있음을 나타냅니다.

기존과 max-age 값과 조합하려면 Cache-Control: public, max-age=86400 과 같이 콤마로 연결할 수 있습니다.

 

프록시 캐시를 이해하기 전에 다시 한번 캐시에대해서 정리한다.

 

  캐시는 client 요청에 server가 응답을 하면 server 측에서 응답 http header에 Cache-Control: xx,xx,xx 이란 문구를 넣어준다.

그러면 client는 응답을 받음과 동시에 browser cache에 받았던 data를 넣는다.

그래서 동일 요청을 할 때 browser는 먼저 cache부터 확인을 한다.

 

  프록시 서버는 프록시(=대신) , 오리진 서버 대신에 서버처럼 역할을 해준다.

프록시 서버도 1) 오리진 서버로부터 cache를 미리 다 받는 서버가 있고 2) 요청이 올때마다 오리진으로 부터 data를 받고 프록시 서버의 프록시 캐시에 data를 저장하는 방식이 존재.

 

  이처럼 본사가 미국은 오리진 서버에게 요청을 보낼 것을 동일 한국지사 프록시 서버 = CDN 에게 요청을 보내서 더 빠르게 data를 받는다. 이 때 프록시 서버도 서버이기 때문에 처음 우리가 배운 캐시의 작동 원리 마냥 브라우저가 브라우저 캐시에 프록시로부터 받은 data 를 캐시에 넣어서 재사용시 또 사용할 수 있다. - 프록시로 부터 부라우저 캐시에 넣어서 재사용할 수 있는지 아닌지는 캐시 정책에 따라서 다르다.

 

  그리고 또다른 프록시 서버의 장점( 프록시 서버 2) 장점)은 첫 client가 요청을 해서 오리진 data사본(=프록시 캐시)을 저장하고 있게 되면 그 다음 client들이 요청을 할때 오리진 까지 갈 필요없이 사본을 뿌려준다. 아주아주 시간 단축이된다. 대규모 회사의 서비스의 경우 효과를 톡톡히 본다. 그러면 오리진 서버의 과부하도 막고 대역폭 또한 그렇게 크지 않아도 되게 된다.

 

정리

 여기서 Cache-Control: private, public이 있는데 , 다시 한번 강조하면 Cache-Control는 응답에서 지정할 수 있는 부분이다.

1) 그래서 오리진 서버 응답 측에서 public이라고 하면 프록시 서버에서도 cache가 저장, browser cache도 저장(정책에 따라 다름), 그 다음 client가 요청할 시 다들 동일한 data를 받을 수 있다. ex) 유튜브 시청

 

2) 반면 private은 오리진 서버에서 프록시 서버는 proxy cache로 저장하지 마 라고 하게 되어서 client의 browser에서만 cache를 저장하게 된다.

    ex) 로그인 되어진 화면 개인 정보 url이 만약 www.naver.woowee개인정보/설정창 이렇게 되어있는데 private이 아니라 public으로 되게 되면 프록시 서버에서 프록시 cache로 저장하게 되서 다른 나라 아프리카 사람들이 동일한 url을 치면 woowee의 개인 정보 창에 접속할 수 있게 된다.

 

3) 여기서 추가로 client에게 너무 중요한 개인 정보라 memory에서만 잠깐 data가 올라가고 바로 삭제 해야되는 cache는 캐시 무효화를 통해 해결한다. 

    Cache-Control: no-cacheno-storemust-revalidate Pragma: no-cache

 

 

 

no-cache vs must-revalidate

client web browser -> proxy Server -> origin server

 

공통: proxy에서 요청 데이터를 건들이면 안된다.

 

차이점: origin 서버에 문제가 발생해서 요청이 접근하지 못할 때 no-cache는 오류보다는 오래된 데이터라도 보여주고 must-revalidate는 무조건 504 error 날린다.

돈 문제같이 아주 중요한 경우에는 must-revalidate가 필수적이다.

 

Pragma: no-chace는 http1.1 이전 버전을 위해서 첨가한 것이다.

 

 

 

 

 

이전 발행글

2023.01.19 - [spring/HTTP] - HTTP 헤더 개요

 

HTTP 헤더 개요

HTTP 헤더 용도 : HTTP 전송에 필요한 모든 부가 정보 RFC 2616(과거) - > RFC7230~7235(현재) 변화 과거에는 헤더를 request,repond,general,entity 로 분류했고 메시지 바디 이름 또한 엔티티 본문이라 명했다. * 이

code-is-me.tistory.com


출처: Inflearn-모든 개발자를 위한 HTTP 웹 기본 지식