본문 바로가기
FrontEnd/HTTP

[HTTP] HTTP 헤더2 - 캐시와 조건부 요청

by 개발 Blog 2024. 10. 9.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

 

캐시 기본 동작

캐시가 없을

번째 요청

  • 클라이언트가 서버에 요청을 보내고 서버는 응답을 보낸다. (캐시가 없는 상황)
  • 네트워크를 통해 데이터가 전송된다.

캐시가 없을

번째 요청

  • 동일한 요청이 다시 발생하면 서버로부터 데이터를 또 받아야 한다.
  • 캐시가 없으므로 매번 서버로부터 데이터를 다운로드 받아야 한다.

캐시가 없을 때 발생하는 문제

  • 데이터가 변경되지 않아도 계속 네트워크를 통해 데이터를 받아야 한다.
  • 인터넷 네트워크는 느리고 비싸기 때문에 성능 저하와 비용 문제가 발생한다.
  • 브라우저 로딩 속도가 느리며 사용자 경험이 저하된다.

캐시 적용

번째 요청

  • 클라이언트가 서버에 요청을 보낼 때, 서버는 데이터를 보내고 캐시에 저장한다.
  • 이후 동일한 데이터 요청 시 캐시에서 바로 응답이 가능하다.

캐시 적용

번째 요청

  • 캐시가 유효한 시간 내에 동일한 요청이 발생하면, 서버에 다시 요청하지 않고 캐시에서 데이터를 제공한다.
  • 이를 통해 서버 부하를 줄이고 네트워크 사용을 최소화할 수 있다.

캐시 적용의 장점

  • 캐시 유효 시간 동안 네트워크를 사용하지 않는다.
  • 비싼 네트워크 비용을 줄일 수 있다.
  • 브라우저 로딩 속도가 빨라진다.
  • 빠른 사용자 경험을 제공한다.

캐시 적용

번째 요청 - 캐시 시간 초과

  • 캐시 유효 시간이 초과하면 서버로 데이터를 다시 요청하고 조회한다.
  • 서버는 최신 데이터를 전송하고, 브라우저는 받은 데이터를 캐시에 갱신한다.
  • 이때 다시 네트워크를 통해 데이터를 다운로드 받는다.

캐시 시간 초과 시 동작

  • 캐시가 만료되면 브라우저는 서버로부터 새로운 데이터를 받아 캐시에 저장한다.
  • 새로운 응답을 받은 후 캐시는 다시 유효 시간을 갖게 된다.

검증 헤더와 조건부 요청1

1. 캐시 시간 초과 후 동작

  • 캐시 유효 시간이 초과하면 서버에 다시 요청한다.
  • 이때 두 가지 상황이 발생할 수 있다.
    1. 서버에서 기존 데이터를 변경함.
    2. 서버에서 기존 데이터를 변경하지 않음.

2. 서버에서 데이터를 변경하지 않는 경우

  • 캐시 만료 후에도 서버에서 데이터가 변경되지 않으면 데이터를 전송할 필요가 없다.
  • 대신 저장된 캐시를 재사용할 수 있다.
  • 단, 클라이언트의 데이터와 서버의 데이터가 같다는 것을 검증할 수 있는 방법이 필요하다.

 

검증 헤더 추가

번째 요청

  • 클라이언트가 서버에 /star.jpg를 요청한다.
  • 서버는 데이터를 전송하고, 응답 헤더에 Last-Modified와 같은 검증 헤더를 포함시켜 보낸다.
  • 클라이언트는 응답을 받은 후, 데이터와 함께 헤더 정보를 캐시에 저장한다.
  • 캐시는 유효 시간이 60초로 설정된다.

번째 요청 - 캐시 시간 초과

  • 캐시 유효 시간이 초과된 후, 클라이언트는 /star.jpg를 다시 요청한다.
  • 이때 클라이언트는 이전에 받은 Last-Modified 정보를 기반으로 If-Modified-Since 헤더를 포함하여 서버에 요청을 보낸다.
  • 서버는 클라이언트가 보낸 If-Modified-Since 헤더 값을 확인하여 데이터가 변경되었는지 여부를 판단한다.

  • 서버가 데이터를 변경하지 않았다면, 304 Not Modified 응답을 보내고 HTTP Body는 전송하지 않는다.
  • 이후 클라이언트는 기존에 캐시된 데이터를 그대로 사용하여 빠른 응답을 제공받는다.

