본문 바로가기

Web

HTTP 캐싱과 캐싱 제어

캐싱이란

  • 어떤 데이터를 한 번 받아온 후에 그 데이터를 불러온 저장소보다 가까운 곳에 임시로 저장하여, 필요 시에 더 빠르게 데이터를 받아오는 프로세스를 의미. 자주 사용하거나 계산이 복잡한 데이터를 캐싱하면 성능 향상. (이전의 계산을 효율적으로 재사용하므로)

HTTP 캐시(웹캐시)

웹 브라우저는 HTTP 프로토콜을 이용해 서버에게 리소스를 요청한다. 이에 따라 서버로부터 응답 받은 리소스를 사용자에게 화면으로 보여주거나 제공한다.

이미 한 번 받았던 리소스를 또 다시 사용자에게 제공해야 한다면, 이와 똑같은 통신 과정을 거치는 것은 비효율적이다.

이 과정의 효율 향상을 위해 캐시의 개념을 HTTP 통신에 적용한 것을 HTTP 캐시 또는 웹 캐시라고 한다

.

웹캐시에는 몇가지 종류가 있다.

  • 저장 위치에 따른 분류:
    브라우저 캐시, 프록시 캐시, 게이트웨이 캐시
  • 사용 범위에 따른 분류:
    한명 이상의 사용자가 재사용할 수 있도록 데이터를 저장하는 공유(Public) 캐시, 단일 사용자가 재사용할 수 있도록 데이터를 저장하는 사설(Private)캐시

브라우저 캐시

  • 브라우저나 HTTP요청을 하는 클라이언트 애플리케이션에 의해 내부 디스크에서 이뤄지는 캐시
  • 메모리 캐시: 브라우저가 실행 중일 때만 유지되며, 빠른 접근 속도를 제공한다.
  • 디스크 캐시: 브라우저가 실행이 종료돼도 유지되며, 더 큰 용량의 데이터를 저장할 수 있다.
  • 사설 캐시

프록시 캐시

  • 프록시(Proxy)는 클라이언트와 원 서버 사이의 중개자로, 원 서버를 대신하여 클라이언트의 요청을 해석하고 이에 응답한다. 이 프록시를 캐시 서버로 이용할 수 있다.
  • 공유 캐시로, 네트워크 상에서 동작한다
  • 프록시 캐싱이란 많은 사용자들이 자주 사용하는 리소스들을 프록시 서버에 저장해 해당 리소스 접근 시간을 절약한다.
  • 예시: 구글 사이트 리소스의 최초 요청 시에만 미국의 원 서버로부터 한국의 프록시 캐시 서버로 가져오고, 한국 클라이언트는 이후 요청부터 한국의 프록시 캐시 서버에서 리소스를 가져온다.

게이트웨이 캐시(Reverse Proxy 또는 CDN)

  • 역방향 프록시(Reverse Proxy): 웹 서버 앞에서 클라이언트의 요청을 웹 서버에 전달하는 서버의 한 유형. 순방향 프록시(Forward Proxy)는 사용자와 인터넷의 방대한 자원 사이의 게이트웨이 역할을 하는 방면, 역방향 프록시는 인터넷과 더 작은 서버 그룹 사이의 게이트웨이 역할을 한다.
  • CDN(Contents Delivery Network): 지리적인 제약 없이 전 세계 사용자에게 빠르고 안전하게 컨텐츠 전송을 할 수 있는 기술이다. 서버를 분산시켜 캐싱해두고 사용자의 컨텐츠 요청이 들어오면 사용자와 가장 가까운 위치에 존재하는 서버로 매핑시켜 요청된 콘텐츠의 캐싱된 내용을 내어주는 방식으로 빠르게 데이터를 전송할 수 있게 된다.
  • CDN은 역방향 프록시의 개념을 확장한 것으로, 전 세계에 분산된 서버 네트워크를 통해 콘텐츠를 더 빠르게 전달한다.
  • CDN이나 리버스 프록시 서버가 정적 콘텐츠를 캐싱하여 사용자와 가까운 위치에서 데이터를 제공한다.

HTTP 캐시 제어 및 유효성 검사

 

HTTP 응답 헤더를 통해 캐싱 동작을 제어하고 유효성을 검증할 수 있다.

  • Cache-control
  • ETag
  • Last-Modified

Cache-control

  • public: 모든 캐시에서의 캐싱을 허용한다.
  • private: 개인 캐시(예: 브라우저 캐시)로 캐싱을 제한한다.
  • max-age=3600 캐시의 최대 수명, 초단위로 설정한다
  • no-cache: 데이터는 캐시해도 되지만, 캐시된 복사본을 사용하기 전에 Origin 서버와의 검증을 요구
  • no-store: 데이터에 민감한 정보가 포함되어 있어 저장 불가 혹은 최대한 빨리 삭제
  • s-maxage: 프록시 캐시 서버에 적용되는 max-age
  • Age: Origin Server의 응답이 프록시 캐시 서버에 머문 시간
  • must-revalidate: 캐시 만료 후 최초 조회시 Origin 서버에 검증

 

