HTTP 헤더2

최은창·2024년 3월 28일
post-thumbnail

캐시 기본 동작

캐시가 없을때

캐시가 없을땐 star 이미지 파일을 서버에 요청할때마다 계속 네트워크를 통해 다운로드 받아야 한다. 이렇게 되면 브라우저 로딩 속도는 느려지게 되고 결과적으로 사용자는 느린 경험을 하게 된다.

캐시를 적용할 때

캐시를 적용하면 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다. 또한 비싼 네이퉈크 사용량을 줄일 수 있으며 브라우저 로딩 속도는 매우 빠르게 된다. 이로써 사용자는 빠른 경험을 하게 된다.

캐시 시간이 초과될 때


캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고, 캐시를 갱신한다. 이때 다시 네트워크 다운로드가 발생한다.
이를 스테일(stale-신선하지 않은)하다 라고 한다.

근데 데이터가 같은데 시간 초과때문에 다시 받으면 낭비가 되지 않을까?

캐시 유효 시간이 초과해서 서버에 다시 요청하면 다음 두 가지 상황이 나타난다.
1. 서버에서 기존 데이터를 변경한 경우 A 데이터B 데이터
2. 서버에서 기존 데이터를 변경하지 않은 경우 A 데이터A 데이터

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

생각해보면 데이터를 전송하는 대신에 저장해 두었던 캐시(로컬캐시)를 재사용할 수 있다. 이런 경우 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법이 필요하다.


캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면 304 Not Modified 헤도로 응답한다. 물론 이때 메시지 바디는 없다! 또한 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신하고 클라이언트는 캐시에 저장되어 있는 데이터를 재활용하게 된다. 결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드하게 된다. 즉 네트워크 다운로드가 줄어들게 되며 이는 매우 실용적인 해결책이 된다.

검증 헤더와 조건부 요청

  • 검증 헤더 : 캐시 데이터와 서버 데이터가 같은지 검증하는 헤더이며 종류는 Last-Modified, ETag가 있다
  • 조건부 요청 헤더 : 검증 헤더로 조건에 따라 다르게 사용된다.
    1. if-Modified-Since : Last-Modified사용
    2. if-None-Match : ETag 사용

→ 조건이 만족하면 200 OK 만족하지 않으면 304 Not Modified를 보낸다.

예시

if-Modified-Since 이후 데이터가 수정되었으면?

  • 데이터가 변경되지 않은 경우
    • 캐시 :2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 10:00:00
    • 304 Not Modified, 헤더 데이터만 전송(BODY 미포함) → 리다이렉션
    • 결과적으로 전송 용량은 0.1M로 줄어들게 된다.
  • 데이터가 변경된 경우
    • 캐시 : 2020년 11월 10일 : 10:00:00 vs 서버 : 2020년 11월 10일 11:00:00
    • 200 OK, 모든 데이터 전송(BODY 포함)
    • 결과적으로 전송 용량 1.1M으로 모든 데이터를 받게 된다.

팁 : 개발자 도구F12에서 색이 연한것은 캐시이며 색이 진한 것은 다운로드 받은 것들이다!

Last-Modified, If-Modified-Since 단점

0.x초 처럼 1초 단위로는 캐시 조정을 할 수 없다. 또한 날짜 기반의 로직을 사용해야 한다.
만약 데이터를 수정해서 날짜가 다르지만 같은 데이터를 수정해서 데이터 결과가 똑같은 경우나 서버에서 별도의 캐시 로직을 관리하고 싶은 경우에는 ETag를 사용하면 된다.
→ 예: 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우

ETag, If-None-Match

  • Etag(Entity Tag)는 캐시용 ㄷ게이터에 임의의 고유 버전 이름을 달아두는 기능이다.
    ETag : "v1.0", Etag: "a2jiodwjekjl3"
  • 데이터가 변경되면 이 이름을 바꾸어서 변경함(Hash를 다시 생성)
    ETag : "aaaa"Etag: "bbbb"
  • 진짜 단순하게 Etag만 보내서 같으면 유지, 다르면 다시 받기

