# 5주차 HTTP 헤더2

# 목표

스터디를 통해 모든 개발자를 위한 HTTP 웹 기본 지식 (opens new window)을 듣고 요약하며 나누고 싶은 내용을 정리한다.

# 캐시 기본 동작

캐시를 적용하지 않는 경우 데이터가 변경되지 않아도 계속 네트워크를 통해 데이터를 다운 받아야 한다. 하지만 이러한 네트워크 비용은 비싸며 느린 속도를 가지고 있다. 결국 이것은 브라우저의 로딩 속도를 낮추게 되며 사용자는 좋지 못한 경험을 마주하게 된다.

이러한 것들을 보완하기 위해 요청 시 cache-control 헤더를 통해 캐시를 적용할 수 있다. 이러한 캐시를 통해 네트워크를 사용하지 않기 때문에 브라우저의 로딩 속도가 매우 빨리진다.

캐시는 무한히 저장될까?

브라우저는 각자의 캐시 데이터를 적절한 크기로 관리하는 정책을 가지고 있다. 해당 정책에 따라 유효성이 지난 캐시 데이터를 적절히 삭제한다.

캐시 vs 쿠키

쿠키는 서버의 필요에 의해 클라이언트에 저장하는 데이터이다. 캐시는 클라이언트 자체에서 페이지 로드를 효율적으로 하기 위한 데이터이다.

# 캐시 시간 초과

캐시의 유효 기간은 보통 cache-control: max-age=60와 같이 설정한다. 이러한 캐시 유효 시간이 초과하면 서버에게 다시 조회하고 캐시를 갱신한다.

만약 캐시 시간 초과 이후에도 데이터가 변경되지 않은 상황이라고 가정하자. 이같은 상황에서 서버에 다시 데이터를 조회하는 것은 불필요한 낭비일 것이다. 결국 이러한 낭비를 줄이기 위해서는 클라이언트의 캐시 저장소가 가지고 있는 데이터와 서버의 데이터가 같다는 사실을 확인해야 한다.

# 검증 헤더

앞서 언급한 것 처럼 클라이언트의 데이터와 서버의 데이터를 비교하기 위해 요청 시 Last-Modified라는 헤더가 사용된다. 서버의 파일 시스템이 관리하는 파일 정보를 기반으로 최종 수정일을 비교하여 적절한지 검증한다.

또한 검증 헤더와 동시에 캐시 시간이 초과한 경우 요청 시 If-Modified-Since 헤더를 통해 캐시가 가지고 있는 데이터 최종 수정일을 함께 전달할 수 있다. 서버 측은 해당 헤더를 기반으로 비교하여 데이터가 수정되지 않은 경우 304 Not Modified 상태 코드를 내려준다. 서버는 이러한 응답을 기반으로 브라우저 캐시를 최신화하고 캐시 데이터를 적절히 활용한다.

If-Modified-Since를 정리하면 아래와 같다.

  • 데이터 미변경 시 304 Not Modified 응답을 보낸다. 이때 Body는 포함하지 않는다.
  • 데이터 변경 시 200 OK와 함께 변경된 데이터를 함께 전송한다.

하지만 위 방식에는 큰 단점을 가지고 있다. 날짜를 기반으로 진행하기 때문에 서버에서 별도의 캐시 로직을 관리하고 싶은 경우 제약이 생긴다.

# ETag

위와 같은 단점들을 보완하는 수 있는 것이 바로 ETag, If-None-Match 헤더이다. 캐시용 데이터에 임의의 고유한 이름을 명시한다. 만약 데이터가 변경되면 서버 측에서 ETag를 수정하면 클라이언트는 해당 ETag를 비교하여 데이터가 수정됬는지 확인할 수 있다.

여기셔 캐시의 시간이 초과된 경우 If-None-MatchETag를 담아 요청한다.

  • 데이터 미변경 시 304 Not Modified 응답을 보낸다.
  • 데이터 변경 시 200 OK를 보낸다.

