HTTP 캐시 헤더

동일한 요청에서 이전 요청과 결과값이 같다면 굳이 재요청을 해야할까? 네트워크 지연시간과 더불어 서버에도 트래픽이 발생하게 될것이다. 이러한 문제를 위해 캐시를 이용한다. 캐시라 함은 익히 알다시피 이전 요청을 저장하여 빠른 시간 내 응답받는 방법이다. 캐시는 하드웨어, 하나의 호스트 내, 서버와 서버간, 클라이언트와 서버 등 대부분의 상호작용 안에서 사용되는 유용한 메커니즘이다. 이 중 HTTP 이용한 클라이언트 서버간 통신에서 사용되는 캐시 제어방법에 대해서 알아보자.


클라이언트에 캐시 허용

클라이언트가 서버에 첫 요청을 보내면 서버는 해당 요청에 대해 캐싱을 허용한다는 의미가 담긴 응답헤더를 보낸다. 대표적으로 Cache-Control, Pragma, Expire 헤더가 존재한다. 3개의 헤더 모두 클라이언트 측에서 캐시를 허용해도 되는지에 대한 내용이 담겨있다. PragmaExpires 헤더는 현재 사용을 권장하지 않으면 대부분 Cache-Control를 사용한다. 만약 PragmaExpires을 본 적 있다면 하위 호환을 위해 사용되는걸 것이다.

Cache-Control 헤더 내에는 구체적인 정보가 들어가는데 다음과 같은 것들이 있다.

  1. max-age
    • max-age=60 과 같은 형식. 값은 초를 의미
    • 해당 시간만큼 캐시를 허용한다는 뜻
  2. no-cache
    • 캐시된 정보를 사용하기 전 항상 본 서버에 요청
    • max-age=0 과 동일한 뜻으로 캐시 저장은 하지만 사용하려고 할때 서버에 재검증 요청
    • 매번 통신하여 최신 정보를 가져오기 위해 사용
  3. no-store
    • 정보 자체를 클라이언트측에 저장하지 말라는 의미
    • 매번 새버로 요청
    • 민감한 정보(개인정보)를 포함할때 사용
  4. public 또는 private
    • 클라이언트와 본서버 사이에 중간서버나 CDN과 같은 서버가 여럿 존재
    • public은 이러한 중간서버가 모두 캐시할 수 있음 의미
    • private은 클라이언트만 캐시 할 수 있음을 의미

만약, max-age 의 시간이 지난 후 해당요청을 하게 된다면 서버에 요청을 보낼 것이다. 이때, 서버에서 해당하는 데이터가 바뀌지 않았다면 어떨까? 다시 같은 데이터를 보낼까? 만약 해당 데이터의 크기가 크다면 그만큼 시간이 오래걸릴 것이다. 이러한 문제를 해결하기 위한 캐시를 검증하는 매커니즘이 존재한다.


Last-Modified 를 이용한 캐시 검증

데이터 요청에 대한 응답으로 Cache-Control 뿐만 아니라 여러가지 헤더를 받는다. 이 중 Last-Modifed 헤더가 존재하는데 이 헤더는 해당 데이터가 마지막으로 수정된 날짜를 의미한다. 응답으로 받은 날짜는 클라이언트 측에 저장되어 이후, 캐시시간이 만료된 후 재요청을 보낼때 사용되어진다.

재요청시, if-modified-since 요청헤더에 저장한 날짜를 넣어 보낸다. 서버에서는 이 값을 확인 후 수정일이 바뀌지 않았다면 304(Not Modified) 상태코드를 보내준다. 이 때, 이 응답은 다음과 같은 특징을 지닌다.

cache-control, Last-Modified 헤더를 다시보내주어 클라이언트측이 저장, 응답 본문이 없음

만약 수정일이 바뀌었다면 200 상태코드와 함께 바뀐 데이터를 보내준다. 이러한 과정을 통해서 수정이 되지 않았을때, 데이터를 보내지 않음으로써 응답에 대한 속도를 높일 수 있다.

하지만 이 방식은 다음과 같은 상황을 제어하지 못한다는 단점이 존재하여 새로운 검증방식이 만들어지게 되었다.

  • 수정되어 날짜가 달라졌지만 데이터 값이 같은 경우(단순 삭제 후 새 데이터 업로드)
  • 서버에서 캐시 로직을 관리하고 싶은 경우(데이터에 큰 영향이 없는 값으로 변경해서 캐시를 유지하고 싶은 경우)


ETag 를 이용한 캐시 검증

ETag 방식의 검증은 응답값만 놓고 본다면 Last-Modifed 방식과 다르지 않다. 하지만 수정날짜 기반이 아닌 데이터의 버전을 기반으로 한다는 점이 다르다.

요청시, 해당 데이터의 버전을 의미하는 ETag를 받고 저장 후 캐시만료 뒤에 If-None-Match 헤더에 넣어 보낸다. 응답은 버전이 바뀌지 않았다면 304 상태코드를, 버전이 바뀌었다면 200 상태코드와 함께 데이터를 다시 보내준다.

카테고리:

업데이트:

댓글남기기