HTTP (7) - 캐시와 조건부 요청 (Last-Modified / ETag)
[ 캐시 제어 헤더 ]
[ Cache-Control ]
- 설명
- 캐시를 제어하는 헤더 필드 / Pramra, Expires 헤더를 완전히 대체
- 세부 종류
Cache-Control: max-age
Cache-Control: no-cache
- 데이터는 캐시해도 되지만, 항상 원(
origin
) 서버에 조건부 요청
으로 검증하고 사용
- 중간 캐시서버는 안되고 반드시 원 서버에서 검증해줘야 함
(if-modified-since
/ if-None-Match
)
Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안된다는 것을 알리는 것
(메모리에서 사용하고 최대한 빨리 삭제)
[ Pragma ]
[ Expires ]
Expires
- 캐시 만료일을 정확한 날짜로 지정
- 지금은 더 유연한
Cache-Control : max-age
권장
(둘 다 사용될 경우 Expires는 무시됨)
- HTTP 1.0 부터 사용하지만 하위 호환으로 사용
[ 검증 헤더 / 조건부 요청 헤더 개요 ]
[ 기본 개념 ]
- 조건부 요청 헤더 ?
- 설명
- 브라우저 로컬 캐시의 데이터와 서버 데이터가 동일한지 검증하기 위한 요청 헤더 필드
- 데이터가 갱신되지 않은 경우 304 상태코드와 갱신된 헤더 필드를 수신
(HTTP Response body가 비어있기 때문에 리소스를 아낄 수 있다)
- 종류
if-modified-since
/ if-Unmodified-since
: Last-Modified
와 함께 사용
if-None-Match
/ is-Match
: ETag
와 함께 사용
[ Last-Modified ]
Last-Modified
로직
- 최초 요청
- Server : 최초 클라이언트 요청에 대해
Last-Modified
/ max-age
를 포함한 응답
- Client : 서버가 보낸 정보를 브라우저 로컬 캐시에 저장
(데이터
/Last-Modified
/ max-age
)
- 캐시 만료 후 요청
- Client : 브라우저의 요청에 대한 로컬 캐시의
max-age
의 만료를 확인
- Client :
if-modified-since
검증 헤더를 추가해서 HTTP 요청
- Server : HTTP 요청에 있는 검증 헤더(
if-modified-since
)를 통해
기존 요청의 응답으로 받은 데이터가 변경되었는지 확인
- Server : 데이터가 미변경 되었음을 확인하고
갱신된 헤더 필드
와 함께 304 status code
로 HTTP 응답
(Last-Modified
/ cache-control
값 갱신)
- Client : HTTP Response에서
새로운 값
들을 통해 로컬 캐시 갱신
후 데이터 캐싱
- 단점
- 날짜 기반의 로직 사용
- 1초 미만(0.x초) 단위로 캐시 조정이 불가능
- 데이터를 수정해 날짜는 다르지만, 데이터 내용은 같은 경우 캐시가 일어나지 않음
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우에 부적합
[ ETag ]
- ETag(
Entity Tag
)
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아두는 원리
- 해시를 이용하면 파일이 동일한 경우 같은 해시값이 나오므로 해시를 이용하기도 함
- 임의로 작성할 수도 있다
- ex)
ETag: "v1.0"
, ETag: "a2jiodwjekil3"
ETag
로직
- 최초 요청
- Server : 최초 클라이언트 요청에 대해
ETag
/ max-age
를 포함한 응답
- Client : 서버가 보낸 정보를 브라우저 로컬 캐시에 저장
- 캐시 만료 후 요청
- Client : 브라우저의 요청에 대한 로컬 캐시의
max-age
의 만료를 확인
- Client : 검증 헤더 (
if-None-Match
)를 포함해서 HTTP 요청
- Server : HTTP 요청에 있는 검증 헤더(
if-None-Match
)를 통해
기존 요청의 응답으로 받은 데이터가 변경되었는지 확인
- Server : 데이터가 미변경 되었음을 확인하고
갱신된 헤더 필드
와 함께 304 status code
로 HTTP 응답
(ETag
/ cache-control
값 갱신)
- Client : HTTP Response에서
새로운 값
들을 통해 로컬 캐시 갱신
후 데이터 캐싱
- 특징
- 단순하게 ETag 값을 통해 서버에서 같으면 유지, 다르면 다시 받는 원리
- 핵심은
캐시 제어 로직
을 서버에서 완전히 관리
된다는 것이다
[ 프록시 캐시 ]
- 설명
- 실제 서버는 나라를 넘어 정말 먼 거리를 통해 구성되는 경우가 많다
- 그래서 나라별 / 지역별 서버를 프록시 서버를 두는 경우가 많다
(원 서버가 아닌, 프록시 서버를 두는 것)
- 이러한 프록시 서버를 통해 캐시를 하는 것을 프록시 캐시라고 한다
- 추가 Cache-Control 값
Cache-Control: public
- 응답이 public 캐시(
프록시 서버 캐시
)에 저장되어도 됨
Cache-Control: private
- 응답이 해당 사용자만을 위한 것이므로, private 캐시(
각 개인의 브라우저 캐시
)에 저장하도록 함 (기본 값)
- 사용자 정보 같은 값은 개인에게 있어야 하는 민감한 정보
Cache-Control: s-maxage
Age: 60
- 원 서버(
origin
)에서 응답 후 프록시 캐시 내에 머문 시간(초)
[ 캐시 무효화 ]
- 설명
- 웹 브라우저가 임의로 캐시를 해버리는 경우가 많음
- 정말 캐시가 되면 안되는 정보에 대한 처리
- 설정
Cache-Control: no-cache, no-store, must-revalidate
- no-cache
- 데이터 캐시가 가능하지만, 항상 원 서버에 검증을 하도록 하는 헤더
- no-store
- 데이터에 민감한 정보가 있으니 메모리에서 사용하고 최대한 빨리 삭제하도록 알려주는 헤더
- must-revalidate
- 캐시 만료후 최초 조회시 원 서버에 검증해야 함
- 원 서버 접근 실패시 반드시 오류가 발생해야 함 - 504(Gateway Timeout)
- 캐시 유효 시간이라면 캐시를 사용함
Pragma: no-cache
- 옛 HTTP 버전은
Cache-Control: no-cache
를 인지하기 때문
(하위 호환을 위함)
no-cache
/ must-revalidate
함께 써야 하는 이유
- 원 서버까지 검증을 위한 요청을 하던 도중 문제가 생겨서 전달되지 않으면,
폴백 데이터
등을 주도록 설정 되어있는 경우가 있다
must-revalidate
를 같이 해주면 원 서버에 접근할 수 없는 경우 항상 504 Gateway Timeout
을 발생시키기 때문에 폴백 데이터
를 줄 일이 없다