검증 헤더와 조건부 요청 정리

  • 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면 서버는 304 Not Modified 응답과 함께 헤더 메타 정보만 전송하고, HTTP Body는 전송하지 않는다.
  • 클라이언트는 서버가 보낸 응답 헤더 정보를 기반으로 캐시의 메타 정보를 갱신한다.
  • 클라이언트는 기존 캐시에 저장되어 있는 데이터를 재활용한다.
  • 결과적으로 네트워크 다운로드가 발생하지만, 용량이 적은 헤더 정보만 다운로드된다.
  • 이는 매우 실용적인 해결책이다.

검증 헤더와 조건부 요청2

검증 헤더

  • 캐시 데이터와 서버 데이터가 동일한지 검증하는 정보이다.
  • 대표적인 검증 헤더는 Last-Modified와 ETag이다.

조건부 요청 헤더

  • 검증 헤더를 기반으로 조건부 요청을 수행한다.
  • If-Modified-Since: Last-Modified 값을 사용하여 조건을 판단한다.
  • If-None-Match: ETag 값을 사용하여 조건을 판단한다.

조건에 따른 서버 응답

  • 조건이 만족하면 200 OK 응답과 함께 데이터를 전송한다 (Body 포함).
  • 조건이 만족하지 않으면 304 Not Modified 응답을 보내며, 헤더 정보만 전송한다 (Body 미포함).

예시

If-Modified-Since: 이후에 데이터가 수정되었을 경우

1. 데이터 미변경 예시

  • 캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 10:00:00
  • 결과: 304 Not Modified, 헤더 데이터만 전송 (Body 미포함)
  • 전송 용량: 0.1M (헤더 0.1M)

2. 데이터 변경 예시

  • 캐시: 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 11:00:00
  • 결과: 200 OK, 모든 데이터 전송 (Body 포함)
  • 전송 용량: 1.1M (헤더 0.1M, 바디 1.0M)

Last-Modified, If-Modified-Since 단점

  1. 1초 미만 단위의 캐시 조정 불가능
    • Last-Modified는 초 단위로 처리되어 1초 미만의 시간 단위로 캐시 조정이 어렵다.
  2. 날짜 기반의 로직 사용
    • 데이터를 수정하면 날짜가 다르지만, 실제로 같은 데이터를 수정하는 경우도 있다. 이런 경우에도 캐시 갱신이 필요하지 않을 수 있다.
  3. 서버에서 별도의 캐시 로직 관리 필요
    • 스페이스나 주석 같은 사소한 변경으로 인해 캐시를 갱신하지 않고 유지하고 싶은 경우가 있다.

ETag와 If-None-Match

  1. ETag(Entity Tag)
    • 캐시 데이터에 고유한 버전 이름을 부여하여 관리한다.
    • 예: ETag: "v1.0", ETag: "a2jiodwjekjl3"
  2. ETag 변경 방식
    • 데이터가 변경되면 ETag 이름을 변경하여 이를 구분한다 (Hash 값을 다시 생성).
    • 예: ETag: "aaaaa" -> ETag: "bbbbb"
  3. 단순하고 효율적인 방식
    • 클라이언트가 ETag를 서버로 보내서, 동일하면 캐시를 유지하고 다르면 데이터를 다시 받는다.

검증 헤더 추가

번째 요청

  • 클라이언트가 /star.jpg 파일을 서버에 요청한다.
  • 서버는 파일을 전송하며, 응답에 ETag 값을 포함하여 보낸다. (예: ETag: "aaaaaaaaa")
  • 클라이언트는 이 응답을 받아 데이터를 캐시에 저장하고, ETag 값도 함께 저장한다.
  • 캐시는 60초 동안 유효하게 유지된다.

번째 요청 - 캐시 시간 초과

  • 캐시 유효 시간이 초과된 후, 클라이언트는 /star.jpg 파일을 다시 요청한다.
  • 이때, If-None-Match 헤더에 캐시 된 ETag: "aaaaaaaaa" 값을 포함하여 서버에 전송한다.
  • 클라이언트는 서버가 해당 ETag 값을 비교하여 데이터가 변경되었는지 판단하도록 요청한다.

이 과정을 통해 클라이언트는 서버로부터 필요한 데이터가 수정되었는지 확인하고, 불필요한 데이터를 다시 전송받지 않도록 요청한다.

  1. 서버는 클라이언트가 보낸 If-None-Match 헤더의 ETag: "aaaaaaaaa" 값을 확인하여, 서버에 저장된 파일의 ETag와 동일한지 비교한다.
  2. 데이터가 변경되지 않았을 경우, 서버는 304 Not Modified 응답을 보내며, HTTP Body는 전송하지 않는다.
  3. 응답에는 ETag와 같은 헤더 정보만 포함되며, 클라이언트는 기존 캐시에 저장된 데이터를 그대로 사용한다.
  4. 클라이언트는 응답 헤더 정보를 통해 캐시의 메타 데이터를 갱신하고, 캐시 유효 시간을 연장하여 이후 요청에 대비한다.

