7. 캐시
- 불필요한 데이터 전송을 줄여, 네트워크 요금으로 인한 비용을 줄여준다.
- 캐시는 네트워크 병목을 줄여준다. 대역폭을 늘리지 않고 페이지를 빨리 불러온다.
- 원 서버에 대한 요청을 줄여준다. 서버 부하를 줄일 수 있으며 더 빨리 응답할 수 있게 한다.
- 페이지를 먼 곳에서 불러올수록 시간이 많이 걸리는데 캐시는 거리로 인한 지연을 줄여준다.
7.1 불필요한 데이터 전송
서버 응답은 캐시에 보관된다. 캐시된 사본이 뒤이은 요청들에 대한 응답으로 사용될 수 있기 때문에, 원 서버가 중복해서 트래픽을 주고 받는 낭비를 줄이게 된다.
7.2 대역폭 병목
캐시 또한 네트워크 병목을 줄여준다. 많은 네트워크가 원격 서버보다 로컬 네트워크 클라이언트에 더 넓은 대역폭을 제공한다. 대역폭은 네트워크 속도와 문서 크기에 따라 전송 시간에 얼마나 영향을 주는지 볼 수 있다. 대역폭은 큰 문서에 대해 현저한 지연을 일으키며 속도는 네트워크 종류의 차이에 따라 극적으로 달라진다. ex) 이더넷 LAN > DS3 > 느린 이더넷 > TI > DSL > 전화식 모뎀
7.3 갑작스런 요청 쇄도(Flash Crowds)
갑작스런 요청 쇄도에 대처하기 위해 캐싱은 중요하다. 많은 사람이 겅의 동시에 웹 문서에 접근 할때 이런 일이 발생된다. 그 결과 불필요한 트래픽 급증은 네트워크와 웹 서버의 심각한 장애를 야기시킨다.
7.4 거리로 인한 지연
대역폭이 문제가 되지 않더라도, 거리가 문제가 될 수 있다. 모든 네트워크 라우터는 제각각 인터넷 트래픽을 지연시킨다. 그리고 클라이언트와 서버 사이에 라우터가 그다지 많지 않아도 빛의 속도 그 자체가 유의미한 지연을 유발한다. 기계실 근처에 캐시를 설치해서 문서가 전송되는 거리를 수천 킬로미터에서 수십미터로 줄일 수 있다.
7.5 적중과 부적중
캐시는 모듬 문서의 사본을 저장하지 않는다. 캐시에 요청이 도착했을 때, 사본이 있다면 그를 이용해 요청을 처리 할 수 있다. 이것을 캐시 적중(cache hit) 이라고 한다. 만약 사본이 없이 원 서버로 전달되면 캐시 부적중(cache miss) 라고 한다.
7.5.1 재검사(Revalidaton)
- 원 서버 콘텐츠는 변경 될 수 있기 때문에, 캐시는 반드시 그들이 갖고 있는 사본이 여전히 최신인지 서버를 통해 때대로 점검해야 한다. 이를 신선도 검사 혹은 재검사라 한다. HTTP는 서버로부터 전체 객체를 가져오지 않고도 콘텐츠가 여전히 신선한지 빠르게 검사할 수 있는 특별한 요청을 정의했다. 캐시는 스스로 원한다면 언제든지 사본을 재검사 할 수 있다. 그러나 많은 양의 경우 네트워크 대역폭은 부족하기 때문에, 사본이 검사를 할 필요가 있을 정도로 충분히 오래된 경우에만 재검사를 한다.
- 콘텐츠가 변경되지 않았다면, 서버는 아주 작은 304 Not Modified 응답을 보낸다.
- 재검사 적중/느린 적중 : 그 사본이 여전히 유효함을 알게된 캐시는 즉각 사본이 신선하다고 임시로 다시 표시한 뒤 그 사본을 클라이언트에 제공한다. 이는 순수 캐시 적중보다 느린데, 원 서버와 검사를 필요가 있기 때문이다. 그러나 캐시 부적중 보다는 빠른데, 서버로부터 객체 데이터를 받아올 필요가 없기 때문이다.
- 정리, 순수 캐시 적중 > 재검사 적중 > 캐시 부적중
- If-Modified-Since : 서버에게 보내는 GET 요청에 이 헤더를 추가하면, 캐시된 시간 이후에 변경된 경우에만 사본을 보내달라는 의미
- 서버 콘텐츠가 변경되지 않은 경우 : 서버 객체가 변경되지 않았다면, 304 Not Modified 응답을 보냄
- 서버 콘텐츠가 변경된 경우 : 사본과 다른 경우 서버는 콘텐츠 전체와 함께 평범한 200 OK 응답을 보냄
- 객체가 삭제된 경우 : 삭제된 경우 404 Not Found 응답을 보냄 그리고 캐시 사본을 삭제
7.5.2 적중률
캐시가 요청을 처리하는 비율을 캐시 적중률 또는 문서 적중률이라고 한다. 적중률은 0에서 1까지의 값으로 흔히 퍼센트로 표현된다.
- 0%는 모든 요청이 부적중(네트워크 너머로 문서를 가져와야 하는 경우)
- 100% 모든 요청이 캐시 적중(캐시에서 사본 가져오는 것)을 의미
- 적중률은 예측하기 어려우나 40% 면 웹캐시로 괜찮은 편
- 보통 크기의 캐시라도 충분한 분량의 자주 쓰이는 문서들을 보관하여 상당한 트래픽을 줄이고 성능을 개선할 수 있다. 캐시는 유용한 콘텐츠가 캐시안에 머무르도록 보장하기 위해 노력한다.
7.5.3 바이트 적중률
바이트 단위 적중률은 캐시를 통해 제공된 모든 바이트의 비율을 표현한다.
- 이 측정값은 트래픽이 절감된 정도 포착
- 바이트 단위 적중률 100%는 모든 바이트가 캐시에서 왔으며, 어떤 트래픽도 인터넷으로 나가지 않았음을 의미
- 트랜잭션은 고정된 소요 시간을 포함하게 되는데, 바이트 단위 적중률은 얼마나 많은 바이트가 인터넷으로 나가지 않았는지 보여준다. 바이트 단위 적중률의 개선은 대역폭 절약을 최적화 한다.
7.5.4 적중과 부적중의 구별
HTTP는 클라이언트에게 응답이 캐시 적중이었는지 아니면 원 서버 접근인지 말해 줄수 있는 방법을 제공하지 않는다. 두 경우 응답 코드는 본문을 갖고 있음을 의미하는 200 OK 가 될것이다.
클라이언트라 응답이 캐시에서 왔는지 알아내는 방법
- 첫째, Date 헤더를 이용하는 것이다.: 응답의 Date 헤더 값ㅅ을 현재 시각과 비교하여, 응답의 생성일을 더 오래되었다면 클라이언트의 응답이 캐시된 것임을 알 수 있다.
- 둘째, 응답이 얼마나 오래되었는지 말해주는 Age 헤더를 이용하는 것이다.
7.6 캐시 토폴로지
- 캐시는 한 명에게만 할당되는 개인 전용 캐시 가 있는데 이는 한 명의 사용자가 자주 찾는 페이지를 담는다.
- 공유된 캐시는 공용 캐시 라고 하며 사용자 집단에게 자주 쓰이는 페이지를 담는다.
7.6.1 개인 전용 캐시
개인 전용 캐시는 많은 에너지나 저장 공간을 필요로 하지 않으므로 작고 저렴할 수 있다. 웹브라우저는 개인 전용 캐시를 내장하고 있다. 대부분의 브라우저는 자주 쓰이는 문서를 개인용 컴퓨터의 디스크와 메모리에 캐시해 놓고, 사용자가 캐시 사이즈와 설정을 수정할 수 있도록 허용한다. 또한 캐시에 어떤 것들이 있는지 확인하기 위해 브라우저 안을 드려다보는 것도 가능하다.
7.6.2 공용 프락시 캐시
- 공용 캐시는 캐시 프락시 서버 혹은 프락시 캐시라고 불리는 특별한 종류의 공유된 프락시 서버다. 프락시 캐시는 로컬 캐시에서 문서를 제공하거나 사용자의 입장에서 서버에 접근한다. 공유캐시에는 여러 사용자가 접근하기 때문에, 불필요한 트래픽을 줄 일 수 있는 더 많은 기회가 있다.
- 각 개인 전용 캐시는 같은 문서를 네트워크를 거쳐 여러 번 가져온다. 그러나 공유된 공유 캐시에서, 캐시는 자주 찾는 객체를 단 한번 만 가져와 모든 요청에 대해 공유된 사본을 제공함으로써 네트워크 트래픽을 줄인다.
- 프락시 캐시는 프락시를 위한 규칙을 따르며 수동 프락시, 프락시 자동설정 파일을 설정하여 브라우저가 프락시 캐시를 사용하도록 설정할 수 있다.
7.6.3 프락시 캐시 계층들
작은 캐시에서 캐시 부적중이 발생했을 때, 더 큰 부모 캐시가 그 걸려 남겨진 트래픽을 처리하도록 하는 계층을 만드는 방식이 합리적인 경우가 많다. 클라이언트 주위에 작고 저렴한 캐시를 사용하고 계층 상단에는 많은 사용자들에 의해 공유되는 문서를 유지하기 위해 더 크고 강력한 캐시를 사용하자는 것이다. -> 물론 캐시 계층이 깊다면 요청은 캐시의 긴 연쇄를 따라가게 될 것이며, 길어질수록 중간 프랒시는 현저한 성능 저하가 발생할 것이다.
7.6.4 캐시망, 콘텐츠 라우팅, 피어링
캐시망의 프락시 캐시는 복잡한 방법으로 서로 대화하며, 어떤 부모 캐시와 대화할것인지 아니면 요청이 캐시를 완전히 우회해서 원 서버로 바로 가도록 할것인지에 대해 캐시 커뮤니케이션 결정을 동적으로 내린다.
- URL에 근거하여, 부모 캐시와 원 서버 중 하나를 동적으로 선택
- URL 에 근거하여 특정 부모 캐시를 동적으로 선택
- 부모 캐시에게 가기전, 캐시된 사본을 로컬에서 찾아본다.
- 다른 캐시들이 그들의 캐시된 콘텐츠에 부분적으로 접근할 수 있도록 허용하되, 그들의 캐시를 통한 인터넷 트렌짓(트래픽이 다른 네트워크로 건거가는것)은 허용하지 않는다. 서로 다른 조직들이 상호 이득을 위해 그들의 캐시를 연결하여 서로를 찾아볼 수 있도록 해주며, 선택적인 피어링을 지원하는 캐시는 형제 캐시라고 한다. HTTP는 형제 캐시를 지원하지 않기 때문에, 인터넷 캐시 프로토콜(ICP)나 하이퍼텍스트 캐시 프로토콜을 이용해 HTTP를 확장했다.
7.7 캐시 처리 단계
HTTP GET 메시지 하나를 처리하는 기본적인 캐리 처리 절차는 일곱 단계로 이루어져있다.
- 요청받기 - 키시는 네트워크로부터 도착한 요청 메시지를 읽는다.
- 파싱 - 메시지를 파싱하여 URL과 헤더들을 추출한다.
- 검색 - 캐시는 로컬 복사본이 있는지 검사하고, 사본이 없다면 사본을 받아온다. (그리고 로컬에 저장)
- 신선도 검사 - 캐시는 캐시된 사본이 충분히 신선한지 검사하고, 신선하지 않다면 변경사항이 있는지 서버에 물어본다.
- 응답 생성 - 캐시는 새로운 헤더와 캐시된 본문으로 응답 메시지를 만든다.
- 발송 - 캐시는 네트워크를 통해 응답을 클라이언트에게 돌려준다.
- 로깅 - 선택적으로, 캐시는 로그파일에 트랜잭션에 대해 서술한 로그 하나를 남긴다.
7.7.1 단계1: 요청받기
캐시는 네트워크 커넥션에서의 활동을 감지하고, 들어오는 데이터를 읽음
7.7.2 단계2: 파싱
캐시는 요청 메시지를 여러 부분으로 파싱하여 헤더 부분을 조작하기 쉬운 자료구조에 담는다.
7.7.3 단계3: 검색
- 캐시는 URL 을 이용하여 로컬 사본이 있는지 검사
- 로컬 복사본은 메모리에 저장되어있을 수 있고, 근처 다른 컴퓨터데 있을 수도 있다.
- 전문적인 수준의 캐시는 객체를 로컬 캐시에서 가져올 수 있는지 판단하기 위해 빠른 알고리즘을 사용한다.
- 만약 로컬에서 가져올 수 없는 경우, 상황/설정에 따라서 원서버나 부모 프락시에서 가져오거나 실패를 반환
- 캐시된 객체는 서버 응답 본문과 원 서버 응답 헤더를 포함하고 있기 때문에 캐시 적중 동안 올바른 서버 헤더가 반환 될수 있다
- 캐시된 객체는 객체가 얼마나 오랫동안 캐시에 있었는지 알려주는 기록이나 자주 사용되었는지에 대한 데이터를 포함
7.7.4 단계4: 신선도 검사
- HTTP는 캐시가 일정기간동안 서버 문서의 사본을 보유 할 수 있도록 한다. ‘신선’으로 간주되면 캐시는 서버와의 접촉 없이 문서를 제공
- 신선도한계를 넘을 정도로 오래된 사본의 경우 신선하지 않은 걸로 간주되며, 캐시는 그 문서를 제공하기 전에 문서에 어떤 변경이 있었는지 검사를 하기 위해 서버와 재검사를 진행
7.7.5 단계5: 응답생성
- 캐시된 응답을 원 서버에서 온것처럼 보이게 하고 싶어서, 캐시는 캐시된 서버 응답 헤더를 토대로 응답 헤더를 생성
- 캐시는 클라이언트에 맞게 헤더를 조정해야하는 책임이 있다.
- 그러나 캐시가 Date 헤더를 조정해서는 안되는 것을 주의해라. Date헤더는 객체가 원서버에서 최초로 생겨난 일시를 나타냄
7.7.6 단계6: 전송
- 응답 헤더가 준비되면, 캐시는 응답을 클라이언트에게 돌려줌
- 프락시 캐시는 클라이언트와의 커넥션을 유지할 필요가 있다.
- 고성능 캐시의 경우 로컬 저장장치, 네트워크 I/O버퍼 사이에서 문서의 콘켄츠 복사를 피함으로서 데이터를 효과적으로 전송하기 위해 노력
7.7.7 단계7: 로깅
- 캐시는 로그 파일과 캐시 사용에 대한 통계를 유지
- 각 캐시 트랜잭션이 완료된후, 캐시는 캐시 적중과 부적중 횟수에 대한 통계를 갱신한다.
- 로그파일에 요청 종류, URL, 어떤 작업이 일어났는지 알려주는 항목을 추가
- 가장 많이 쓰이는 캐시 로그 포맷은 Squid log format, Netscape extended common log format
7.8 사본을 신선하게 유지하기
오래된 데이터를 제공하는 캐시는 불필요하다. 캐시된 데이터는 서버의 데이터와 일치하도록 관리되어야 함 캐시된 사본이 서버와 충분히 일치하도록 유지할 수 있도록 하기 위해 HTTP 는 단순한 메커니즘을 갖고 있다.
7.8.1 문서만료
- HTTP는 Cache-Control과 Expires 라는 헤더를 이용하여 원서버가 각 문서에 유효기간을 붙일 수 있도록 함
- 만료전에는 캐시가 필요하면 서버와의 접촉없이 사본을 제공할 수 있다.
- 만됴뢰면 캐시는 반드시 서버와 무서에 변경된 것이 있는지 검사하고 다른경우 새로운 유효기관과 사본을 서버에서 가져옴
7.8.2 유효기간과 나이
- Cache-Control:max-age: max-age 값은 문서의 최대 나이를 정의한다. 최대 나이는 문서가 처음 생성된 이후부터 더이상 신선하지 않다고 간주될때까지 경과한 시간의 합법적인 최댓값이다.
- Expires: 절대유효시간을 명시한다. 유효기간이 경과했다면, 더이상 신선하지 않은 자료이다.
7.8.3 서버 재검사
- 캐시가 원서버에게 문서가 변경되었는지 여부를 물어볼 필요가 있음을 의미하는 것을 ‘서버 재검사’라고 함
- 재검사 결과 콘텐츠가 변경되었다면, 캐시는 그 문서의 새로운 사본을 가져와오래된데이터 대신 저장한 뒤 클라이언트에게 전달
- 반면 콘텐츠가 변경되지 않았다면 새 만료일을 포함한 새 헤더들만 가져와서 캐시안의 헤더들을 갱신
- HTTP 프로토콜은 캐시가 다음 중 하나를 반환하도록 예상
- 충분히 신선한 캐시된 사본
- 원 서버와 재검사되었기 때문에 충분히 신선하다고 확신할 수 있는 캐시된 사본
- 재검사해야하는 원서버가 다운되어 에러메시지를 전달
- 부정확한 경우 경고 메시지를 부착한 캐시를 전달
7.8.4 조건부 메서드와 재검사
- HTTP 는 캐시가 서버에 ‘조건부 GET’ 요청을 이용하여 재검사를 효율적으로 만듬
- 이 요청은 서버가 갖고 있는 문서가 캐시가 갖고 있는 것과 다른 경우에만 객체 본문을 보내달라는 것
- 신선도 검사와 객체를 받아오는 것은 하나의 조건부 GET 으로 결합된다.
- 캐시 재검사를 할때 가장 유용한 헤더는 IF-Modified-Since 와 If-None-Match
- If-Modified-Since:
: 문서가 주어진 날짜 이후로 수정되었다면 요청 메서드를 처리한다. 캐시된 버전으로부터 콘텐츠가 변경된 경우에면 콘텐츠를 가져오기 위해 Last-Modified 서버 응답 헤더와 함께 사용 - If-None-Match:
: 마지막 변경된 날짜를 맞춰보는 대신, 서버는 문서에 대한 일련번호와 같이 동작하는 특별한 태그를 제공. 캐시된 태그가 서버에 있는 문서의 태그와 다른 경우에면 요청을 처리
- If-Modified-Since:
7.8.5 If-Modified-Since(IMS): 날짜 재검사
리소스가 특정 날짜 이후로 변경되었을 경우만 요청 본문을 보내달라는 의미
- 날짜 이후에 변경되었다면 GET 요청은 평범하게 성공. 새 문서가, 새로운 만료 날짜와 그 외 저보를 담긴 헤더들과 함께 캐시에게 반환
- 날짜 이후에 변경되지 않은 경우는 304 Not Modified 응답메시지를 클라이언트에게 돌려준다. 효율을 위해 본문은 보내지 않는다. 응답은 헤더를 포함하지만, 갱신에 필요한것만 보내준다.
- 원서버는 제공하는 문서에 최근 변경일시를 붙인다.(Last-Modified) 캐시된 문서를 재검사 할때 마지막 수정된 날짜가 담긴 해당 헤더를 포함
- 만약 변경되었다면 최근 변경일시가 다를것이기 때문에 새문서를 보내준다.
- If-Modified-Since 는 실제 날짜 비교로 구별하지 않고 IMS 날짜와 최근 변경일간의 문자열 비교를 수행한다.
7.8.6 If-None-Match: 엔터티 태그 재검사
- 일정 시간 간격으로 다시 쓰여지는 문서의 경우 실제로는 같은 데이터를 포함하는 경우가 있다. 즉 내용에는 아무런 변화가 없이 변경시간만 바뀌는 경우
- 어떤 서버의 경우에는 페이제 대한 최근 변경 일시를 정확하게 판별 할 수 없다
- 1초보다 작은 간격으로 갱신되는 문서의 경우 변경일에 대한 1초의 정밀도는 충분하지 않을 수 있다.
- 따라서 이때 엔터티 태그를 이용하여 해당 태그가 변경되었을 경우 서버는 200 ok응답으로 새 컨텐츠를 새 ETag 와 반환
- 만약 여러개의 사본을 갖고 있는 경우 If-None-Match 여러개의 엔터티 태그를 포함할 수 잇다.
7.8.7 약한 검사기와 강한 검사기
- 약한검사기(weak validator): 모든 캐시된 사본을 무효화시키지 않고 문서를 살짝 고칠 수 있도록 허용 (If-None-Match: W/”v2.6”)
- 강한검사기(strong validator): 콘텐츠가 바귈때마다 바뀐다.
- 원서버는 서로 다른 두 엔터티에 대해 강한 엔터티 태그값을 재활용해서 안되며, 약한 엔터티 태그 값이라고 할지라도 서로 의미가 다른 두 엔터티에 대해서는 재활용해서는 안된다.
- 유효기간에 상관없이 캐시 항목은 임의의 긴 기간 동안 계속 될수 있기 때문에, 캐시가 과거의 특정 시점에서 얻은 검사기를 사용해서 캐시 항목을 다시 검사하려 시도하지 않을것이라는 예상은 틀릴 수 있다
7.8.8 언제 엔터티 태그를 사용하고 언제 Last-Modified 일시를 사용하는가?
- HTTP/1.1 클라이언트는 서버가 엔터티 태그를 반환했다면, 반드시 엔터티 태그 검사기를 사용해야한다
- 서버가 Last-Modified 값만 반환했다면 클라이언트는 If-Modified-Since 검사를 사용할 수 있다.
7.9 캐시제어
7.9.1 no-cache 와 no-store 응답 헤더
- HTTP/1.1 신선도를 관리하기 위해 객체를 캐시하는 것을 제한하거나 캐시된 객체를 제공하는 여러가지 방법을 제공한다.
- no-store, no-cache 헤더는 캐시가 검증되지 않은 캐시된 객체로 응답하는 것을 막는다.
- no-store: 캐시가 그 응답읫 ㅏ본을 만드는 것을 금지
- no-cache: 로컬 캐시 저장소에 저장 될 수 있다. 다만 서버와 재검사를 하지 않고서는 캐시에서 클라이언트로 제공될 수 없을 뿐.
7.9.2 Max-Age 응답 헤더
신선하다고 간주되었던 문서가 서버로부터 시간이 흐른 초를 나타낸다.
7.9.3 Expires 응답 헤더
더 이상 사용하지 않기를 권하는 헤더는 초단위의 시간 대신 실제 만료 날짜를 명시
7.9.4 Must-Revalidate 응답 헤더
신선하지 않은 객체를 제공하도록 설정 할 수 있다. 만약 캐시가 만료 정보를 엄격하기를 원하는 경우 must-revalidate
를 붙일 수 있따.
신선하지 않은 사본을 원서버와의 최초 재검사 없이는 제공해서는 안됨을 의미하며, 항상 신선한 사본을 제공할 수 있다. 만약 원 서버를 사용할 수 없는 경우, 504 Gateway Timeout error 를 반환
7.6.5 휴리스틱 만료
경험적방법으로 최대 나이를 계산하여, 계산 결과로 얻은 최대 나이 값이 24시간 보다 크다면, Heuristic Expiration 경고 헤더가 응답 헤더에 추가 된다.
7.6.6 클라이언트 신선도 제약
웹브라우저는 브라우저나 프락시 캐시의 신선하지 않은 콘텐츠를 강제로 갱신시켜주는 리프레시나 리로드 버튼을 가지고 있다. 리프레시 버튼은 Cache-control 요청 헤더가 추가된 GET 요청 발생시켜서, 강제로 재검사하거나 서버로부터 콘텐츠 무조건 가져온다. 클라이언트는 Cache-Control 요청 헤더를 사용하여 만료 제약을 엄격하게하거나, 느슨하게 할 수 있다.