📌 김영한 님의 "모든 개발자를 위한 HTTP 웹 기본 지식" 강의 듣고 정리
📍캐시 기본 동작
- 캐시가 없을 때
ex) 이미지를 요청할 경우 서버는 이미지에 대한 헤더(0.1M)와 바디의 이미지(1.0M)를 합쳐 1.1M의 응답을 보낸다.
캐시가 없다면 요청할 때마다 1.1M의 응답을 보냄- 데이터가 변경이 없어도 계속 네트워크를 통해 데이터를 다운받아야 한다.
- 인터넷 네트워크는 매우 느리고 비싸다 + 브라우저 로딩 속도가 느리다 = 느린 사용자 경험
- 캐시를 적용하면
ex) 서버에서 캐시 적용을 하게 되면 요청시 서버가 응답할 때 캐시가 유효한 시간을 지정하여 해당 요청에 대한
데이터를 보낸다. 그리고 웹브라우저는 그 응답 결과를 다운받아 브라우저 캐시에 저장한다 (유효시간만큼)
두번째 요청시 웹 브라우저는 캐시부터 뒤져서 유효시간이 만료되지 않았다면 존재하고 있을 데이터를 가져온다.
다시 요청시 유효시간 만료되면 다시 다운받아 기존에 캐시에 저장된 데이터를 초기화하고 가져온 것으로 덮는다.
- 비싼 네트워크 사용량을 줄일 수 있다.
- 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다. + 브라우저 로딩 속도가 매우 빠르다 = 빠른 사용자 경험
- 만료되면 다시 조회하고 다시 다운로드하여 캐시를 갱신한다.
그런데 시간만 만료됬을 뿐 데이터가 변한건 아닌데 또 다운받아야 한다?!
이걸 해결할 수 있는 매커니즘이 바로 검증 헤더이다.
📍검증 헤더와 조건부 요청1
캐시 만료 후에도 서버에서 데이터를 변경하지 않았다면 만료됬더라도 그 캐시를 재사용 할 수 있다.
단, 웹브라우저 캐시의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법이 필요한데, 그게 검증 헤더.
- 클라이언트의 데이터 요청
- 검증 헤더를 통해 서버가 Last-Modified 값을 캐시 만료시간과 함께 전송
ex) Last-Modified: 2020년 11월 10일 10:00:00 (검증 헤더) - 응답 결과를 웹브라우저가 캐시에 저장. (만료시간과 최종 수정일 정보 또한 같이)
- 클라이언트의 데이터 요청시 먼저 캐시를 조회하고 만료시간 초과한 경우 캐시의 최종 수정일을 요청에 넣어 보낸다.
ex) if-modified-since: 2020년 11월 10일 10:00:00 (조건부 헤더, 만약 이후로 변경되었다면?) - 서버가 이를 서버내의 최종 수정일과 비교해 봤을 때 동일하면 바디 없이 헤더 정보만 있는 304 Not Modified 응답을 보낸다. (헤더 크기 만큼의 용량은 전달)
ex) cache-control: max-age=60
Last-Modified: 2020년 11월 10일 10:00:00 - 이 응답을 받으면 캐시 컨트롤 값을 갱신시켜 캐시를 다시 세팅. 그리고 이 캐시를 불러와 사용한다.
- 캐시 유효시간 초과 + 서버 데이터 갱신 없음 시
- 304 Moidified + 헤더 메타 정보만 응답(바디X)
- 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신
- 클라이언트는 캐시에 저장되어 있는 데이터 재활용
- 결과적으로 네트워크 다운로드는 발생하나 용량이 적은 헤더만 다운받으므로 매우 실용적인 해결책이다.
📍검증 헤더와 조건부 요청2
- 검증 헤더
- 캐시 데이터와 서버 데이터가 같은지 검증하는 데이터
- Last-Modified, ETag
- 조건부 요청 헤더
- 검증 헤더로 조건에 따른 분기
- If-Modified-Since: Last-Modified 사용
- If-None-Match: ETag 사용
- 조건이 만족하면 200 OK
- 조건이 만족하지 않으면 304 Not Modified
- If-Modified-Since: 이후에 데이터가 수정되었다면?
- 데이터 미변경시 (실패)
- 304 Not Modified, 헤더 데이터만 전송 (헤더 용량만큼 전송) - 데이터 변경시 (성공)
- 200 OK, 모든 데이터 전송 (헤더 + 바디 용량 전송)
- 데이터 미변경시 (실패)
- Last-Modified, If-Modified-Since 단점
- 1초 미만(0.x초) 단위로 캐시 조정이 불가능 (최소 단위가 초라서)
- 날짜 기반의 로직 사용
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우도 전체 다운로드
- 서버에서 최종 수정일이 아니라 별도의 캐시 로직을 관리하고 싶은 경우 사용 불가
(ex. 스페이스나 주석처럼 크게 영향이 없는 변경은 무시하고 캐시 유지 원하는 경우)
이런 경우 이걸 해결 할 수 있는 것이 ETag!
- ETag, If-None-Match
- ETag(Entity Tag)
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠 (ex. ETag: "v1.0" , ETag: "a2jiodwjekjl3")
- 데이터가 변경되면 이 이름을 바꾸어서 변경 (Hash를 다시 생성, 만약 컨텐츠가 동일하면 동일한 Hash값 나옴)
- 요청시 ETag를 보내어 같으면 유지, 다르면 다시 다운로드
- 사용 과정은 Last-Modified, If-Modified-Since과 동일하며 실패시(미변경) 304 Not Modified, 성공시(변경) 200 OK
- 캐시 제어 로직을 서버에서 완전히 관리 (클라이언트는 캐시 매커니즘을 모른다)
- 클라이언트는 단순히 이 값을 서버에 제공
📍캐시와 조건부 요청 헤더 정리
- 캐시 제어 헤더
- Cache-Control: 캐시 제어 (지금은 이걸로 모두 가능)
- 캐시 지시어(directives)
- Cache-Control: max-age
- 캐시 유효 시간, 초단위 - Cache-Control: no-cache
- 데이터는 캐시해도 되지만 캐시 사용하려고 할때 항상 Origin 서버에 검증하고 사용 - Cache-Control: no-store
- 데이터에 민감한 정보가 있으면 저장하면 안된다는 표시 (메모리에서 사용하고 최대한 빨리 삭제)
- Pragma: 캐시 제어(하위 호환) : HTTP 1.0
- Expires: 캐시 유효 기간(하위 호환)
- 캐시 만료일 지정
- 더 유연한 Cache-Control: max-age 권장
- Cache-Control: max-age 랑 같이 사용시 Expires는 무시된다.
- Cache-Control: 캐시 제어 (지금은 이걸로 모두 가능)
- 검증 헤더 (Validator)
- ETag: "v1.0" , ETag: "a2jiodwjekjl3"
- Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT
- 조건부 요청 헤더
- If-Match, If-None-Match: ETag 값 사용
- If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용
📍프록시 캐시
- 원(Origin) 서버
원 서버에 직접 접근하게 되면 거리가 멀수록 속도가 느리다
이를 해결하기 위해 프록시 캐시 서버를 도입 - 프록시(Proxy) 캐시 서버
보통 CDN(Content Delivery Network)이름으로 서비스로 제공
원서버가 아닌 프록시 서버(클라이언트와 가까운 프록시 캐시 서버)에 거쳐 가게 하여, 프록시 서버에 캐시가 있으면 거기서 캐시를 조회해 빠른 응답을 받게 한다. (없으면 원서버 다녀와야함)
- 프록시 서버의 캐시를 Public 캐시라 하고 클라이언트의 캐시는 Private 캐시라고 한다. - Cache-Control: 기타
- Cache-Control: public
- 응답이 public 캐시에 저장되어도 됨 - Catche-Control: private
- 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값) - Cache-Control: s-maxage
- 프록시 캐시에만 적용되는 max-age - Age: 60 (HTTP 헤더)
- 오리진 서버에 응답 후 프록시 캐시 내에 머문 시간(초)
- Cache-Control: public
📍캐시 무효화
- 확실한 캐시 무효화 응답이 존재 (캐시를 적용안해도 웹 브라우저가 임의로 캐시해버리고 하기 때문)
- Cache-Control:
- Cache-Control: no-cache, no-store, must-revalidate (이걸 모두 넣어주어야 무효화)
- Cache-Control: no-cache
- 데이터는 캐시해도 되지만 캐시 사용하려고 할때 항상 Origin 서버에 검증하고 사용 - Cache-Control: no-store
- 데이터에 민감한 정보가 있으면 저장하면 안된다는 표시 (메모리에서 사용하고 최대한 빨리 삭제) - Cahce-Control: must-revalidate
- 캐시 만료후 최초 조회시 원 서버에 검증해야함
- 원 서버 접근 실패시 반드시 오류가 발생해야함 (504 Gateway Timeout)
- must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
- ❓no-cache가 있는데 이거 왜 사용
no-cache의 경우 프록시 서버와 원 서버 사이의 일시적 장애가 생긴 경우 프록시 서버의 오래된 데이터라도 보여주는 설정도 할 수 있다. must-revalidate는 서버 사이 장애시 무조건 504 오류 응답
- Cache-Control: no-cache
- Pragma: no-cache (HTTP 1.0 하위 호환, HTTP 1.0 요청 경우를 무효화 위해)
- Cache-Control: no-cache, no-store, must-revalidate (이걸 모두 넣어주어야 무효화)
'Computer Science > Web' 카테고리의 다른 글
HTTP 웹 지식 - HTTP 헤더1 (일반 헤더) (0) | 2023.03.12 |
---|---|
HTTP 웹 지식 - HTTP 상태코드 소개 (0) | 2023.03.08 |
HTTP 웹 지식 - HTTP 메서드 활용 (0) | 2023.03.08 |
HTTP 웹 지식 - HTTP API를 만들어보자 (0) | 2023.03.07 |
HTTP 웹 지식 - 모든 것이 HTTP (0) | 2023.03.06 |