HTTP - 8) 캐시와 조건부 요청

박재현·2023년 5월 20일
0

🔎 캐시 기본 동작

📌 캐시가 없을 때

  • 데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다.
  • 인터넷 네트워크는 매우 느리고 비싸다.
  • 브라우저 로딩 속도가 느리다.
  • 느린 사용자 경험

📌 캐시 적용

  • 응답값으로 HTTP header에 cache-control 값을 넣어줘서 캐시 유효 시간을 설정
    -> 해당 응답 바디를 브라우저 캐시에 저장, 두번째 요청부터는 캐시에서 해당 요청을 조회해서 그 값을 가져온다.

  • 캐시 덕분에 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다.

  • 비싼 네트워크 사용량을 줄일 수 있다.

  • 브라우저 로딩 속도가 매우 빠르다.

  • 빠른 사용자 경험


if) 캐시 유효시간이 초과된다면?
-> 브라우저는 서버에 다시 한 번 데이터를 요청해서 받아와야 한다.
이러한 과정을 줄이기, 없애기, 최적화 하기 위해 사용하는 방법이 검증 헤더, 조건부 요청을 활용한다.

  • 검증 헤더 (서버 응답)
    • Last-Modified - 날짜
    • eTag - 데이터 버전 및 고유 이름(해쉬 값)
    • 브라우저에 저장된 캐시 데이터와 서버 데이터가 같은지 검증하기 위함
  • 조건부 요청 헤더 (브라우저 요청)
    • If-Modified-Since (Last-Modified 사용) - 날짜
    • If-None-Match (Etag 사용) - 데이터 버전 및 고유 이름(해쉬 값)

=> 검증 헤더와 조건부 요청 헤더로 데이터 검증 후,

  • 데이터가 변하지 않았다면 서버로부터 304 Not Modified 응답 - Body(데이터) 미포함
    => 너의 브라우저 캐시로 리다이렉트해서 그 데이터 사용해라!

  • 데이터가 변경되어서 다시 데이터를 받게 된다면 200 OK - Body(데이터) 포함

🔎 검증 헤더와 조건부 요청1

  • 브라우저 요청 헤더(If-Modified-Since) + 서버 응답(Last-Modified) 헤더 사용
  • 날짜를 통한 판단

📌 검증 헤더 추가

서버는 응답을 내려줄 때 데이터, cache-control 헤더와 함께,
날짜를 기록한 Last-Modified를 헤더에 추가해서 HTTP응답을 내려주고

클라이언트는 데이터, cache-control과 함께 Last-Modified 정보도 함께 저장한다.

=> 브라우저는 cache-control 시간 까지는 브라우저 캐시를 활용함

만약 캐시 시간이 초과된다면, 원래는 서버에 다시 한 번 요청을 해서 데이터를 받아와야 했지만,

브라우저는 요청과 함게 이전 캐시에 저장된 Last-Modified 정보로,
조건부 요청 헤더인 if-modified-since를 추가해 서버에 데이터를 요청하게 된다.

서버는 헤더에 있는 if-modified-since 정보를 보고, 데이터가 변경되지 않았다면 상태코드 304 Not Modified와 함께 헤더에 Last-Modified를 갱신해 클라이언트에 응답을 내려준다.

브라우저는 해당 헤더의 Last-Modified, cache-control 정보로 브라우저 캐시를 갱신하고, 해당 캐시를 사용하게 된다.

=> 결과적으로 네트워크 다운로드가 발생하긴 하지만, 용량이 훨신 적은 헤더 정보만 내려줌으로써 네트워크 부하를 줄일 수 있고, 속도 측면에서 최적화가 가능 (유저 경험 ↑)


색깔이 연한 것 -> 캐시에서 불러온것

🔎 검증 헤더와 조건부 요청 2

앞 선 Last-Modified, If-Modified-Since의 단점

  • 날짜 기반으로 사용되기 때문에, 1초 미만(0.x초) 단위로는 캐시 조정이 불가능
  • 만약 서버에서 해당 데이터를 가공하는 로직에 주석이나 들여쓰기와 같은 변경사항이 발생했다고 가정했을 때,
    서버 입장에서는 변경사항은 발생했지만 실제 데이터는 변경되지 않았다
    -> 그러면 Last-Modfied 정보가 달라져, 데이터를 다시 응답해줘야 할 수 있다.

=> 이와 같은 상황을 해결하기 위해 Etag 활용
(해당 정보에 대한 메타데이터와 정보를 담고 있으며, 파일 정보가 변하지 않는 이상 해쉬 값 기반의 Etag는 변하지 않는다)


  • 브라우저 요청 헤더(If-None-Match) + 서버 응답(Etag) 헤더 사용

  • Etag(Entitiy Tag)를 통해 별도의 캐시 로직을 관리할 수 있다.

  • 캐시용 데이터에 잉의의 고유한 버전 이름을 달아둠(변경 시 해당 값 변경)

    • ex) Etag: "v1.0", Etag: "a2344ff4"

