HTTP 캐시와 재검증: Last-Modified와 ETag

민준·2024년 12월 30일

HTTP Cache 동작 원리

HTTP 캐시 : 네트워크 트래픽을 줄이고, 사용자 경험을 개선하며, 서버 부하를 줄이기 위해 사용되는 중요한 기술

캐시의 핵심 목표 : 데이터를 임시 저장하여 서버 요청을 줄이면서도, 데이터가 너무 오래되지 않도록 유지하는 것, 이를 위해 HTTP 캐시는 재검증 메커니즘을 통해 데이터를 관리

재검증 주기 : 재검증 주기가 너무 길면 데이터가 너무 오래되어 신뢰할수 없게 될 가능성이 있음. 그렇다고 너무 짧으면 서버와 불필요한 통신을 너무 자주 하게 되어 비효율적임.

재검증 방식

HTTP 캐시는 재검증 시 서버와 조건부 요청을 사용하여 데이터의 유효성을 확인 1. Last-Modified(수정일) 2. ETag(고유값)

1. Last-Modified(수정일) 기반 캐싱

Last-Modified는 서버가 리소스의 마지막 수정일을 클라이언트에게 제공하는 방식.
이를 통해 클라이언트는 데이터가 변경되었는지 시간 기반으로 판단

서버가 클라이언트에게 제공

Last-Modified 헤더
서버가 리소스를 전송할 때, 해당 리소스의 마지막 수정 시간을 Last-Modified 헤더에 포함해 응답
클라이언트는 이 값을 저장하여 이후 요청 시 재검증 요청에 활용합니다.

클라이언트가 서버에게 재검증 요청

재검증 요청 헤더
클라이언트는 Last-Modified 값과 함께 두 가지 방식으로 재검증 요청을 보낼수 있음.

1. If-Modified-Since 헤더

  • 목적: 변경된 리소스를 가져와야 할지 확인하기 위한 재검증 요청.

  • 사용 상황: 일반적으로 GET 요청에서 사용하며, 변경된 경우 새로운 데이터를 요청시(바뀌었는지 확인)

  • 서버 응답

    • 200 OK + 새로운 리소스: 리소스가 변경되었음을 알림. 새로운 리소스를 캐시하고 사용.
    • 304 Not Modified: 리소스가 변경되지 않았음을 알림. 캐시에 저장된 리소스를 그대로 사용 가능.
  • 예시
    1. 서버는 Last-Modified 헤더를 응답에 포함시켜 클라이언트에 전달
    2. 클라이언트는 재검증 요청 시 If-Modified-Since 헤더에 이전에 받은 수정일을 포함하여 서버에 전송
    3. 서버는 수정일을 기준으로 리소스 변경 여부를 판단하고 응답
      3.1. 200 OK: 리소스가 변경됨 → 새로운 데이터를 전송.
      3.2. 304 Not Modified: 리소스가 변경되지 않음 → 기존 캐시를 재사용.

2. If-Unmodified-Since 헤더 (POST 요청 등)

  • 목적: 클라이언트의 작업(예: 리소스 수정, 삭제 등)이 리소스가 변경되지 않았다는 전제하에 수행되도록 보장.

  • 사용 상황: 주로 POST, PUT, DELETE 등 서버 상태를 변경하는 요청에서 사용됩니다.
    클라이언트는 "리소스가 변경되지 않았다면 요청을 처리해달라"고 조건부로 요청합니다.

  • 서버 응답

    • 2XX (성공 응답): 리소스가 지정된 시간 이후로 변경되지 않음. 작업 수행.

    • 412 Precondition Failed: 리소스가 변경되었음. 작업 실패.

한계점

  • 정확도가 낮을 수 있음
  • 파일이 수정되지 않았는데도 수정일이 변경될 수 있음.
  • 파일 내용이 원상복구되었더라도 수정일이 업데이트됨.

2. ETag 기반 캐싱

ETag (Entity Tag)는 리소스의 고유 값을 나타내는 해시값으로, 데이터의 무결성을 보장하는 데 사용됩니다. 이는 시간이 아닌 내용 기반으로 데이터 변경 여부를 판단합니다.

서버가 클라이언트에게 제공

