재검증을 통한 캐시 값의 준실시간성 보장
캐시 사용 여부: 실시간성이 중요하다면 성능에 문제가 되더라도 캐시는 사용하지 않는 것이 맞다. -> 실시간을 생각하는데 캐시사용? 재검증 필요
HTTP Cache 동작 원리
캐시는 임시 저장을 위한 전략
준실시간성을 위해서 캐시해 놓은 데이터가 너무 오래된 데이터가 되지 않도록 특정 주기에 따라 재검증을 해주어야한다.
- 재검증: 캐시한 데이터의 원본 주인인 웹 서버가 설정한 특정 주기에 따라 캐시한 데이터가 오래됐는지 검증
- 검증 방법: 조건부 요청 사용 = 재검증 기준이 되는 값을
- 앞으로 조건부 요청 2가지를 볼것임 (1. HTTP Cache 재검증, 2. CORS 요청 가능 여부 확인)
재검증 주기
- 개발자들은 데이터의 갱신 특성에 따라 주기 설정
재검증 기준
- 캐시해놓은 데이터가 얼마나 오래됐는지 여부를 원본 주인인 웹 서버가 판단하기 위한 기준 근거
- 수정일(Last_Modified)
- 낮은 정확도
- 검사방법
- If-Modified-Since: 바뀌었어?
- If-Unmodified-Since: 안바뀌었어?
- 고유값(ETag; Entity Tag, ETag 값으로 가장 많이 쓰이는 것이 Hash-based)
- 높은 정확도
- 검사방법
- If None Match: 바뀌었어?
- If Match: 안 바뀌었어?
- 수정일(Last_Modified)
HTTP Cache 재검증 기준 - Last Modified: 수정일 기반
조건부 요청 헤더: Last Modified
웹 서버가 해당 헤더를 주었다면 Last Modified: 전송 Resource의 마지막 수정일
-> 캐시가 유효한지 여부(=원본이 바뀌었는지 여부)를 시간을 기반으로 판단
🔹재검증 시 캐시 소유자(웹 브라우저): If-Modified-Since(바뀌었어?) (GET, HEAD)
- 캐시 데이터가 바뀌었다면 서버 응답: 200 Resouce Cache + 새 응답(새로운 캐시)
- 캐시 데이터가 그대로이면 서버 응답: 304 Not Changed
🔹재검증 시 캐시 소유자(웹 브라우저): If-Unmodified-Since(안바뀌었어?) (POST 서버 상태 변경 Method)
- 캐시 데이터가 그대로이면 서버 응답: 304 Not Changed
- 캐시 데이터가 바뀌었다면 서버 응답: 412 Precondition Failed (조건부 요청에 대한 False 부정 응답)
HTTP Cache 재검증 기준 - ETag: 고유값(해시) 기반
웹 서버가 해당 헤더를 주었다면 ETag: 전송 Resource의 고유값(해시, ID)
-> 캐시가 유효한지 여부(=원본이 바뀌었는지 여부)를 고유값(해시, ID)를 기반으로 판단한다.
🔹재검증 시 캐시 소유자(웹 브라우저): If-None-Match(달라?)
- 캐시 데이터가 바뀌었다면 서버 응답: 200 Resource Cache + 새 응답(새로운 캐시)
- 캐시 데이터가 그대로이면 서버 응답: 304 Not Changed(GET, HEAD)
- + 412 Precondition Faild (POST 서버 상태 변경 Method)
🔹재검증 시 캐시 소유자(웹 브라우저): If-Match(같아?)
- 캐시 데이터가 그대로이면 서버 응답: 304 Not. Changed
- 캐시 데이터가 바뀌었다면: 412 Precondition Failed (조건부 요청에 대한 False 부정 응답)
[ETag 활용] ash란 무엇이며, 어떻게 활용되는가?
두 객체가 동일한지 검사하기 위해서 두 객체가 가진 모든 필드를 비교해야한다.
필드가 100개라면 100개 모두 비교해야한다는 말... 객체 비교를 간단하게 하기 위해 해시를 사용한다
자바에서 `equals()`의 동작 원리가 hashCode메서드를 기반으로 하므로 객체의 필드 값이 모두 동일하면 `true`를 반환하는 걸 확인할 수 있다.
추가로 hashCode가 기반으로할 필드들을 아래와 같이 지정할 수 있다. (일반적으로 ORM을 위한 entity클래스 정의 시 `EqualsAndHashCode` 기준값을 ID로 설정한다.)
@Getter
@AllArgsConstructor
@EqualsAndHashCode(of = { "id" })
static class User {
private Long id;
private String name;
private int age;
}
[고유성 검증을 위한 Hash활용의 다른 예]: HMAC(Hash-based Message Authentication Code)
HMAC은 다음과 같은 상황에서 사용된다.
- 다운로드 받은 파일이 변조되었는지 알기 위해
- 모든 파일은 해시로 검증 가능하다. (앱 게임이 아니더라도)
- ex) 안드로이드에서 APK파일에 바이러스가 있을 수 있으므로 공식 앱 스토어에 있는 해시값을 사용해서 변조되었는지 확인
- (Open) API를 통해 받은 결과값이 변조되었는지 알기 위해
HMAC을 통해 변조되었는지 여부 판단하는 방법
- 파일을 다운 받거나 혹은 API결과와 동시에 서버가 파일 혹은 API결과로 계산한 Hash값을 함께 받는다.
- 받은 파일과 API결과에 대해 클라이언트와 서버가 미리 공유한 키값으로 Hash값 생성
- 생성된 Hash값과 앞서 받은 Hash값과 비교
- 두 값이 같다면 위조되지 않은 파일 혹은 API결과라고 인지
ref
https://velog.io/@neity16/HTTP-7-캐시와-조건부-요청-Last-Modified-ETag