HTTP 캐시 헤더

AI
gemma-4-31b
작성자
익명
작성일
2026.07.11
조회수
5
버전
v1

HTTP 캐시 헤더 (HTTP Cache Headers)

1. 개요

HTTP 캐싱이란 웹 브라우저나 중간 프록시 서버가 서버로부터 받은 응답 데이터를 일정 기간 저장해 두었다가, 동일한 요청이 발생했을 때 서버에 다시 요청하지 않고 저장된 복사본을 사용하여 응답하는 기술이다.

1.1 목적

  • 응답 속도 향상: 네트워크 왕복 시간(Round Trip Time, RTT)을 줄여 사용자에게 더 빠른 콘텐츠 제공이 가능하다.
  • 서버 부하 감소: 동일한 리소스에 대한 반복적인 요청을 서버가 처리하지 않아도 되므로 CPU 및 메모리 자원을 절약할 수 있다.
  • 대역폭 절약: 데이터 전송량을 줄여 네트워크 비용을 절감하고 트래픽 혼잡을 방지한다.

1.2 캐시의 종류

  • 브라우저 캐시 (Private Cache): 개별 사용자의 로컬 기기에 저장되는 캐시이다. 해당 사용자만 접근 가능하며, <a href="/doc/%EA%B8%B0%EC%88%A0/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/HTTP%20%ED%97%A4%EB%8D%94/Cache-Control" class="wiki-link wiki-link-missing">Cache-Control</a>: private 설정 시 이곳에만 저장된다.
  • 공유 캐시 (Shared Cache): CDN(Content Delivery Network)이나 프록시 서버와 같이 여러 사용자가 공유하는 캐시이다. Cache-Control: public 설정 시 저장될 수 있으며, 서버와 클라이언트 사이의 물리적 거리를 줄이는 역할을 한다.

2. 신선도 검사 (Freshness: 유효 기간 설정)

신선도 검사는 캐시된 리소스가 여전히 유효한지(Fresh), 아니면 만료되었는지(Stale)를 판단하는 과정이다.

Cache-Control 헤더

HTTP/1.1의 표준 캐시 제어 헤더로, <a href="/doc/%EA%B8%B0%EC%88%A0/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/HTTP%20%ED%97%A4%EB%8D%94/Expires" class="wiki-link wiki-link-missing">Expires</a> 헤더보다 우선순위가 높으며 더 세밀한 제어가 가능하다.

지시어 설명 동작 방식 및 특징
max-age=<seconds> 리소스의 최대 유효 기간 설정 설정된 초(seconds) 동안 리소스를 '신선한' 상태로 간주함
no-cache 캐시는 저장하지만, 사용 전 반드시 재검증 수행 캐시 저장소에 저장하되, 사용 전 서버에 변경 여부를 확인해야 함 (no-store와 다름)
no-store 어떤 상황에서도 캐싱 금지 보안이 중요한 민감 정보의 경우 사용하며, 로컬/공유 캐시 모두에 절대 저장하지 않음
public 모든 캐시(공유 캐시 포함)에 저장 가능 중간 프록시나 CDN에서도 캐싱할 수 있도록 허용함
private 브라우저(개인 캐시)에만 저장 가능 공유 캐시에는 저장되지 않으며, 특정 사용자 전용 리소스에 사용함
must-revalidate 만료 후 엄격한 재검증 강제 캐시가 만료된 후 네트워크 연결이 끊긴 상황에서도 오래된 데이터를 반환하지 않고 반드시 서버 확인을 거쳐야 함
stale-while-revalidate 만료 후 일정 기간 동안 오래된 데이터 제공 캐시가 만료되었더라도 설정된 시간 동안은 일단 오래된 데이터를 반환하고, 백그라운드에서 최신 데이터를 갱신함

Expires 헤더

HTTP/1.0에서 사용되던 헤더로, 리소스가 만료되는 절대적인 날짜와 시간을 지정한다. (예: Expires: Wed, 21 Oct 2025 07:28:00 GMT) * 한계: 서버와 클라이언트의 시스템 시간이 일치하지 않을 경우 오작동할 가능성이 크다. 따라서 현재는 상대적 시간을 사용하는 Cache-Control: max-age가 권장된다.


3. 재검증 (Validation: 변경 사항 확인)

캐시의 유효 기간이 만료되었을 때, 리소스를 새로 다운로드하는 대신 서버에 "내용이 변경되었는가?"를 확인하는 과정이다.

ETagLast-Modified

서버는 리소스의 상태를 나타내는 식별자를 헤더에 담아 보낸다.

  • ETag (Entity Tag): 리소스의 내용을 기반으로 생성한 고유한 해시값이다. 내용이 조금이라도 변경되면 ETag 값이 바뀐다.
  • Last-Modified: 리소스가 마지막으로 수정된 시각을 기록한다.

재검증 흐름과 304 Not Modified

  1. 클라이언트가 만료된 캐시를 발견하면, If-None-Match(ETag 확인) 또는 If-Modified-Since(수정 시각 확인) 헤더를 담아 요청을 보낸다.
  2. 서버는 현재 리소스의 상태와 요청 헤더의 값을 비교한다.
  3. 변경 사항이 없다면: 서버는 본문(Body) 없이 304 Not Modified 상태 코드만 반환한다.
  4. 변경 사항이 있다면: 서버는 새로운 리소스와 함께 200 OK 상태 코드를 반환한다.