이로써 클라이언트는 불필요한 데이터 다운로드 없이 빠르게 기존 데이터를 재활용할 수 있게 된다.

 

검증 헤더와 조건부 요청 - ETag, If-None-Match 정리

  1. 간단한 방식
    • 클라이언트는 ETag 값을 서버에 보내서, 값이 같으면 캐시를 그대로 유지하고, 값이 다르면 데이터를 다시 받아온다.
  2. 서버에서 캐시 제어
    • 캐시 제어 로직은 서버에서 완전히 관리한다.
    • 클라이언트는 캐시 메커니즘을 신경 쓰지 않고, 단순히 서버로 ETag 값을 전달하는 역할을 한다.
  3. 예시
    • 서버는 베타 오픈 기간 동안 파일이 변경되어도 ETag 값을 동일하게 유지한다.
    • 이후 애플리케이션 배포 주기에 맞춰 ETag 값을 모두 갱신하여 새로운 파일을 제공한다.

이 방식은 캐시 관리를 서버가 주도적으로 하며, 클라이언트는 캐시의 유효성을 검증하는 간단한 역할만 수행한다.

 

캐시와 조건부 요청 헤더

캐시 제어 헤더

  1. Cache-Control
    • 캐시 제어를 위한 주요 헤더이다.
  2. Pragma
    • 캐시 제어를 위한 헤더로, 하위 호환을 위한 것이다.
  3. Expires
    • 캐시의 유효 기간을 설정하는 헤더로, 하위 호환용이다.

Cache-Control

캐시 지시어(directives)

  • Cache-Control: max-age
    • 캐시의 유효 시간을 초 단위로 설정한다.
  • Cache-Control: no-cache
    • 데이터를 캐시해도 되지만, 항상 원본 서버에서 검증 후 사용한다.
  • 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는 무시된다.

검증 헤더와 조건부 요청 헤더

  1. 검증 헤더 (Validator)
    • ETag: "v1.0", "asid93jkrh2l".
    • Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT.
  2. 조건부 요청 헤더
    • If-Match, If-None-Match: ETag 값을 사용한다.
    • If-Modified-Since, If-Unmodified-Since: Last-Modified 값을 사용한다.

이 헤더들은 캐시와 데이터 유효성을 관리하고, 서버와 클라이언트 간의 효율적인 데이터 전송을 가능하게 한다.

 

프록시 캐시

서버 직접 접근(origin 서버)

  • 사용자가 미국에 있는 원 서버에 직접 접근할 경우, 응답을 받는 데 500ms(0.5초)가 소요된다.
  • 이는 한국에 있는 클라이언트가 물리적으로 멀리 떨어진 서버에 직접 접근하기 때문에 발생하는 지연이다.

프록시 캐시 도입

번째 요청

  • 클라이언트가 프록시 캐시 서버를 통해 원 서버에 접근하면, 프록시 캐시 서버가 원 서버로부터 응답을 받고 이를 클라이언트에게 전달한다.
  • 한국에 있는 프록시 캐시 서버를 거치면, 클라이언트와의 통신 시간이 100ms(0.1초)로 단축된다.
  • 원 서버와 프록시 서버 간 통신에는 400ms(0.4초)가 소요되지만, 전체적으로 효율적인 응답을 제공한다.

이후 요청

  • 클라이언트가 다시 요청을 보낼 때, 프록시 캐시 서버에 저장된 데이터를 100ms(0.1초) 만에 받을 수 있다.
  • 원 서버에 대한 요청을 줄임으로써 네트워크 성능을 크게 향상시킨다.

Cache-Control

캐시 지시어(directives) - 기타

  • Cache-Control: public
    • 응답을 공용(public) 캐시에 저장해도 된다.
  • Cache-Control: private
    • 응답이 해당 사용자만을 위한 것으로, private 캐시에 저장해야 한다. (기본값)
  • Cache-Control: s-maxage
    • 프록시 캐시에만 적용되는 max-age 값이다.
  • Age: 60 (HTTP 헤더)
    • 원 서버에서 응답한 후 프록시 캐시 내에 머문 시간을 초 단위로 나타낸다.

