우리가 서버에서 웹 페이지를 랜더링 받는다고 생각을 해보자
naver 웹 이라고 생각을 하면, 여러 그림들도 많고 정말 많은 데이터들이 서버에서부터 받아질 것이다. 그런데 내가 똑같은 페이지를 여러번 들어간다면 여러번 모두 같은 데이터(그림,오디오)등등을 계속 받아야 될까? 음 한번만 받고 저장해 놓는다면, 정말 필요한 정보만 다시 받고 랜더링을 더 빠르게 할 수 있지 않을까?
이런 고민 즉 웹 페이지를 빠르게 랜더링 하기 위해서, 캐시라는 개념이 나온다.
- 그런데 이렇게 http에 대해서 공부하다 보니 캐시와, 쿠키가 비슷하다고 느껴졌다.
- 그래서 캐시를 정리하기 전에, 캐시와 쿠키의 차이점에 대해서 먼저 정리를 해보겠다.
음, 쿠키/세션
은 사용자의 로그인 같은 인증을 하기 위한 부분의 정보를 저장하는 것이고, 캐시
는 웹 페이지를 빠르게 랜더링 하기 위해서 웹 페이지의 요소를 저장하기 위한 임시 저장소구나! 라고 이해를 했다
만약 캐시가 없다면...
- 데이터가 변경되지 않아도 계속 네트워크를 통해 데이터를 다운 받아야 한다
- 근데 이 인터넷 네트워크가 느리고 비싸다...-> 캐시의 필요성!
그래서! 서버에서 캐시를 생성하면서 데이터를 웹 브라우저에 주면
- 웹 브라우저에서 캐시 유효 시간을 검증하고
- 브라우저 캐시에서 조회된 데이터를 웹 페이지에 랜더링을 한다
- 캐시가 적용이 되면
- 비싼 네트워크의 사용량을 크게 줄일 수 있고
- 브라우저 로딩 속도가 빨라서 사용자가 좋아한다
- 유효 시간을 정하는데..
- 만약 유효시간이 지나면..?
- 웹 브라우저는 다시 서버에 요청해서 데이터를 다시 받아야 된다
- 다시 네트워크 다운로드가 발생한다
검증 헤더와 조건부 요청1
- 방금 말했듯이 캐시 시간이 초과될 때를 생각해보자
- 서버에서 기존 데이터를 변경함
- 서버에서 기존 데이터를 변경하지 않음
-> 1번이면 다시 데이터를 다운받아야한다
-> 하지만 2번이라면? 캐시가 만료되었지만, 저장해 두었던 캐시를 재사용할 수 있지 않을까?
-> 그럼 여기서 중요한 것 : "클라이언트의 데이터와" "서버의 데이터"가 같다는 거 어떻게 확인할건데??? : 검증헤더
를 이용한다
아 그러니까! 캐시가 유효시간이 남았을 때
는, 그냥 캐시를 이용해 화면 랜더링을 빠르게 하고
캐시의 유효시간이 만료되었을 때
는 검증헤더를 사용해서, 저장된 캐시를 사용할지 아니면 다시 데이터를 받을지 정하는 거구나!
검증 헤더와 조건부 요청(Last-Modified, If-modified-since)
- 서버에서 클라이언트로 데이터를 전송할 때
Last-Modified
라고 최종 데이터의 수정일을 응답 헤더
로 보내준다
- 이제
cache-control
:max-age=60의 60초가 지나서, 캐시가 만료되었다고 생각해보자. 그러면 우리는 이제 데이터가 바뀌었는지 아니면 유지되었는지 확인을 해야한다.
- 다시 똑같은 url로 웹 브라우저가 서버에 요청을 한다. 이때 브라우저 캐시에 저장된
Last-Modified
의 정보를 If-modified-since
요청 HTTP 헤더에 넣어서 서버에 보내준다
4-1. 만약 수정일이 다르다면 다시 데이터를 다운 받는다
4-2. 수정일이 같다면???-> 데이터를 다시 다운 받을 필요가 없다!
- http 응답 메시지에 body없이 status-line, header부분만 데이터를 보내준다
- 그리고
304 Not Modified
오류를 내준다(안 바꼈어라고 알려주는 것)
- 그러면 다시
cache-control
에 인해 캐시의 유효 시간을 갱신
한다
- 웹 브라우저에서 유효시간이 갱신되었으므로 캐시를 이옹해 화면을 랜더링해준다
<정리>
- 캐시 유효시간이 초과해도, 서버의 데이터가 갱신되지 않으면 저장된 캐시를 이용할 수 있다
- 그럴려면, 서버의 데이터가 갱신되었는지를 확인해야한다 -> 검증헤더를 이용한다
- 응답 header인
Last-Modified
와 요청 header인 If-mdified-since
를 통해 확인을 한다
- 요청 header가 만약 바꼈어? 라고 물어봤기 때문에, 안 바뀌었으니까
304 Not Modified
와 헤더 메타 데이터
로 응답을 한다(바디 X)
- 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신한다
- 클라이언트는 캐시에 저장되어 있는 데이터를 재활용한다
- 네트워크 다운로드는 발생, but 용량이 적은 header정보만 다운 받는다
- 만약 데이터가 변경되었다면 ->
200 OK
- 데이터가 변경되지 않았다면 ->
304 Not Modified
검증 헤더와 조건부 요청2
- 그런데
Last-Modified
, If-Modified-Since
에는 몇가지 단점이 있다.
- 1초미만 단위로 캐시 조정이 불가능하다
- 잘짜 기반의 로직을 사용한다
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 같은 경우 -> 이런 경우는 다시 데이터를 다운 받을 필요가 없다!
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
- 스페이스, 주석처럼 크게 영향 없는 변경 -> 캐시를 유지하는게 좋다
검증 헤더와 조건부 요청(Etag, If-None-Match)
ETag
(Entity Tag)
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아둔다
- 데이터가 변경 -> 이 이름을 바꾸어서 변경(Hash를 다시 생성)
- 이러면 크게 영향 없는 변경을 하고 ETag의 이름을 유지하면 된다
- 정말 단순하게 ETag만 보내서 같으면 유지, 다르면 다시 데이터 받기
- 내가 설정한
ETag이름
을 응답 header에 넣어준다
- 응답 결과를 브라우저 캐시에 저장한다
- 캐시의 저장 유효 시간이 만료 되고 다시 요청이 들어오면??
If-None-Match
header을 통해 같은지 확인!
- 수정되지 않았으면(=Etag가 같다면) ->
304 Not Modified
와 함께 응답 Http header만 반환된다
- 다시 캐시의 유효시간이 갱신되고, 웹 브라우저에서 캐시를 조회해 화면을 랜더링 한다
<정리>
- 정말 단순하게 ETag만 서버에 모내서 같은지 다른지 확인
- 케시 제어 로직을 서버에서 완전히 관리
- 클라이언트는 단순히 이 값을 서버에 제공함, 블랙박스야
캐시 제어 헤더
Cache-Control
: 캐시 제어
• Cache-Control: max-age
= 초 단위
• Cache-Control: no-cache : 데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증및 사용
• Cache-Control: no-store :데이터에 민감한 정보가 있으므로 저장하면 안됨
(메모리에서 사용하고 최대한 빨리 삭제)
Pragma
: 캐시 제어(하위 호환)
• Pragma: no-cache
• HTTP 1.0 하위 호환
Expires
: 캐시 유효 시간(하위 호환)
• expires: Mon, 01 Jan 1990 00:00:00 GMT
• 캐시 만료일을 정확한 날짜로 지정
• HTTP 1.0 부터 사용
• 지금은 더 유연한 Cache-Control: max-age 권장
• Cache-Control: max-age와 함께 사용하면 Expires는 무시
웹 브라우저(naver)라고 가정을 해보면 우리는 누군가가 처음에 많은 데이터들을 다운 받고 캐시로 저장을 해놨고, 캐시의 유효시간이 지났음에도 데이터가 변하지 않았기 때문에 빠르게 웹 브라우저를 이용할 수 있는 것이다!
프록시 캐시
만약에 우리가 미국에 있는 사이트를 사용한다면? 데이터 가져오는데 시간이 좀 걸린다,,,
미리 미국 서버에서 데이터를 가져와 캐시로 가지고 있는 프록시 캐시 서버
를 한국에 둔다
Cache-Control (캐시 지시어)
- Cache-Control :
public
응답이 public 캐시에 저장되어도 됨
- Cache-Control :
private
응답이 해상 사용자만을 위한 것 private 캐시에 저장되어야 됨(개인정보)
- Cache-Control :
s-maxage
프록시 캐시에만 적용되는 max-age
Age
:60(Http 헤더)
오리진 서버에서 응답 후, 프록시 캐시 내에 머문 시간(초)
Cache-control (캐시 무효화 응답)
- Cache-Control:
no-cache
• 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용(이름에 주의!)
- Cache-Control:
no-store
• 데이터에 민감한 정보가 있으므로 저장하면 안됨
(메모리에서 사용하고 최대한 빨리 삭제)
- Cache-Control:
must-revalidate
• 캐시 만료후 최초 조회시 원 서버에 검증해야함
• 원 서버 접근 실패시 반드시 오류가 발생해야함 - 504(Gateway Timeout)
• must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
Pragma: no-cache
• HTTP 1.0 하위 호환
no-cache기본 동작-> 원서버 검증!!!
-> 원서버의 접근이 안될 때, 그 전에 있던 캐시를 이용해 응답해버림
-> 만약 돈과 관련된 매우 중요한 문제라면...? 문제 발생 ㅜ
-> must-revalidate
로 해결해보자