📌 검증 헤더 추가

  • 웹 브라우저가 서버 요청 시, 서버는 응답 헤더로 데이터와 함께 Etag 헤더를 내려줌
  • 브라우저는 해당 데이터와 함께, Etag를 저장

  • 브라우저 캐시 시간이 초과되었으면 브라우저는 캐시에 저장된 Etag값을 If-None-Match 헤더에 담아서 서버로 요청을 보냄

  • 서버에서 만약 해당 데이터가 변경되지 않았다면(Etag가 바뀌지 않았다면) 304 Not Modified 상태 코드(+ Etag)를 내려줌 (HTTP Body X)

  • 브라우저는 캐시 데이터를 갱신해서 사용하게 됨
  • 캐시 제어 로직을 서버에서 완전히 관리
  • 클라이언트는 단순 히 이값을 서버에 제공하고 검증 받고 사용하는 역할만

🔎 캐시와 조건부 요청 헤더

📌 캐시 제어 헤더

  • Cache-Control: max-age
    • 캐시 유효시간, 초 단위
  • Cache-Control: no-cache
    • 데이터는 캐시해도 되지만, 항상 원(origin)서버에 검증하고 사용
    • 캐시 데이터를 사용할 때, 서버에 If-Modified-Since, If-None-Match 헤더와 함께 서버에 요청을 보내고, 서버 응답을 바탕으로 데이터를 사용하라는 뜻
  • Cache-Control: no-store
    • 데이터에 민감한 정보가 있으므로 저장하면 안됨 (메모리에서 사용하고 최대한 빨리 삭제)

📌 Expires

  • 캐시 만료일을 정확한 날짜로 지정
    • expires: Mon, 01 Jan 2021 00:00:00 GMT
  • HTTP 1.0 부터 사용
  • 현재는 더 유연한 Cache-Control: max-age 권장
  • Cache-Control: max-age와 함께 사용된다면 Expires는 무시된다.

📌 Pragma

  • Pragma: no-chee
  • HTTP 1.0 하위 호환 (HTTP 1.0 프로토콜 이전 버전 캐시 설정)

🔎 프록시 캐시

유투브와 같이 다른 국가 서비스를 활용하고 있는 경우, 실제 그 국가로 요청을 보내고 응답을 받아오려면 긴 시간이 걸릴 수 있다.

이를 해결하기 위해 일반적인 글로벌 서비스의 경우 해당 국가에 프록시 캐시 서버를 두고 클라이언트는 해당 데이터를 서빙 받아 사용하게 된다. (CDN - Content Delivery Network, AWS의 Cloud Front)

유투브에서 사람들이 많은 컨텐츠를 보려고 하면 빠르게 시청이 가능하다.
이미 많은 사람들이 해당 컨텐츠를 봤기 때문에 프록시 캐시 서버에 해당 컨텐츠가 저장되어 있어 빠르게 응답을 받아 시청이 가능
(but, 조회수가 거의 없는 영상을 시청하려면 origin 서버에서 데이터를 받아와야 해 시간이 좀 더 걸림)

🔎 Cache-Control (캐시 지시어)

  • Cache-Control: public
    • 응답이 public 캐시에 저장되어도 됨
  • Cache-Control: private
    • 응답이 해당 사용자만을 위한 것, private 캐시에 저장(기본값)
  • Cache-Control: s-maxage
    • 프록시 캐시에만 적용되는 max-age
  • Age: 60 (HTTP 헤더)
    • Origin 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)

🔎 캐시 무효화

별도의 Cache-Control을 사용하지 않더라도, 브라우저는 get요청인 경우 임의로 캐시를 해버린다...
하지만 고객 계좌 정보와 같이 민감, 중요 데이터의 경우 캐시를 적용하면 안된다

📌 확실한 캐시 무효화 응답

  • Cache-Control: no-cache, no-store, must-revalidate
  • Pragma: no-cache
    • HTTP 1.0 하위 호환 (이 전 버전 HTTP 프로토콜에서 캐쉬를 저장했을 때)

📌 캐시 지시어

  • Cache-Control: no-cache
    • 데이터는 캐시해도 되지만, 항상 원(origin)서버에 검증하고 사용
    • 캐시 데이터를 사용할 때, 서버에 If-Modified-Since, If-None-Match 헤더와 함께 서버에 요청을 보내고, 서버 응답을 바탕으로 데이터를 사용하라는 뜻
  • Cache-Control: no-store
    • 데이터에 민감한 정보가 있으므로 저장하면 안됨 (메모리에서 사용하고 최대한 빨리 삭제)
  • Cache-Control: must-revalidate
    • 캐시 만료 후 최초 조회시 원 서버에 검증해야 함
    • 원 서버 접근 실패 시 504 Gateway TimeOut 반드시 발생 시켜줌
      (🤔 그래서 프록시 서버 죽으면 nginx 에러뜨는데, 원 서버 죽으면 504 뜨는건가?)
    • must-revalidate는 캐시 유효시간이라면 캐시를 사용함
  • Pragma: no-cache
    • HTTP 1.0 하위 호환

📌 no-cache vs must-revalidate

no-cache의 경우 프록시 캐시 서버 설정에 따라 orgin 서버에 접근이 불가하더라도 이전 데이터 기반으로 응답을 내려줄 수도 있음

must-revalidate는 origin 서버에 접근이 안되는 경우 프록시 서버 설정에 관계없이
무조건 504 Gateway TimeOut을 내려주게 되어 있다.

0개의 댓글

관련 채용 정보