해쉬는 파일이 동일하면 똑같은 결과가 나온다 즉 파일의 컨텐츠가 가틍면 똑같은 해쉬 값이 나온다.

ETag는 진자 단순하게 같으면 캐시를 유지하고, 다르면 데이터를 다시 받게 한다. 이는 캐시 제어 로직을 서버에서 완전히 관리하며 클라이언트는 단순이 로컬 ETag 값을 서버에게 제공할 뿐이다.(클라이언트는 캐시 메커니즘을 모른다 -> 블랙박스)
다음 경우에 ETag를 사용한다.

  • 서버는 배타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지 (억지 느낌)
  • 애플리케이션 배포 주기에 맞추어 ETag 모두 갱신(가능성 있음)

캐시와 조건부 요청 헤더

케시 제어 헤더

캐시 제어 헤더는 다음 3가지로 제어 할 수 있다.

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

Cache-Control -캐시 지시어(directives)

  • Cache-Control: max-age : 캐시 유효 시간, 초 단위 즉 얼마만큼 유효한지 결정

  • Cache-Control: no-cache : 데이터는 캐시해도 되지만, 항상 origin서버에 검증하고 사용해야 한다. ( 중간 캐시 서버가 검증해주지 않는다.)

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

Pragma - 캐시 제어(하위 호환)

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는 무시된다.

정리

  • 검증 헤더(Vaildator)
    • ETage : "v1.0", ETag: "asid93jkrh2l"
    • Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT
  • 조건부 요청 헤더
    • If-Match, If-None-Match : ETag값 사용
    • If-Modified-Since, If-Unmodified-Since: Last- Modified값 사용

프록시 캐시

프록시 캐시 서버가 없을때

캐시를 받을때 원 소스를 제공하는 원 서버에 접근해서 캐시를 받으면 다운로드 하는 속도가 꽤나 길다 (youtube 생각하기)

프록시 캐시 서버 도입

프록시 캐시 서버를 도입하면 보통 첫사용자가 느리고 다머지 다음 사용자들은 빠르게 접근이 가능하다.

이때 사용하는 Cache-Control 지시어는 다음과 같다.

  • Cahce-Control:public
    *응답이 public 캐시에 저장되어도 된다.
  • Cahce-Control:private
    • 응답이 해당 사용자만을 위한 것이며 Private 캐시에 저장해야 한다(기본값)
      -> Froxy 캐시 서버에 저장되면 안된다!
  • Cahce-Control:s-maxage
    • 프록시 캐시에만 적용되는 max-age이다. (중요한건 아님)
  • Age: 60(HTTP 헤더)
    • 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초), (중요한건 아님) -> 이건 잘 모르겠다.

캐시 무효화

"이런건 절대로 캐시가 되면 안돼" 할 때 사용하는 Cache-Control 지시어는 다음과 같다.

Cache- Control: no-cache, no-store, must-revalidate
Pragma: no-cache // HTTP 1.0 하위 호환을 위해

위 내용을 다 넣어야 된다. 과거부터 오래되어서 꼭 하위 호환 버전도 다 넣어줘야된다. 왜냐하면 GET 요청인 경우 Web 브러우저가 임의로 캐시해버리기 때문이다!

  • Cache- Control: no-cache
    • 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용(이름에 주의)
  • Cache- Control: no-store,
    • 데이터에 민감한 정보가 있으므로 저장하면 안된다. → 메모리 내용도 최대한 삭제
  • Cache- Control: must-revalidate
    • 캐쉬 만료후 최초 조회시 원 서버에 검증을해야 하며 원 서버 접근 실패시 반드시 오류(504-Gateway Timeout)가 발생해야한다.
    • must-revalidate는 캐시 유효 시간이라면 캐시를 사용한다.
  • pragma: no-cache → HTTP 1.0 하위 호환

네이버는 위 내용을 다 포함하고 있다!


no-cache는 오류가 발생해도 예전 데이터를 보여준다.

must-revalidate는 오류가 발생하면 504오류를 보낸다. → 통장잔고는 오류가 나면 예전 데이터를 보여주는게 아닌 오류를 보내줘야 된다.!

profile
비슷한 어려움을 겪는 누군가에게 도움이 되길

0개의 댓글