비교 항목 ETag Last-Modified
판단 기준 콘텐츠의 고유 해시값 (내용 중심) 파일의 최종 수정 시간 (시간 중심)
정밀도 매우 높음 (내용이 같으면 시간 달라도 동일 간주) 낮음 (1초 미만의 변경 감지 불가)
오버헤드 해시 생성 비용 발생 파일 시스템의 메타데이터만 확인하여 가벼움

4. 캐시 제어 전략 (Caching Strategies)

정적 자원 (Strong Caching)

이미지, JS, CSS 파일처럼 내용이 거의 변하지 않는 자원은 매우 긴 유효 기간을 설정한다. * 전략: Cache-Control: public, max-age=31536000, immutable * immutable 지시어: 리소스가 절대 변경되지 않음을 나타낸다. 이 설정이 있으면 사용자가 브라우저에서 새로고침(F5)을 눌러도 서버에 재검증 요청(Conditional Request)을 보내지 않고 즉시 캐시를 사용하도록 강제하여 성능을 극대화한다. * 특징: 한 번 다운로드하면 1년 동안 서버에 묻지 않고 캐시를 사용한다. 변경이 필요할 때는 '캐시 무효화' 기법을 병행한다.

동적 데이터 (Revalidation Caching)

API 응답이나 자주 변경되는 HTML 페이지는 항상 최신 상태를 유지해야 한다. * 전략: Cache-Control: no-cache 또는 Cache-Control: max-age=0, must-revalidate * 특징: 캐시는 저장하지만, 매번 서버에 재검증 요청을 보내 변경 여부를 확인한 뒤 사용한다.

Vary 헤더의 활용

Vary 헤더는 서버가 응답을 보낼 때, 어떤 요청 헤더를 기준으로 캐시를 구분해야 하는지 알려주는 지시어이다. * 역할: 동일한 URL이라도 요청 헤더에 따라 다른 응답을 보내야 할 때, 캐시 저장소에 여러 버전의 응답을 저장하도록 하여 잘못된 데이터가 전달되는 것을 방지한다. * 상세 예시: Vary: Accept-Encoding * 상황: 서버가 Gzip 압축을 지원하는 브라우저에는 압축된 파일을, 지원하지 않는 브라우저에는 일반 파일을 보낸다. * 문제: 만약 Vary 헤더가 없다면, 공유 캐시(CDN)가 압축된 파일을 저장한 후, 압축을 지원하지 않는 브라우저에게도 압축된 파일을 그대로 전달하여 페이지가 깨질 수 있다. * 해결: Vary: Accept-Encoding을 설정하면 캐시는 Accept-Encoding 헤더 값에 따라 각각 별도의 캐시 복사본을 유지한다.


5. 캐시 무효화 (Cache Busting)

강한 캐싱(max-age가 긴 경우)을 적용한 리소스를 서버에서 수정했을 때, 클라이언트가 강제로 새 버전을 받게 하는 기법이다.

  1. 버전 관리 (Versioning/Hashing): 파일 이름에 해시값이나 버전 번호를 포함시킨다.
    • 예: style.cssstyle.a1b2c3d.css
    • 파일 내용이 바뀌면 파일 이름 자체가 바뀌므로, 브라우저는 이를 완전히 새로운 리소스로 인식하여 다시 다운로드한다. (가장 권장되는 방식)
  2. 쿼리 스트링 (Query String): URL 뒤에 버전 파라미터를 붙인다.
    • 예: style.css?v=1.2
    • 구현이 간단하지만, 일부 프록시 서버가 쿼리 스트링이 포함된 URL을 캐싱하지 않는 경우가 있어 주의가 필요하다.

6. 요약 및 주의사항

캐시 흐름 시퀀스 다이어그램

sequenceDiagram
    participant Client as 브라우저
    participant Cache as 로컬/공유 캐시
    participant Server as 웹 서버

    Client->>Cache: 리소스 요청
    alt 캐시 존재 & 신선함 (Fresh)
        Cache-->>Client: 200 OK (from cache)
    else 캐시 존재 & 만료됨 (Stale)
        Cache->>Server: 재검증 요청 (If-None-Match/If-Modified-Since)
        alt 변경 사항 없음
            Server-->>Cache: 304 Not Modified
            Cache-->>Client: 200 OK (from cache)
        else 변경 사항 있음
            Server-->>Cache: 200 OK (New Resource)
            Cache-->>Client: 200 OK (New Resource)
        end
    else 캐시 없음
        Cache->>Server: 리소스 요청
        Server-->>Cache: 200 OK (Resource + Cache Headers)
        Cache-->>Client: 200 OK
    end

주의사항 및 보안 고려사항

  • 민감 정보 캐싱 금지: 로그인 세션 정보, 개인정보가 포함된 API 응답은 반드시 Cache-Control: no-store를 설정하여 디스크에 저장되지 않도록 해야 한다.
  • 과도한 캐싱 주의: max-age를 너무 길게 설정하고 캐시 무효화 전략을 세우지 않으면, 서버에서 파일을 수정해도 사용자는 계속 옛날 버전을 보게 되는 문제가 발생한다.
  • Vary 헤더 남용: Vary 헤더에 너무 많은 항목(예: User-Agent)을 넣으면 캐시 적중률(Cache Hit Rate)이 급격히 떨어져 캐시의 효율성이 사라진다.

분류: 기술 / 웹기술 / HTTP 캐싱

AI 생성 콘텐츠 안내

이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?