프록시 캐시를 도입하면, 서버 부하를 줄이고 사용자에게 빠른 응답을 제공하는 데 매우 유리하다.

 

캐시 무효화

캐시 무효화는 서버가 캐시 된 데이터를 반드시 재검증하거나 삭제하도록 하는 방식이다. 캐시 제어 헤더 중에서 Cache-Control: no-cache, no-store, must-revalidate와 같은 지시어는 확실한 캐시 무효화를 보장한다. 또한, Pragma: no-cache는 HTTP 1.0 하위 호환을 위한 헤더다.

  1. Cache-Control: no-cache는 데이터를 캐시 할 수 있지만, 사용할 때마다 원 서버에서 검증해야 한다. 이름과는 다르게 데이터를 저장할 수 있으며, 단지 검증만 필수적이다.
  2. Cache-Control: no-store는 민감한 정보가 포함된 데이터를 저장하지 않고, 메모리에서 사용하고 즉시 삭제하는 방식이다.
  3. Cache-Control: must-revalidate는 캐시 만료 후에는 반드시 원 서버에 검증을 거쳐야 하며, 서버 접근이 실패하면 504 Gateway Timeout과 같은 오류가 발생해야 한다. 유효한 캐시 시간 내에는 캐시를 사용할 수 있다.

Pragma: no-cache는 HTTP 1.0 하위 호환을 위한 옵션으로, Cache-Control: no-cache와 동일한 역할을 한다.

이와 같은 캐시 무효화 방식은 데이터를 안전하게 유지하고, 항상 최신 상태를 보장하기 위해 필수적이다.

 

캐시 서버로의 요청

클라이언트가 no-cache와 ETag를 포함한 요청을 캐시 서버로 보낸다.

  • 클라이언트는 브라우저 캐시 데이터를 가지고 있지만, no-cache로 인해 서버 검증이 필요하다.
  • 캐시 서버는 클라이언트가 제공한 ETag와 원 서버의 데이터를 비교하기 위해 원 서버로 요청을 보낸다.

원 서버 검증 및 캐시 데이터 사용

캐시 서버가 원 서버로 no-cache와 ETag 요청을 보내 검증을 진행한 후, 원 서버로부터 304 Not Modified 응답을 받는다.

  • 원 서버는 데이터가 변경되지 않았음을 알리기 위해 304 Not Modified를 응답한다.
  • 이 응답을 캐시 서버가 받으면, 캐시 서버는 클라이언트에게 다시 304 응답을 전달하고, 클라이언트는 자신이 가지고 있는 캐시 데이터를 재사용한다.
  • 클라이언트는 원 서버와 동일한 데이터임을 확인하고 네트워크 대역폭을 절약할 수 있다.

캐시 서버와 원 서버 접속 불가 시 상황

캐시 서버가 원 서버에 접속할 수 없을 때, 캐시 서버는 설정에 따라 예전 캐시 데이터를 반환하거나 오류를 반환한다.

  • no-cache 지시어가 적용되었지만, 원 서버에 접속할 수 없는 상황에서는 캐시 서버가 네트워크 오류를 발생시키거나, 캐시 서버에 남아 있는 데이터라도 클라이언트에 반환할 수 있다. 이는 캐시 서버의 설정에 따라 달라진다.
  • 여기서 캐시 서버가 데이터를 반환할지, 오류를 발생시킬지는 서버의 정책에 의존하게 된다.

must-revalidate 설정

클라이언트가 must-revalidate와 ETag를 포함한 요청을 캐시 서버로 보낸다. 캐시 서버가 원 서버에 접속할 수 없을 경우 504 Gateway Timeout 오류를 반환한다.

  • must-revalidate 지시어가 있을 경우, 캐시 서버는 원 서버 검증 없이 캐시 데이터를 사용하지 못한다. 따라서 네트워크 장애 시 반드시 오류를 발생시켜야 한다.
  • 이 경우 504 Gateway Timeout과 같은 오류가 반환된다. 이는 중요한 데이터일수록 보안을 강화하기 위한 조치이다.

'FrontEnd > HTTP' 카테고리의 다른 글

[HTTP] HTTP 헤더1 - 일반 헤더(2)  (1) 2024.10.08
[HTTP] HTTP 헤더1 - 일반 헤더(1)  (2) 2024.10.08
[HTTP] HTTP 상태코드  (0) 2024.10.08
[HTTP] HTTP 메서드 활용  (1) 2024.10.07
[HTTP] HTTP 메서드  (1) 2024.10.06