이러한 ETag 사용은 캐시 제어 로직을 온전히 서버에서 관리할 수 있게 만들어준다. 클라이언트는 단순히 서버에서 제공 받은 ETag를 기반으로 캐시 검증을 진행하면 된다.

Server to Server에서 캐시관련 헤더 사용하기

서로 약속을 통해 사용할 수는 있다. 웹 브라우저의 경우 이러한 기능들을 모두 구현했기 때문에 편리하게 사용할 수 있다. 하지만 Server to Server의 경우 직접 구현해야 하기 때문에 잘 사용하지 않는다.

# Cache-Control

  • Cache-Control: max-age=60: 캐시 유효 시간을 지정한다. 초 단위로 지정할 수 있다.
  • Cache-Control: no-cache: 데이터는 캐시해도 되지만 항상 origin 서버에 검증하고 사용해야 한다.
  • Cache-Control: no-store: 데이터에 민감한 정보가 존재하기 때문에 저장하면 안된다.

그 밖에도 하위 호환성을 위한 Pragma: no-cache가 존재한다. HTTP 1.0 하위 호환을 위해 존재한다.

# 프록시 캐시

만약 우리가 유튜브에 외국인이 올린 영상을 시청한다고 가정한다. 결국 해당 영상을 보기 위해서는 외국에 있는 origin 서버에 접근해야 한다. 이것은 우리 생각 보다 많은 시간을 소요하며 결국 사용자에게 좋지 않은 경험을 남겨준다.

이것을 보완하기 위해 프록시 캐시 서버를 둘 수 있다. origin 서버에 접근하기 이전 public한 캐시 정보를 가진 프록시 캐시 서버를 거치게 되고 해당 서버에 필요한 데이터가 존재하면 바로 응답을 확인할 수 있다.

  • Cache-Control: pulbic: 앞서 언급한 응답 데이터가 프록시 캐시 서버에 저장해도 된다는 것을 명시한다.
  • Cache-Control: private: 응답이 해당 요청을 진행한 사용자를 위한 것임을 명시한다. 관련 설정을 하지 않으면 기본적으로 private이다.
  • Cache-Control: s-maxage: 프록시 캐시에만 적용하기 위한 max-age이다.

# 캐시 무효화

  • Cache-Control: no-cache: 데이터는 캐시해도 되지만 항상 origin 서버에 검증해야 한다.
  • Cache-Control: no-store: 데이터에 민감한 정보가 담겨 있으므로 저장하면 안된다.
  • Cache-Control: must-revalidate: 캐시가 만료된 후 최초 조회 시 origin 서버에 금증해야 한다. 이때 origin 서버에 접근 실패할 경우 반드시 504 Gateway Timeout 응답을 보내야 한다. 해당 설정을 하지 않을 경우 프록시 서버에 있는 불완전한 데이터를 기반으로 200 OK 응답을 확인할 수 있다.

# 공유하고 싶은 내용

# 캐시는 무한히 저장될까?

브라우저는 각자의 캐시 데이터를 적절한 크기로 관리하는 정책을 가지고 있다. 해당 정책에 따라 유효성이 지난 캐시 데이터를 적절히 삭제한다.

# 캐시 vs 쿠키

쿠키는 서버의 필요에 의해 클라이언트에 저장하는 데이터이다. 캐시는 클라이언트 자체에서 페이지 로드를 효율적으로 하기 위한 데이터이다.

# Server to Server에서 캐시관련 헤더 사용하기

서로 약속을 통해 사용할 수는 있다. 웹 브라우저의 경우 이러한 기능들을 모두 구현했기 때문에 편리하게 사용할 수 있다. 하지만 Server to Server의 경우 직접 구현해야 하기 때문에 잘 사용하지 않는다.

# References

모든 개발자를 위한 HTTP 웹 기본 지식 (opens new window)

#우아한테크코스 #모든 개발자를 위한 HTTP 웹 기본 지식
last updated: 5/28/2022, 7:29:31 PM