티스토리 뷰

발생일: 2015.07.01

키워드: 캐시, cache, cache revalidate, max-age, expires, no-cache, pragma, 304 Not Modified, from cache, if-modified-since, cache-control, disable cache

문제:

동일한 도메인에서 동일한 캐시 응답을 갖는 두 개의 리소스 A, B가 있다.

두 리소스 모두 최대한 캐시되도록 설정하고 있는데 (max-age 와 expires 응답 헤더를 큰 값으로 설정),
페이지를 새로고침했을 때(Cmd + R), 다음 요청에서의 캐시 동작이 다르다.

리소스 A는 예상했던 대로, 일단 요청을 보내고 304 Not Modified 를 응답받는다.


헌데, 리소스 B는 로컬에 캐시된 것(from cache)을 사용하고, 요청 자체를 보내지 않는다. 



이상하다.
Cmd + R로 페이지를 새로고침했는데도, 왜 리소스 B는 리소스 갱신 요청조차 보내지 않는 걸까?


해결책:

기본적으로, 웹킷에서 리소스가 캐시되어 있는 경우의 동작은 아래와 같다.

1) 주소창에서 URL을 입력해 페이지에 접근했거나, 북마크 링크 또는 일반 링크를 클릭해 페이지에 접근한 경우
    - 리소스가 이미 캐시되어 있을 경우, 요청 없이 로컬의 값을 사용한다. (from cache)

2) 새로고침 버튼을 클릭하거나, Cmd + R로 새로고침한 경우
    - 리소스가 캐시되어 있더라도 요청을 보낸다.
    - 이 때, 요청에 캐시된 리소스의 수정 시간(응답에서의 `Last-Modified` 헤더 값)을 `If-Modified-Since` 헤더에 담아 보낸다.
    - 정상적으로 캐시되어 있다면, 서버에서 304 Not Modified 를 응답한다.

3) Cmd + Shift + R로 새로고침 한 경우
    - 캐시를 무시하고 모두 새로 요청 보낸다.
    - 이 때, 요청에 `Cache-Control: no-cache`와 `Pragma: no-cache` 헤더를 포함해 보낸다.


단, Cmd + R 이나 Cmd + Shift + R 을 통해 캐시 유효성을 확인하는 대상은, `load` 이벤트가 발생하기 전에 요청된 리소스들이다.
웹킷에서는 `load` 이벤트 이후에 동적으로 추가된 리소스는 페이지의 일부로 판단한지 않으며, 새로고침을 시도하더라도 갱신 대상으로 포함되지 않는다.
(참고로, 캐시에 저장하는 건 요청 시간과 관계 없이 응답 헤더만으로 판단한다)


문제점에서 A와 B는 동일한 도메인에서 동일한 캐시 설정으로 로드한 리소스였지만,
A는 `load` 이벤트 이전에 불러온 리소스였고, B는 이후에 동적으로 로드한 리소스였다.

그래서 B는 새로고침 이후에도 캐시 유효성 확인 없이 로컬에 캐시된 값을 그대로 사용했던 것이다.


리소스 B의 예처럼, 동적으로 추가된 리소스들은 브라우저의 캐시를 비우기 전까지는 갱신할 수 있는 방법이 없다.
개발자 도구에서 `Disable Cache` 옵션을 선택하더라도, 동적으로 로드해 캐시됐던 리소스를 다시 요청하지 않는다면 갱신되지 않는다.




반응형
댓글
공지사항