앱이나 웹을 사용할 때, 속도가 느리면 사용자들은 많은 불편을 느낀다.
이러한 불편을 해소하기 위해 빠른 응답을 위해서 개발자들은 많은 노력을 한다.
웹 서버 캐싱 처리
웹에 요청을 호출 하면, 요청은 웹 브라우저로 부터 하드 디스크의 파일 시스템에 있는
정적 리소스를 제공하는 웹 서버로 전달 한다.
이때 성능을 고려하여 캐싱 시스템을 잘 활용하고 있는 시스템 환경상이라고 한다면
웹 서버로 첫 요청시, 하드 디스크는 캐시를 확인하고 "캐시 미스(Cache miss)"를 발생시킨다.
그리고 추후 다시 요청받을 수 있다고 하면 캐시를 하드디스크에 저장한다.
이후 요청부터는 캐시를 사용할 수 있는 경우 "캐시 히트(Cache hit)"를 발생시키고,
캐시 미스가 발생하기 전까지 버퍼에서 캐시가 제공 된다.
응답 캐싱
웹 서버는 응답을 캐싱하도록 구성하여 유사한 요청이 애플리케이션 호스트로 전달되지 않도록 할 수 있다.
이와 비슷한 방식으로, 애플리케이션 호스트는 비용이 높은 데이터베이스 쿼리나 자주 요청되는 파일에 대한 응답을 캐시할 수도 있다.
웹 서버의 응답은 메모리에 캐싱하고, 애플리케이션 캐시는 로컬 인메모리에 저장하거나 캐시 서버 위에서 실행되는 레디스와 같은 인메모리 데이터베이스에 저장할 수 있다.
HTTP 헤더를 통한 브라우저 캐싱
모든 브라우저는 HTML 페이지, 자바스크립트 파일 및 이미지와 같은 웹 문서의 임시 저장을 위해
HTTP 캐시 (웹 캐시)의 구현을 제공하고있다.
HTTP 헤더 지시문을 제공하여 브라우저가 응답을 캐싱할 수 있는 시기와 지속 기간을 지시할 때 사용된다.
리소스가 로컬 캐시로부터 빠르게 로드되기 때문에 점점 하드웨어 성능이 급격하고 있는 최근 잘만 활용한다면 엄청 강력한 속도를 제공 한다.
요청이 네트워크를 통해 전송되지 않기 때문에 왕복 시간(RTT, Round Trip Time)이 발생하지 않는다.
애플리케이션 서버 및 파이프라인의 다른 구성 요소에 대한 부하가 줄어든다.
WEB-CACHE
client가 요청하는 Resource(html, image, js, css등)에 대해 최초 요청 시 파일을 내려받아 특정 위치에 복사본을 저장, 이후 동일한 URL의 Resource요청은 내부에 저장한 파일(캐시)을 사용하여 더 빠르게 서비스한다.
서버를 통하지 않아 응답 시간이 감소하고 네트워크 트레픽이 감소되니 잘만 사용한다면 정말 좋은일이다. 하지만 잘못 사용한다면 고객들에게 실시간으로 정보를 올바르게 주지 못하고, 오히려 고객 CS가 발생하는 등 해당 업무 프로세스와 시스템 환경을 잘 분석하여 적용하는 것이 중요하다.
Header 지시문을 통한 캐싱
모든 브라우저에는 HTTP 캐시 구현이 포함되어 있기 때문에 서버 응답이 브라우저에 응답을 캐시할 수 있는 시점, 그 기간을 지시하기 위한 올바른 HTTP 헤더 지시문을 제공하는지 확인하면 캐시 적용이 가능하다.
캐시 설정을 통해 브라우저에 응답으로 온 HTML, JSON 등의 이미 저장된 데이터를 통해 서버에 요청을 보내지 않고도 사용할 수 있다.
일반 적으로 캐싱은 GET 요청에서 처리한다.
일반적으로 상태 코드로 온 응답등을 캐싱할 수 있다.
Header 지시문을 통한 캐싱 문법
public
공유 캐시(또는 중개 서버)에 저장해도 된다는 뜻이다. ex) public, max-age=3600
max-age로 캐시 유효시간을 줄 수 있다. 초 단위이므로 1시간이 지나면 이 응답 캐시는 만료된 것으로 여겨진다.
대부분의 경우, 명시적 캐싱 정보(예: 'max-age')가 응답이 어떠한 경우든지 캐시가 가능하다고 나타내므로 'public'이 필요하지 않다.
private
브라우저같은 특정 사용자 환경에만 저장하라는 뜻이다. 일반적으로 단일 사용자를 대상으로 하므로 중간 캐시가 이 응답을 캐시하는 것은 허용되지 않는다. 예를 들어, 비공개 사용자 정보가 포함된 HTML 페이지는 사용자의 브라우저가 캐시할 수 있지만, CDN은 이 페이지를 캐시할 수 없다.
no-cache
캐시를 사용하지 말라는 뜻이 아니라 캐시를 쓰기 전에 서버에 이 캐시 진짜 써도 되냐고 물어보라는 뜻이다.
이것은 원본 서버가 클라이언트의 요청에 오래된(stale) 응답으로 돌려 주도록 설정하는 캐시를 의한 캐싱을 방지하도록 허용하는 것이다.
no-store
아무것도 캐싱하지 않으려면 사용한다. ex) Cache-Control: no-cache, no-store
부주의하게 공개되었거나 민감한 정보의 저장을 막는 것이다. no-stroe 지시자는 전체 메시에 적용된다.
그리고 응답과 요청 모두에 보내진다.
만약 요청 시에 보내졌다면, 캐시는 어떠한 응답 또는 이 요청 또한 어떠한 부분도 저장되지 않아야만 한다.
만약 응답 시에 보내졌다면, 캐시는 그것을 발생시킨(elicated) 응답과 현재의 응답 어떠한 부분에도 저장되지 않아야만 한다.
must-revalidate
만료된 캐시만 서버에 확인을 받도록 한다.
ex) Cache-Control: max-age=86400
max-age
캐시 유효시간, 즉 리소스가 유효하다고 판단되는 최대 시간 이다.
초단위로 설정하며, 해당 시간이 지나면 만료된것으로 여겨진다.
ex) Cache-Control: max-age=31536000
Age
캐시 응답 때 나타나는데, max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려준다.
Expires
Cache-Control과 동시에 동작하진 않지만, Expires라는 헤더를 지정하여 응답 컨텐츠 만료 시간을 나타낼 수 있다.
ex) Expires: Wed, 23 Jan 2019 03:44:00 GMT
Cache-Control의 max-age가 있는 경우 이 무시된다.
유효 수명 : Expires 헤더에서 Date 헤더의 값을 뺀 결과
ETag로 캐시된 응답에 대한 유효성 검사 수행한다. (HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그)
서버는 ETag HTTP 헤더를 사용하여 유효성 검사 토큰을 전달한다.
유효성 검사 토큰을 사용하여 리소스 업데이트 검사하며 리소스가 변경되지 않은 경우 데이터가 전송되지 않는다.
ex) 클라이언트에 최대 120초 동안 캐시하도록 지시하고, 응답이 만료된 후 리소스가 수정되었는지 확인하는 데 사용할 수 있는 유효성 검사 토큰('x456dff')을 제공한다.
ETag가 달라졌는 지 검사하고 ETag가 다를 경우에만 컨텐츠를 새로 받는다.
ex) If-None-Match: "0-2b800-5c466dda"
만약 ETag가 같다면 서버는 304 Not Modified를 응답하고 캐시를 그대로 사용하게 한다.
클라이언트에서 분명 데이터가 변경 되었는데 계속 캐쉬 데이터를 읽어오는 문제가 발생하였다.
JSON 형태로 응답을 받는 호출이 있었는데 이 호출시 응답이 계속 304로 내려왔기 때문이다.
이는 해당 응답이 내려오는 에러를 처리하여 해결하였다.