CS/Http, Network

[매트 스터디] 5주차 HTTP 헤더2 - 캐시와 조건부 요청

kth990303 2022. 6. 1. 18:27
반응형

우아한테크코스 레벨2 에서 매트가 주관한 스터디로, 인프런 김영한님의 강의 모든 개발자를 위한 HTTP 웹 기본 지식 스터디를 진행중이다. 이 포스팅에서는 스터디에 PR을 날릴 내용과 함께 스터디 시간에 얻어간 내용을 적을 예정이다.


캐시 기본 동작

  • HTTP 헤더의 cache-control에 캐시 유효기간(max-age)를 설정해줌으로써 캐시를 적용할 수 있다.
  • 캐시 가능 시간동안 네트워크를 사용하지 않아도 브라우저 캐시에 존재한 요청은 요청 측의 메모리나 하드디스크에서 꺼내게 해 빠르게 응답해줄 수 있다. (like. Dynamic Programming)
  • 캐시 가능 시간이 초과된 경우, 서버를 통해 다시 데이터를 조회하고 갱신하여 캐시가 없을 때와 동일하게 느려짐.

검증 헤더와 조건부 요청 1

캐시 가능 시간이 초과된 경우, 재요청이 들어오는 경우는 두 가지로 나눌 수 있다.

  1. 서버에서 기존 데이터를 변경하여 응답
    • 데이터가 변경된 경우이므로, 다시 데이터를 조회하고 갱신해야 함.
  2. 서버에서 기존 데이터를 변경하지 않고 응답
    • 데이터가 변경되지 않은 상태이므로 요청 측에 저장돼있는 값을 그대로 꺼내게 하면 됨.
    • 검증 헤더 추가 (Last-Modified)
    • cache가 가지고 있는 최종 수정일과, 서버가 가지고 있는 HTTP 검증 헤더 최종 수정일을 비교하여 수정이 됐는지 여부를 확인해줄 수 있음.

수정되지 않은 경우, HTTP Body를 보내줄 필요 없이 304 Not Modified가 포함된 header만 보내주면 된다.

 

검증 헤더와 조건부 요청 2

Last-Modified, If-Modified-Since 비교 방법은 아래와 같은 문제점이 있다.

  • 초 단위 비교까지만 가능.
  • 데이터를 리셋한 경우에도 Last-Modified, If-Modified-Since가 변함 (A->B->A)
  • 서버에서 별도로 캐시 로직을 관리하고 싶은 경우 문제 발생 (주석, 공백 등 중요한 변경이 없는 경우를 equals하게 보고 싶은 때)

이 문제점을 보완해줄 ETag(Entity Tag) 방법이 추가됐다.

HTTP Header에 ETag를 추가로 보내주면 된다.

  • 캐시용 데이터에 ETag (임의의 고유한 버전 이름) 생성
  • ETag가 같으면 같은 데이터, 다르면 다른 데이터  (Hash 이용)
    • 서버에서 캐시 제어 로직을 관리할 수 있음. (like. equals() & hashCode())

캐시와 조건부 요청 헤더

  • Cache-Control
    • max-age: 캐시 유효 시간 (초 단위)
    • no-cache: 데이터는 캐시해도 되지만, 사용 시마다 origin 서버에 검증할 것.
    • no-store: 민감정보가 있으므로 사용하자마자 삭제할 것.
  • Pregma(캐시 제어), Expires(만료일)은 하위 호환을 위해 사용.
    • Cache-Control: max-age로 Expires 대체 가능.
    • Cache-Control: max-age가 있을 경우 Expires는 무시됨.
  • ETag, Last-Modified 헤더 (검증 헤더)
  • If-Match, If-Modified-Since (조건부 요청 헤더)는 검증 헤더의 값들을 사용.

프록시 캐시

origin 서버가 너무 먼 경우에, 데이터 전송까지 오랜 시간이 걸릴 수 있다. 이는 비교적 거리가 가까운 프록시 캐시 서버를 만드는 걸로 해결할 수 있다. 

출처: 김영한님 인프런 강의자료

따라서 위와 같은 상황에서 public cache data, private cache data가 분리되므로 Cache-Control 헤더에 추가적인 정보를 담을 수 있다.

  • Cache-Control: public
    • public 캐시에 응답 저장 가능
  • Cache-Control: private
    • 특정 private에만 저장 가능한 응답 (기본값)
  • Cache-Control: s-maxage
    • 프록시 캐시에만 적용되는 max-age

캐시 무효화

통신에 장애가 발생할 경우, 캐시 데이터를 어떻게 보여줘야할 지 설정을 해주어야 한다. 또한, 중요한 데이터가 포함될 경우 캐시를 무효화시켜야할 때가 존재한다. Cache-Control 헤더 설정으로 캐시 무효화 방법을 정할 수 있다.

  • Cache-Control: no-cache, Cache-Control: no-store, Pragma: no-cache은 위에서 설명한 내용과 동일.
  • Cache-Control: must-revalidate
    • 캐시 만료 후 최조 조회 시 원 서버에 검증해야 함.
    • 원 서버 접근 실패 시 반드시 504 Gateway Timeout 오류가 발생해야 함.

이 때, no-cache와 must-revalidate의 차이점은 아래와 같다.

  • no-cache: origin 서버에 접근할 수 없는 경우 캐시 서버 설정에 따라 200(오래된 데이터라도 보여주기) or Error 둘 중 하나를 선택해서 보여줄 수 있음. (이 때의 경우 웬만해선 200, 오래된 데이터)
  • must-revalidate: origin 서버에 접근할 수 없는 경우 항상 504 에러 (ex. 돈과 관련된 중요한 데이터)

 

Q. cache를 무효화하고 싶다면 no-store(데이터를 저장하지 않고 사용 후 바로 삭제)만 있으면 되는 것 아닌가?

A. HTTP 스펙을 작성하다보면, no-store만으로 판단하기 애매한 부분들이 존재함. ex) 앞으로가기, 뒤로가기는 cache로 볼 것인가? 이 때는 어떠한 헤더를 보고 판단할 것인가? 그 외 호환성, 프록시 캐시 서버 업체들과의 통신, 버그 등이 존재하므로 no-store만으로는 한계가 있다.


캐시 헤더 부분은 아직 경험이 없기 때문에 크게 와닿진 않고, 이러한 것이 있구나 알아가는 정도로 학습하였다.

나중에 기회가 되면 캐시 설정, redis 사용을 경험해보면서 느껴보고 싶다. 프록시 캐시 서버까지 사용할 기회가 있다면 더 좋을 듯 ㅎㅎ

반응형