캐시와 조건부 요청
캐시 기본 동작
- 캐시가 없을때
- 용량이 어느정도 큰 파일을 서버로 요청을 할때마다 데이터를 다운로드 받아야하고, 비용이 발생한다. 또한 다운로드를 하는 시간이 발생해 사용자 경험이 저하된다.
- 캐시가 있다면 cache-control 로 지정된 시간만큼 캐시에서 다운받은 데이터가 저장되어 있다가 다시 요청을 할때 바로 재사용할 수 있다.
- 다운로드 시간 및 비용이 발생하지 않고 사용자 경험이 향상된다.
검증 헤더와 조건부 요청
캐시 시간 초과 시 발생하는 상황
- 서버에서 기존 데이터를 변경함
- 서버에서 기존 데이터를 변경하지 않음
- 기존 데이터가 변경되지 않았기 때문에 굳이 다시 다운로드할 필요가 없음. 이를 확인하기 위해 검증헤더가 필요함.
검증 헤더
if-modified-since 요청 헤더를 붙여서 캐시에 저장되어있는 데이터의 최종 수정 시간을 포함함.
서버에서 요청 받은 데이터의 최종 수정일을 확인하고 판단해서 캐시 저장소의 데이터를 사용할 수 있는지 알려준다.
(304 Not Modified를 보내고 이때 HTTP body가 없음.)
이때, 서버로 부터 전송된 HTTP 응답을 통해 다시 캐시를 세팅함.서버로 부터 다운로드가 발생하긴함. 하지만 다운받으려는 데이터를 제외한 헤더값만 받으면 됨.
ex) 다운 받으려는 이미지 크기 2MB, HTTP 헤더 크기 0.1MB -> 0.1MB 만큼만 다운로드 받게됨.캐시 데이터와 서버 데이터가 같은지 검증하는 데이터 ex) Last-Modified, ETag
조건부 요청 헤더
- 검증 헤더로 조건에 따른 분기
- if-Modified-Since: Last-Modified 사용
- if-None-Match: ETag 사용
- 조건이 만족하면 200 OK
- 조건이 만족하지 않으면 304 Not Modified (이때, 기존에 저장된 캐시 데이터를 사용함)
검증 헤더와 조건부 요청 예시
- if-Modified-Since: 이후에 데이터가 수정되었으면?
- 200 OK 와 함께 Body를 포함한 모든 데이터 전송
- 데이터가 수정되지 않았다면?
- 304 Not Modified와 함께 헤더 데이터만 전송됨(Body 미포함)
- if-Modified-Since: 이후에 데이터가 수정되었으면?
단점
- 1초 미만 단위로 캐시 조정 불가능
- 날짜 기반의 로직 사용
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우에 다시 다운로드 받아야함.
- 이때, ETag를 통해서 데이터에 임의의 고유한 버전 이름을 달아둠으로써 해결할 수 있음. (Hash를 이용하기도 함)
ETag
- if-None-Match: 를 통해서 ETag를 전송함.
- 서버의 응답은 헤더에 ETag를 포함시키고 나머지 로직은 <검증 헤더와 조건부 요청> 와 같음.
캐시 제어 헤더
- Cache-Control: 캐시 제어
- Cache-Control: max-age (캐시 유효 시간, 초 단위)
- Cache-Control: no-cache (데이터는 캐시해도 되지만, _항상 Origin 서버에 검증_하고 사용)
- Cache-Control: no-store (데이터에 민감한 정보가 있으므로 저장하면 안됨. _메모리에서 사용하고 최대한 빨리 삭제_해야함.)
- Pragma: 캐시 제어(하위 호환)
- Expires: 캐시 유효 기간(하위 호환)
- Cache-Control: 캐시 제어
프록시 캐시
- 원(Origin) 서버 직접 접근에 직접 접근을 하려면 오래걸림. 따라서, 프록시 캐시 서버(CDN) 도입
- 웹 브라우저에서는 원 서버에 직접 요청하는 것이 아니고, 가까운 프록시 캐시 서버에 요청을 하게 됨.
- 프록시 서버에 캐시되어 있는 데이터를 사용하거나, 없다면 프록시 서버에서 Origin 서버에 요청을 하고 그것을 캐시함.
- 웹 브라우저의 캐시: private cache
- 프록시 서버의 캐시: public cache
Cache-Control: 캐시 지시어
Cache-Control: public
- 응답이 public 캐시에 저장되어도 됨
Cache-Control: private
- 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
캐시 무효화
Cache-Control: (확실한 캐시 무효화 응답)
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
- HTTP 1.0 하위 호환
위 헤더들을 다 넣어야 캐시를 무효화시킬 수 있음
no-cache: 데이터는 캐시해도 되지만, 항상 Origin 서버에 검증하고 사용
no-store: 데이터에 민감한 정보가 있으므로 저장하면 안됨
must-revalidate:
- 캐시 만료후 최초 조회시 Origin 서버에 검증해야함
- Origin 서버에 접근 실패시 반드시 오류가 발생해야함 (504)
- must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
Pragma: no-cache
- HTTP 1.0 하위 호환(간혹 낮은 버전의 브라우저에서 요청이 들어올 수 있음)
위 4가지를 반드시 조합해야 캐시 무효화에 확실함.
no-cache vs must-revalidate
no-cache: 해당 헤더가 붙어 있는 요청을 프록시 캐시 서버에서는 검증하면 안되기 때문에 Origin 서버로 보내게 됨.
(만약 원서버와 네트워크가 단절된 상황이라면 오래된 데이터라도 웹 브라우저로 전송하도록 설정할 수 있음 Error or 200 OK)
must-revalidate: no-cache와 마찬가지로 Origin 서버로 전송하게 되지만, 원 서버와의 네트워크가 단절된 상황에는 504를 반환함.
출처-인프런 김영한님의 강의 (모든 개발자를 위한 HTTP 웹 기본 지식)
'BackEnd' 카테고리의 다른 글
API의 구현과 API 명세서-1 (2) | 2025.03.21 |
---|---|
HTTP 요청의 구조와 통신 과정 / HTTP 메서드 (0) | 2025.03.21 |
클라이언트-서버 구조와 HTTP란? (0) | 2025.03.21 |
HTTP 헤더1 - 일반 헤더 (2) | 2025.03.18 |
HTTP 상태코드 (0) | 2025.03.06 |