ETag 헤더
서버는 ETag 헤더를 응답에 포함시켜 클라이언트에 전달합니다.
클라이언트는 재검증 요청 시 If-None-Match 헤더에 이전에 받은 ETag 값을 포함하여 서버에 전송합니다.

클라이언트가 서버에게 재검증 요청

재검증 요청헤더
클라이언트는 저장된 ETag 값을 사용하여 다음과 같은 요청을 보낼 수 있습니다

1. If-None-Match 헤더 (GET, HEAD 요청) : "서버의 ETag와 다른가요?"

  • 목적 : 클라이언트가 "이전 ETag와 다르면 변경된 것으로 간주"합니다.

  • 사용 상황: GET 요청에서 사용하며, 캐시된 리소스가 유효하지 않을 경우 새로운 데이터를 요청합니다.

  • 서버 응답:

    • 200 OK + 새로운 리소스: 리소스가 변경되었음을 알림. 새로운 리소스를 캐시하고 사용.

    • 304 Not Modified: 리소스가 변경되지 않았음을 알림. 캐시에 저장된 리소스를 그대로 사용 가능.

2. If-Match 헤더 (POST 요청 등) : "서버의 ETag와 동일한가요?"

  • 목적: 클라이언트의 작업(예: 리소스 수정, 삭제 등)이 특정 버전의 리소스를 대상으로 수행되도록 보장.

  • 사용 상황: POST, PUT, DELETE와 같은 요청에서 사용하며, 리소스가 변경되지 않았을 경우 요청을 처리합니다.

  • 서버 응답:

    • 2XX (성공 응답): ETag가 일치하여 작업 수행 가능.

    • 412 Precondition Failed: ETag가 불일치하여 작업 수행 불가.

장점

  • 높은 정확도: 데이터가 실제로 변경되었는지에 대해 신뢰성이 높음.
  • 유연성: 시간 정보에 의존하지 않음.

번외. ETag와 해시의 관계

ETag는 일반적으로 리소스의 내용을 해싱(Hashing)하여 생성됩니다.
이를 통해 리소스의 고유성을 간단하게 표현, 변경 여부를 효율적으로 판단할 수 있음

Hash란? 객체를 함축적으로 표현하는 짧은 고유의 값

해싱의 장점:
고유성: 해시 값은 리소스 상태를 대표하는 고유한 값입니다.

효율성: 리소스 전체를 비교하지 않고도 상태 변화를 빠르게 확인할 수 있습니다.

변경 감지: 리소스의 작은 변경도 다른 해시 값을 생성합니다. 이를 쇄도 효과(Avalanche Effect)라고 합니다.

ETag 활용 예시

상황: 클라이언트가 이미지 파일을 다운로드했는데, 이 파일이 변조되었는지 확인하려고 합니다.

  1. 서버는 파일을 제공할 때, 파일 내용으로 해시를 계산하여 ETag 값을 생성합니다.

    ETag: "xyz789"
  2. 클라이언트는 이 ETag 값을 저장하고, 이후 파일 재다운로드 시 서버에 검증 요청을 보냅니다.

    If-None-Match: "xyz789"
  3. 서버는 현재 파일의 ETag와 클라이언트가 보낸 ETag를 비교하여 응답합니다:

    ETag가 다르면, 200 OK와 함께 새로운 파일을 전송합니다.
    ETag가 같으면, 304 Not Modified로 캐시를 재사용하게 합니다.

ETag와 HMAC

HMAC(Hash-based Message Authentication Code)는 해시와 비슷하지만, 무결성을 보장하기 위해 추가적인 보안 키를 사용합니다.

HMAC 동작 방식

  1. 서버와 클라이언트가 미리 공유한 비밀 키를 사용합니다.

  2. 서버는 리소스를 해싱하여 HMAC 값을 생성하고 이를 클라이언트에 제공합니다.

  3. 클라이언트는 동일한 키로 HMAC 값을 생성하고, 서버가 제공한 값과 비교합니다.

HMAC의 활용

  • 파일 다운로드: 다운로드한 파일이 변조되지 않았는지 확인.

  • Open API: API 응답이 변조되지 않았는지 확인.

0개의 댓글