콤마로 여러 파라미터를 열거 가능하다.

 

이를 통해

→ 리소스가 캐시되는 시간을 제어

→ 어떤 리소스가 누구에 의해 캐시될 수 있는지 지정 가능

→ 다양한 계층에서의(브라우저, 원본 서버, CDN)에서의 캐시 동작을 관리

 

✔ no-cache와 must-revalidate의 차이점

 

no-cache는 캐시 서버 요청을 하면 프록시 캐시 서버에 도착하면 원 서버에 요청한다.

만약 프록시 캐시 서버와 원 서버 사이에서 네트워크 단절이 일어나 접근이 불가능하다면, no-cache에서 오류가 아닌 오래된 데이터라도 보여주자라는 개념으로 200OK을 응답으로 내보낸다.

 

must-revaildate는 만약 접근이 불가능 하다면 504(Gateway Timeout)라는 오류를 내보낸다

 


 

만일 데이터가 새롭게 갱신된다면, 다시 원서버로부터 데이터를 받아와야한다.

데이터가 최신의 것인지 확인하여 새로운 데이터의 전송이 필요한 지 여부를 확인하는 것, 즉 클라이언트의 데이터와 서버의 데이터가 같은지를 확인하는 것을 캐시 유효성 검사 또는 조건부 요청이라고 한다.

검증 헤더로 캐시 데이터와 서버 데이터가 일치하는 지 여부를 확인할 수 있으며, 최종 수정 시간을 나타내는 Last-Modified와, 특정 리소스 버전을 나타내는 ETag로 나뉜다.

 

Last-Modified

 

최초 요청

GET /index.html HTTP/1.1
Host: example.com

 

최초 요청 시 응답

HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Sat, 03 Sep 2022 00:00:00 GMT //데이터가 마지막으로 수정된 시간
Content-Length: 157

<message body contains resource>

 

두 번째 요청

GET /index.html HTTP/1.1
Host: example.com
If-Modified-Since: Sat, 03 Sep 2022 00:00:00 GMT //캐시의 최종 수정일

 

리소스가 변경되지 않았을 경우 두 번째 응답

HTTP/1.1 304 Not Modified
Last-Modified: Sat, 03 Sep 2022 00:00:00 GMT

 

만일 조건부 요청을 보냈는데, 기존 데이터에 아무런 변경이 없었다면,

서버는 304 Not Modified 응답을 보낸다.

 

리소스가 변경됐을 경우 두번째 응답

HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Sun, 04 Sep 2022 00:00:00 GMT
Content-Length: 250

<message body contains resource>

 

데이터에 수정된 것이 없으므로 이 응답에는 바디를 제외한 헤더 메타 정보만 전송된다.

클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신하고, 캐시에 저장되어 있는 데이터를 재활용한다.

 

Last-Modified의 한계점

ms 단위로 캐시 조정이 불가능하며, 날짜 기반의 정해진 로직을 사용해야 한다.

데이터를 수정하면 파일의 날짜가 갱신된다.

만일 데이터를 A->B->A로 수정한다면 실제 콘텐츠 자체는 수정되지 않았어도 날짜가 변경되었으므로 전체 데이터를 다시 다운로드 받아야 한다.

스페이스나 주석처럼 크게 영향이 없을 때도 마찬가지다.

이러한 한계점에 대응할 수 있는 것이 ETag다.


 

Etag

ETag(Entity Tag)는 웹 서버가 리소스의 버전을 식별한다.

앞서 언급한 상황에선 서버가 ETag를 동일한 값으로 그대로 가지고 있게 되어, 웹 서버에 전체 요청을 보내지 않아 효율적으로 캐시를 관리한다.

만약 해당 요청의 리소스가 변경됐다면 새로운 ETag 가 생성된다.

 

최초 요청

GET /index.html HTTP/1.1
Host: example.com

 

최초 요청 시 응답

HTTP/1.1 200 OK
Content-Type: text/html
ETag: "abcdefg"
Content-Length: 157

<message body contains resource>

 

웹 브라우저는 ETag 헤더와 함께 응답 결과를 캐시에 저장

 

두 번째 요청

GET /index.html HTTP/1.1
Host: [example.com](<http://example.com/>)
If-None-Match: "abcdefg"

 

이후 캐시 시간이 초과되어 리소스에 대한 재요청 시 If-None-Match 헤더에 저장해 둔 ETag 값을 넣어 보낸다.

 

리소스가 변경되지 않았을 경우 두번째 응답

HTTP/1.1 304 Not Modified
ETag: "abcdefg"

 

304 Not Modified로 응답

 

리소스가 변경되었을 경우 두 번째 응답

HTTP/1.1 200 OK
Content-Type: text/html
ETag: "hijklmn"
Content-Length: 500

<message body contains resource>