HTTP 캐싱 설명: 강한 캐시 vs. 협상 캐시
Grace Collins
Solutions Engineer · Leapcell

브라우저 캐싱 메커니즘
브라우저에서 웹 페이지를 열 때, 브라우저는 입력된 URL을 기반으로 해당 서버에 요청을 보내 필요한 데이터 리소스를 가져온다는 것을 우리 모두 알고 있습니다. 그러나 이 과정에서 페이지가 화면에 렌더링되기 전에 로딩하는 데 시간이 걸릴 수 있습니다(흰색 화면이 나타남).
사용자 경험을 개선하기 위해 DNS 캐싱, CDN 캐싱, 브라우저 캐싱, 로컬 페이지 캐싱 등 다양한 캐싱 기술이 필수적입니다. 좋은 캐싱 전략은 불필요한 리소스 요청을 줄이고 서버 오버헤드를 낮추며 페이지 로드 속도를 향상시킬 수 있습니다.
이 문서에서는 HTTP 강한 캐싱과 협상 캐싱에 중점을 둘 것입니다.
기본 원리
브라우저가 리소스를 로드할 때 먼저 Expires
및 Cache-Control
요청 헤더를 검사하여 강한 캐싱 전략을 적용할지 여부를 결정합니다. 이는 브라우저가 원격 서버에서 리소스를 요청할지 아니면 로컬 캐시에서 검색할지를 결정합니다.
강한 캐싱
브라우저에서 강한 캐싱은 Expires
(HTTP/1.0 사양에 정의됨)와 Cache-Control
(HTTP/1.1에 정의됨)의 두 가지 범주로 나뉩니다.
Expires
Expires
는 리소스의 만료 시간을 나타내는 응답 헤더 필드로 사용되는 HTTP/1.0의 표준입니다. 값은 서버에서 반환된 절대 타임스탬프입니다.
- 브라우저가 처음으로 리소스를 요청할 때 서버의 응답 헤더에
Expires
필드가 포함됩니다. - 다음에 브라우저가 동일한 리소스를 요청할 때 이전 응답의
Expires
값을 확인합니다. - 현재 요청 시간이
Expires
에 지정된 만료 시간보다 빠르면 브라우저는 캐시된 리소스를 직접 사용합니다.
그러나 Expires
는 로컬 시스템 시간에 의존하기 때문에 클라이언트와 서버 시계 간의 불일치로 인해 캐시 불일치가 발생할 수 있습니다.
Cache-Control
앞서 언급했듯이 Expires
에는 단점이 있습니다. 클라이언트의 로컬 시간이 서버 시간과 다르면 캐시 정확도가 영향을 받을 수 있습니다. 이 문제를 해결하기 위해 HTTP/1.1은 Expires
보다 우선하는 Cache-Control
필드를 도입했습니다. Expires
와 달리 Cache-Control
은 절대 타임스탬프 대신 상대 시간을 사용하여 캐시 만료를 정의합니다.
가장 일반적인 Cache-Control
지시어는 다음과 같습니다.
max-age
: 리소스가 신선하게 유지되는 시간(초)을 지정합니다(예:3600
). 즉,현재 시간 + 3600초
입니다.s-maxage
:max-age
와 유사하지만 프록시 서버의 캐싱을 위해 특별히 사용됩니다.private
: 리소스는 개인 캐시(즉, 클라이언트에 의해서만 캐시되고 프록시 서버와 같은 공유 캐시에는 캐시되지 않음)에 의해서만 캐시될 수 있습니다.public
: 리소스는 클라이언트와 프록시 서버 모두에서 캐시될 수 있습니다.no-store
: 모든 종류의 캐싱을 방지합니다.no-cache
: 리소스는 로컬 캐시에 저장되지만 클라이언트에 제공되기 전에 원본 서버로 재검증되어야 합니다.
협상 캐싱
강한 캐싱은 브라우저 자체에 의해 결정됩니다. 강한 캐싱이 적중되지 않으면 브라우저는 서버에 요청을 보내 협상 캐싱이 적용되는지 확인합니다. 캐시가 유효하면 서버는 새 리소스 데이터 대신 304 Not Modified 상태를 반환합니다.
협상 캐싱(또는 조건부 캐싱)은 서버에 의해 결정되며 두 세트의 쌍을 이루는 헤더를 포함합니다. 브라우저가 처음 요청할 때 서버는 응답에 Last-Modified
또는 ETag
헤더를 포함합니다. 후속 요청에는 리소스가 변경되었는지 여부를 확인하기 위해 해당 요청 헤더(If-Modified-Since
또는 If-None-Match
)가 포함됩니다.
Last-Modified
: 서버에서 반환된 리소스의 마지막 수정 시간을 나타냅니다.If-Modified-Since
: 브라우저에서 요청 시 전송되며 이전Last-Modified
값을 포함합니다.ETag
: 리소스에 대한 고유 식별자입니다. 리소스가 변경되면ETag
값이 그에 따라 변경됩니다. 파일 내용이 동일하게 유지되더라도 변경될 수 있는Last-Modified
와 달리ETag
는 더 정확한 캐시 유효성 검사를 보장합니다.If-None-Match
: 브라우저에서 요청 시 전송되며 이전에 반환된ETag
값을 포함합니다.
강한 캐싱 및 요청 흐름
- 브라우저가 리소스를 요청할 때 먼저 로컬 캐시 레코드가 있는지 확인합니다. 레코드가 없으면 서버에 요청을 보내 반환된
Last-Modified
값을 저장합니다. - 캐시 레코드가 있는 경우 브라우저는 먼저 강한 캐싱이 여전히 유효한지 확인합니다(
Cache-Control
이Expires
보다 우선함). 캐시가 여전히 유효하면 브라우저는 캐시된 리소스를 제공합니다(HTTP 상태 200). - 강한 캐싱이 만료된 경우 브라우저는 협상 캐싱 전략을 사용하여 요청을 시작합니다. 서버는 먼저
ETag
값을 확인합니다.- 클라이언트의
ETag
가 서버의ETag
와 일치하면 서버는 304 Not Modified를 반환합니다(리소스 데이터를 보내지 않음).
- 클라이언트의
- 서버가
ETag
를 사용하지 않으면If-Modified-Since
를 확인합니다. 제공된 값이 서버의 마지막 수정 시간과 일치하면 서버는 304 Not Modified를 반환합니다. ETag
와If-Modified-Since
가 모두 일치하지 않으면 서버는 새로운 리소스를 보내고 캐시를 업데이트합니다.
ETag가 필요한 이유?
ETag
는 다음과 같은 Last-Modified
의 문제를 해결하기 위해 도입되었습니다.
- 타임스탬프 부정확성: 파일의 마지막 수정 타임스탬프는 내용이 동일하게 유지되더라도 변경될 수 있으며, 이로 인해 불필요한 캐시 무효화가 발생합니다.
- 고빈도 수정:
Last-Modified
는 초 단위의 세분성만 지원하므로 자주 업데이트되는 파일에는 충분하지 않을 수 있습니다.ETag
는 더 나은 정밀도를 보장합니다. - 일부 서버는 파일의 마지막 수정 시간을 정확하게 확인할 수 없으므로
ETag
가 더 나은 대안입니다.
HTTP 상태 코드의 차이점
200
: 요청이 성공적으로 완료되었으며 서버는 리소스의 새로운 사본을 반환합니다.200 (from memory cache / from disk cache)
: 강한 캐싱이 여전히 유효하므로 브라우저는 로컬 캐시에서 리소스를 로드합니다.304 Not Modified
: 요청에서 협상 캐싱을 사용했으며 서버는 캐시된 리소스가 여전히 유효하다고 판단했습니다.
참고:
from memory cache
: 리소스가 메모리에서 검색되었습니다(예: 소프트 새로 고침 후).from disk cache
: 리소스가 디스크 스토리지에서 검색되었습니다(예: 브라우저 탭을 다시 연 후).
캐시 우선 순위 규칙
Expires
와Cache-Control
이 모두 있는 경우Cache-Control
이 우선합니다.- Cache-Control > Expires
- 강한 캐싱과 협상 캐싱이 모두 있는 경우 브라우저는 먼저 강한 캐싱을 확인합니다. 캐시가 여전히 유효하면 사용됩니다. 그렇지 않으면 협상 캐싱이 적용됩니다.
- 강한 캐싱 > 협상 캐싱
ETag
와Last-Modified
가 모두 있는 경우ETag
가 우선합니다.- ETag > Last-Modified
추가 참고 사항
HTTP/1.0 사양에는 Cache-Control: no-cache
와 동일한 효과를 내는 Pragma
라는 이전 캐싱 지시어가 있었습니다. Pragma
는 브라우저가 원본 서버로 리소스를 재검증하도록 강제합니다.
캐싱 우선 순위 순서:
Pragma -> Cache-Control -> Expires -> ETag -> Last-Modified
휴리스틱 캐싱
응답에 Expires
또는 Cache-Control
헤더가 포함되어 있지 않지만 Last-Modified
가 포함되어 있는 경우 브라우저는 휴리스틱 캐싱 전략을 적용합니다.
브라우저에서 사용되는 공식은 다음과 같습니다.
(currentTime - lastModified) * 0.1
이 캐싱 전략은 서버가 캐시 정책을 명시적으로 정의하지 않은 경우에만 적용됩니다.
자세한 내용은 HTTP Heuristic Caching (Missing Cache-Control and Expires Headers) Explained를 참조하십시오.
기타 고려 사항
- 협상 캐싱은 강한 캐싱과 결합된 경우에만 효과적입니다. 강한 캐싱 없이는 협상 캐싱은 의미가 없습니다.
- 대부분의 웹 서버는 협상 캐싱을 기본적으로 활성화하며 일반적으로
Last-Modified
와ETag
를 동시에 사용합니다.
중요한 시나리오
- 분산 시스템에서는
Last-Modified
타임스탬프가 서버 간에 일관성이 있는지 확인하십시오. 그렇지 않으면 로드 밸런싱으로 인해 캐시 유효성 검사가 일관되지 않아 불필요한 리소스 재페치가 발생할 수 있습니다. - 분산 시스템에서는 서로 다른 서버가 서로 다른
ETag
값을 생성하여 불필요한 캐시 미스가 발생할 수 있으므로ETag
를 비활성화하는 것이 좋습니다.
Leapcell은 백엔드 프로젝트 호스팅을 위한 최고의 선택입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하십시오.
무제한 프로젝트를 무료로 배포
- 사용량에 대해서만 지불하십시오. 요청 없음, 요금 없음.
탁월한 비용 효율성
- 유휴 요금 없이 사용한 만큼만 지불하십시오.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 메트릭 및 로깅.
손쉬운 확장성 및 고성능
- 높은 동시성을 쉽게 처리할 수 있도록 자동 확장됩니다.
- 운영 오버헤드가 없으므로 구축에만 집중하십시오.
설명서에서 자세히 알아보십시오!
X에서 팔로우하십시오: @LeapcellHQ