티스토리 뷰
이번 포스팅에서는 HTTP 완벽가이드 책을 활용하였습니다.
7장 Cache
이 포스팅에서는 웹 캐시를 집중적으로 다룬다. 캐싱의 숨겨진 요소들에 대해서는 이 링크를 참조하는 것이 좋겠다.
네트워크를 통해 데이터를 가져오는 것은 하드디스크나 메모리에 비해서 상당히 느리다.
그래서 웹 브라우저는 웹 페이지에 접속할 때 HTML, CSS, JS, Image 등 정적 파일을 캐싱해뒀다가 재사용한다. - 브라우저 캐시 활용
웹 캐시는 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치이다. 웹 요청이 캐시에 도착했을 때, 캐시된 로컬 사본이 존재한다면(cache hit) Origin Server가 아니라 그 캐시로부터 제공된다. - HTTP 캐싱
* 웹 캐시 이점
- 캐시는 불필요한 데이터 전송을 줄여서, 네트워크 요금으로 인한 비용을 줄여준다.
- 캐시는 네트워크 병목을 줄여준다. 대역폭을 늘리지 않고도 페이지를 빨리 불러올 수 있게 된다.
- 캐시는 Origin Server에 대한 요청을 줄여준다. 서버는 부하를 줄일 수 있으며 더 빨리 응답할 수 있게 된다.
- 페이지를 먼 곳에서 불러올수록 시간이 많이 걸리는데, 캐시는 거리로 인한 지연을 줄여준다.
* Cache 처리 단계
단계 1: 요청 받기 - 캐시는 네트워크로부터 도착한 요청 메시지를 읽는다.
단계 2: 파싱 - 캐시는 메시지를 파싱하여 URL과 헤더들을 추출한다.
단계 3: 검색 - 캐시는 로컬 복사본이 있는지 검사하고, 사본이 없다면 사본을 받아온다 그리고 로컬에 저장한다.
단계 4: 신선도 검사 - 캐시는 캐시된 사본이 충분히 신선한지 검사하고, 신선하지 않다면 변경사항이 있는지 서버에 물어본다.
단계 5: 응답 생성 - 캐시는 캐시된 응답을 Origin Server에서 온 것처럼 보이게 하고 싶기 때문에, 새로운 헤더와 캐시된 본문으로 응답 메시지를 만든다. 이 때 헤더의 응답 버전을 클라이언트에 맞게 조정해야 하며, Cache-Control/Age/Expires 등 캐시 신선도 정보를 삽입하여야 한다. 또한 요청이 프락시 캐시를 거쳐갔음을 알려주기 위해 종종 Via 헤더를 포함시킨다.
단계 6: 발송 - 캐시는 네트워크를 통해 응답을 클라이언트에게 돌려준다.
* 캐시 제어
- no-cache와 no-store 응답 헤더
1
|
Cache-Control: no-cache, no-store
|
'no-cache'는 매 요청마다 ETag를 통해 자원의 유효성 확인. Cache-Control의 max-age가 0과 같음.
'no-store'는 자원을 캐시하지 않음.
- 'public' vs 'private'
1
|
Cache-Control: private, max-age=600
|
'public'은 중간 단계를 포함해 캐시 가능하다. 대부분의 경우, 명시적 캐싱 정보(예: 'max-age')가 응답이 어떠한 경우든지 캐시가 가능하다고 나타내므로 'public'이 필요하지 않다.
'private'은 중간 단계에 캐시를 하지 않는다. 즉, 사용자 브라우저는 캐시할 수 있지만 CDN은 캐시할 수 없다.
- 유효기간을 까마득한 미래로 설정한다면 그 문서에 대한 어떤 변경도 캐시에 반영되지 않을 것이다.
* 사본을 신선하게 유지하기
Expires : 절대 유효기간을 명시한다.
Cache-Control: max-age : max-age값은 문서의 최대 나이를 정의한다. 최대 나이는 문서가 처음 생성된 이후부터 제공하기엔 더 이상 신선하지 않다고 간주될 때까지 경과한 시간의 합법적인 최댓값이다.
* 재검사(Revalidation)
Origin Server의 컨텐츠는 변경될 수 있기 때문에 캐시는 반드시 그들이 갖고 있는 사본이 여전히 최신인지 서버를 통해 때때로 점검해야 한다. 이러한 신선도 검사를 HTTP 재검사라 부른다. 캐시된 문서가 만료되었다는 것은, 그 문서가 Origin Server에 현재 존재하는 것과 실제로 다르다는 것을 의미하지는 않으며, 다만 이제 검사할 시간이 되었음을 뜻한다. 재검사 결과 컨텐츠가 변경되었다면 새로운 사본을 가져와 데이터 갱신을, 변경되지 않았다면 캐시 안의 헤더들을 갱신한다.
효과적인 재검사를 위해 HTTP는 서버로부터 전체 객체를 가져오지 않고도 컨텐츠가 여전히 신선한지 빠르게 검사할 수 있는 특별한 요청을 정의했다. 캐시는 캐시된 사본의 재검사가 필요할 때 Origin Server에 작은 재검사 요청(GET If-Modified-Since)을 보낸다. 컨텐츠가 변경되지 않았다면, 서버는 아주 작은 304 Not Modified 응답을 보낸다.
If-Modified-Since:
만약 문서가 주어진 날짜 이후로 수정되었다면 요청 메서드를 처리하고, 수정되지 않았다면 304를 반환한다.
If-None-Match:
최근 변경일시 재검사가 적절치 않은 경우가 있다.
- 어떤 문서는 일정 시간 간격으로 다시 쓰여지지만 내용에 변화가 없는 경우가 있다.
- 어떤 문서는 철자나 주석 변경 등 전 세계의 캐시를 다시 읽어들이기엔 사소한 것일 수도 있다.
- 어떤 서버는 그들이 갖고 있는 페이지에 대한 최근 변경일시를 정확하게 판별할 수 없다.
- 1초보다 작은 간격으로 갱신되는 문서를 제공하는 서버들에게는 변경일에 대한 1초의 정밀도는 충분하지 않을 수 있다.
이 경우 ETag가 같지 않을 경우에만 새 객체를 달라고 요청한다
클라이언트는 서버가 ETag를 반환했다면 반드시 ETag 검사기를 사용하여야 하며, Last-Modified값만 반환했다면 If-Modified-Since 검사를 사용할 수 있다.
반면, 캐시나 서버는 ETag 조건부 헤더와 If-Modified-Since를 모두 받았다면 요청의 모든조건부 헤더 필드의 조건에 부합되지 않는한 304 응답을 반환해서는 안된다.
그렇다면 만약, 캐시를 설정해둔 가운데 즉각적으로 수정사항을 반영해야 할 경우에는 어떻게 해야할까?
HTTP 캐싱에도 나와있듯 '리소스의 URL을 변경하고 콘텐츠가 변경될 때마다 사용자가 새 응답을 다운로드하도록 하면 된다.' CDN을 사용한다면, AWS 에서는 객체무효화(Invalidation)를, Cloudflare 에서는 퍼징(purge cache)을 활용하여 리소스의 URL 변경없이 해당 파일/디렉토리에 설정해놓은 캐시를 삭제하고 다시 Origin Server로부터 파일/디렉토리 정보를 가져와서 캐싱할 수 있다.
'Infra Structure > .system' 카테고리의 다른 글
MySQL 다시 공부하기 (1) (0) | 2019.11.10 |
---|---|
HTTP 완벽가이드 스터디 #8 Gateway, Tunnel (0) | 2019.10.12 |
HTTP 완벽가이드 스터디 #6 Proxy Server (0) | 2019.09.23 |
HTTP 완벽가이드 스터디 #4 -d Keep-Alive (1) | 2019.09.16 |
HTTP 완벽가이드 스터디 #4 -c TCP 성능 (0) | 2019.08.25 |