Chapter8. HTTP 헤더 & 캐시
카테고리: Network
인프런에 있는 김영한님의 모든 개발자를 위한 HTTP웹 기본 지식 강의를 듣고 정리한 내용입니다.
중간에 등장하는 ppt 내용들은 모두 강의자료를 캡처한 것입니다.
✈️ 캐시
한 사용자가 같은 페이지를 반복적으로 요청한다고 가정해보자. 클라이언트는 네트워크를 통해 변경되지 않은 데이터를 계속 다운로드 받아야 한다. 이렇게 되면 브라우저 로딩 속도가 느려질 뿐만 아니라 비싼 인터넷 네트워크 비용을 지불해야 한다. 반복적으로 사용하는 데이터들을 재활용 할 수 있는 방법이 없을까? 이때 등장하는 개념이 바로 캐시⭐ 이다. 예를 들어 누구나 뒤로가기 버튼을 눌렀을 때 페이지가 빠르게 뜨는 경험을 했을 것이다. 이런 것들이 전부 캐시를 적용한 결과이다.
캐시 작동 방식
- 클라이언트가 요청한 데이터에 캐시를 적용할 경우 응답 메시지에 cache-control 헤더가 추가 된다.
- 캐시 제어 메시지를 받은 클라이언트는 응답 결과를 캐시 저장소에 저장한다.
- 이후 요청에 대해서는 캐시 저장소를 먼저 뒤지고 데이터가 유효하면 바로 사용한다.
- 서버와 네트워크 연결도 필요 없다.
- 만약 캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고 캐시를 갱신한다.
- 이때 다시 네트워크 다운로드가 발생한다.
✈️ 캐시 검증 헤더와 조건부 요청
캐시 유효 시간이 초과해서 서버에 다시 데이터를 요청하는 경우를 생각해보자.
- 서버에서 기존 데이터를 변경함 (캐시 데이터와 다름)
- 서버에서 기존 데이터를 변경하지 않음 (캐시 데이터와 같음)
만약 서버의 데이터가 캐시 데이터와 동일하다면 굳이 같은 데이터를 다시 다운받을 필요가 있을까? 이런 상황에서 캐시까지 재활용해버리는 지독한 방법이 존재한다.
Last-Modified & If-Modified-Since
- 클라이언트의 첫 요청 응답에 검증 헤더 Last-Modified(최종 수정 일시) 추가
- last-modifeid 데이터를 캐시와 함께 저장소에 저장
- 캐시 유효 시간이 초과한 이후 데이터를 요청할 시 데이터가 변경되었는지 서버에 물어봄
- 요청 메시지에 조건부 요청 헤더 If-Modified-Sicne(이때 이후로 바뀌었어?) 추가
- 데이터 변경
- 200 OK (응, 바뀜)
- 모든 데이터 전송 (BODY 포함)
- 데이터 미변경
- 304 Not Modified (아니, 안바뀜)
- 헤더 데이터만 전송 (BODY 미포함)
- 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시 메타 정보 갱신
- 캐시 데이터 재활용
- 결과적으로 요청&응답 네트워크가 발생하지만 헤더 정보만 다운로드하므로 매우 효율적이다.
ETag & If-None-Match
Last-Modified, If-Modified-Since 단점
- 1초 미만 단위 캐시 조정이 불가능
- 날짜 기반의 로직 사용
- 날짜는 다르지만 같은 데이터인 경우 ( ex. A -> B 수정, 다시 B -> A 수정)
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
- ex) 스페이스나 주석은 변경되어도 캐시를 유지하고 싶은 경우
ETag 등장 😲
- ETag (Entity Tag)
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠 (사용자 지정, Hash값)
- ex) ETag: “v.1.0”, ETag: “a2jiodwjekjl3”
- 데이터가 변경되면 이름 바뀜 (Hash값 달라짐)
- 진짜 단순하게 ETag만 보내서 같으면 유지, 다르면 갱신
✈️ 캐시 제어 헤더
- Cache-Control: 캐시 제어
- Pragma: 캐시 제어 (HTTP이전 버전 하위 호환)
- Expires 캐시 유효 기간 (HTTP이전 버전 하위 호환)
Cache-Control
- Cache-Control: max-age
- 캐시 유효 시간 (초 단위)
- Cache-Control: no-cache
- 데이터 캐시해도 되지만, 항상 Origin 서버에 검증해라 (이름 주의!)
- Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)
Pragma
- no-cache 기능
- HTTP 1.0 하위 호환
Expires
- 캐시 만료일 정확한 날짜로 지정
- ex) expires: Mon, 01 Jan 1990 00:00:00 GMT
- HTTP 1.0 부터 사용
- cache-Control: max-age와 함께 사용하면 Expires는 무시
- cache-Control: max-age 사용 권장
✈️ 프록시 캐시
우리가 youtube를 볼 때 모든 요청을 미국에 있는 원 서버에 보내야 할까? 동영상의 경우 특히 데이터 변경이 적을 텐데, 캐시의 개념을 이용하면 보다 효율적인 네트워크 통신이 가능하지 않을까?
그림과 같이 클라이언트와 지리적으로 가까운 캐시 서버를 두면 효율적인 통신이 가능하다. 이러한 중간 서버를 프록시 캐시 서버라 한다.
- Cache-Control: public
- 응답이 public 캐시에 저장되어도 됨
- Cache-Control: private
- 응답이 해당 사용자 만을 위한 데이터임. private 캐시에만 저장(기본값)
- Cache-Control: s-maxage
- 프록시 캐시에만 적용되는 max-age
- Age: 60
- origin 서버에서 응답 후 프록시 캐시 내에 머문 시간 (초 단위)
✈️ 캐시 무효화
서버가 캐시 지정을 하지 않아도 웹 브라우저가 임의로 캐시 하는 경우가 종종 있다. “이건 진짜 캐시 하면 안돼”(ex. 통장 잔고 등등..) 할 때 쓰는 확실한 캐시 무효화 응답이 존재한다.
- Cache-Control: no-cache, no-store, must-revalidate
- Pragma: no-cache (HTTP이전 버전 하위 호환)
Cache-Control: no-cache
- 데이터 캐시해도 되지만, 항상 Origin 서버에 검증 (이름 주의!)
Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)
Cache-Control: must-revalidate
- 캐시 만료 후 최초 조회시 원 서버에 검증
- 원 서버에 접근 실패시 반드시 오류 발생 - 504(Gateway Timeout)
- 캐시 유효 시간이라면 캐시를 사용
No-Cache vs Must-Revalidate
No-Cache
- 클라이언트가 캐시 서버에 요청시 무조건 원 서버로 넘김
- 원 서버가 OK 하면 캐시 사용
- 원 서버에 접근 실패시 캐시 서버 재량으로 OK 가능
- 오류 보다는 이전 데이터라도 보여주자
Must-Revalidate
- 원 서버에 접근 실패시 무조건 오류 발생
댓글 남기기