HTTP 헤더 - 캐시와 조건부 요청
캐시 기본 동작
클라이언트가 서버에 정보를 요청할 때마다 같은 정보라도 같은 요청과 응답을 받아야한다. ( 비효율적, 자원낭비 )
=> 브라우저 로딩 속도가 느려지고 그에 따라 느린 사용자 경험
캐시 적용
클라이언트가 데이터를 요청하고 서버가 응답을 보낼 때 cache-control : max-age=60 를 설정 ( 60초동안 캐시 유효 )
그 후 웹 브라우저의 캐시저장소에 응답결과의 데이터를 저장한다.
두번째 요청 시 캐시저장소에서 데이터를 먼저 찾고 있으면 바로 가져오고 없으면 서버에 요청하게 된다.
캐시 유효시간이 지난 세번째 요청 시 캐시저장소의 데이터가 없어졌기 때문에 다시 서버에 요청하여 응답받고 캐시저장소에 저장하게된다.
=> 기존 캐시 데이터와 서버의 데이터가 달라질 수도 있기 때문에 캐시 유효시간이 지나면 새로 요청한다.
그런데 캐시 데이터와 서버의 데이터가 같다면 굳이 다시 요청할 필요가 있을까?
↓
검증 헤더 : 캐시 데이터와 서버 데이터가 같으지 검증하는 데이터 ( Last-Modified, ETag )
조건부 요청 헤더 : 검증 헤더로 조건에 따른 분기 ( if-modified-since : Last-Modified, if-none-match : ETag )
조건이 만족하면 200 OK, 만족하지 않으면 304 Not Modified
검증 헤더와 조건부 요청1
클라이언트가 데이터를 요청하고 서버가 응답을 보낼 때 Last-Modified:날짜... 를 설정 ( 마지막 수정일자 )
그 후 웹 브라우저의 캐시저장소에 응답결과의 데이터를 저장
캐시 유효시간이 지난 두번째 요청 시 캐시저장소의 데이터의 유효시간이 만료되어 if-modified-since: 날짜... 를 보내 서버 데이터의 최종 수정일자와 캐시저장소의 최종 수정일자의 일치 여부를 확인한다.
서버의 최종 수정일자와 캐시저장소의 최종 수정일자가 같다면 304 Not Modified 응답으로 HTTP 헤더만 보낸다. ( 바디는 필요없다. )
304 응답을 받으면 캐시 저장소의 유효시간이 만료된 데이터의 유효시간을 초기화하고 재사용한다.
=> HTTP 바디를 다시 보내지 않아도 되기 때문에 자원을 아낄 수 있다. ( 빠른 사용자 경험, 매우 실용적 )
* Last-Modified, if-modified-since 단점
=> 0.x 초 단위로 캐시 조정 불가, 날짜 기반 로직 사용, 데이터는 그대로인데 날짜만 변경된 경우, 서버에서 별도의 캐시 로직을 관리하고 싶은 경우 한계가 있다.
↓
검증 헤더와 조건부 요청2
ETag ( Entity Tag ) : 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠
클라이언트가 데이터를 요청하고 서버가 응답을 보낼 때 ETag:"Hash" 값을 설정
그 후 웹 브라우저의 캐시저장소에 응답결과의 데이터를 저장
캐시 유효시간이 지난 두번째 요청 시 캐시저장소의 데이터의 유효시간이 만료되어 if-none-match: "Hash" 를 보내 서버 데이터 hash값과 캐시저장소의 hash 값의 일치 여부를 확인한다.
서버의 hash 값과 캐시저장소의 hash 값이 같다면 304 Not Modified 응답으로 HTTP 헤더만 보낸다. ( 바디는 필요없다. )
304 응답을 받으면 캐시 저장소의 유효시간이 만료된 데이터의 유효시간을 초기화하고 재사용한다.
* 단순하게 ETag만 서버에 보내서 비교 가능, 캐시 제어 로직을 서버에서 완전 분리 가능
캐시 제어 헤더
Cashe-Control : 캐시 제어
: max-age
=> 캐시 유효 시간, 초단위
: no-cache
=> 데이터는 캐시해도 되지만, 무조건 origin 서버에 검증하고 사용
: no-store
=> 데이터에 민감한 정보가 있으므로 저장하면 안됨
: must-revalidate
=> 캐시 만료 후 최초 조회 시 origin 서버에 검증해야함, origin 서버 접근 실패 시 504 오류 발생해야함
( no-cache 와 같이 프록시 캐시에서 검증하지 않고 origin 서버에서 검증해야할 때, 순간적으로 프록시 캐시와 origin 서버 간의 네트워크에 장애가 발생 할 수 있다.
이 때 no-cashe의 경우 오류를 반환하는 대신 오래된 데이터라도 200 OK 응답으로 보여준다. 반면 must-revalidate의 경우 504 에러를 반환한다. )
Pragma : 캐시 제어 ( 하위 호환 )
Expires : 캐시 유효 기간 ( 하위 호환 )
프록시 캐시
웹 브라우저에서 미국의 origin 서버의 데이터를 요청하면 요청 시간이 오래 걸린다.
그 사이에 프록시 서버를 구축해 놓고 웹 브라우저는 프록시 서버에 데이터를 요청하게 되고 빠른 응답결과를 받게 된다.
=> 웹 브라우저 캐시 ( private 캐시 ), 프록시 서버 캐시 ( public 캐시 )
Cashe-Control
: public
=> 응답이 public 캐시에 저장되어도 됨
: private
=> 응답이 private 캐시에만 저장되어야 함 ( default 값 )
: s-maxage
=> 프록시 캐시에만 적용되는 max-age
Age : 60 ( HTTP 헤더 )
캐시 무효화 처리
Cashe-Control: no-cache, no-store, must-revalidate
Pragma: no-cashe ( 과거 브라우저 대응용 )