HTTP

HTTP 완벽 가이드 스터디 (7)

kchabin 2025. 3. 6. 12:06

웹 캐시 : 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치

캐시가 주는 혜택

  • 불필요한 데이터 전송을 줄여서, 네트워크 요금으로 인한 비용을 줄여줌
  • 네트워크 병목을 줄여줌. 대역폭을 늘리지 않고도 페이지를 빨리 불러올 수 있게 됨
  • 원 서버에 대한 요청 감소, 서버 부하를 줄일 수 있으며 더 빨리 응답할 수 있게 됨
  • 거리로 인한 지연 감소

복수의 클라이언트가 한 개의 원 서버에 같은 콘텐츠 중복 요청.

  • 같은 바이트 반복 이동 → 불필요한 데이터 전송
  • 값비싼 네트워크 대역폭을 잡아먹음 / 전송 느려짐 / 웹 서버 부하 발생

캐시 이용 : 첫 번째 응답을 캐시에 저장 → 캐시된 사본을 이어지는 똑같은 요청에 대해 응답으로 사용

대역폭 병목

캐시는 네트워크 병목을 줄여준다.

  • 원격 서버보다 로컬 네트워크 클라이언트에 더 넓은 대역폭을 제공한다.
  • WAN 접속 → 그 경로에 있는 가장 느린 네트워크의 속도

Flash Crowds

캐싱은 갑작스런 요청 쇄도에 대응하기 위해 중요하다.

  • 웹 서버에 과부하 발생

거리로 인한 지연

대역폭이 문제가 되지 않더라도, 거리가 문제 될 수 있음.

  • 네트워크 라우터에서 트래픽 지연
  • 빛 속도 그 자체가 유의미한 지연 유발.
  • 병렬이면서 keep-alive 커넥션이라도 빛의 속도는 뚜렷한 지연을 발생시킴
보스턴 ~ 샌프란시스코 거리 = 4,400km
빛의 속도 = 300,000km/s

가정 : 20 개의 작은 이미지를 포함하고 있는 웹 페이지. 이미지는 전부 샌프란시스코에 있는 한 서버에 있음. 
왕복 30m/s.

동시에 네 개의 커넥션을 열고(병렬), 유지(keep-alive) -> 빛의 속도로 인한 지연은 거의 1/4초(240밀리초)

서버가 도쿄에 위치할 경우(10,800km)
지연이 600ms로 커짐

적중과 부적중

캐시 적중

요청에 대응하는 사본이 있는 경우.

  • cache hit

캐시 부적중

대응하는 사본이 없다면 요청은 원 서버로 전달됨

  • cache miss

캐시된 객체가 최신인지 검사해야 함.

  • If-Modified-Since 헤더와 같은 도구로 신선도 검사를 하고, 최신 여부에 따라 달라짐
  • 재검사 적중은 느린 적중이라고도 함.

  • 부적중 : 서버 객체가 캐시된 사본과 다르다면, 서버는 콘텐츠 전체와 함께 평범한 HTTP 200 OK 응답을 클라이언트에게 보냄

캐시 삭제

원 서버 객체 삭제 → 404 Not Found 응답, 캐시는 사본을 삭제

캐시 적중률

캐시가 요청을 처리하는 비율

  • 캐시가 얼마나 큰지
  • 캐시 사용자들의 관심사가 얼마나 비슷한지
  • 캐시된 데이터가 얼마나 자주 변경되거나 개인화되는지
  • 캐시가 어떻게 설정되어 있는지

문서 적중률과 바이트 적중률

문서 적중률 바이트 적중률
얼마나 많은 웹 트랜잭션을 외부로 내보내지 않았는지 보여줌 얼마나 많은 바이트가 인터넷으로 나가지 않았는지 보여줌 → 캐시를 통해 제공된 모든 바이트의 비율 표현
트랜잭션(고정된 소요 시간 포함), 커넥션을 맺는 등 종종 길어질 수 있음. → 개선 시 전체 대기시간(지연) 감소 대역폭 절약 최적화
  • 모든 문서의 크기가 같지 않음 → 적게 접근되는 크기가 큰 객체는 전체 트래픽에는 더 크게 기여함.
    • 이런 이유로 어떤 사람들은 바이트 단위 적중률 측정값을 더 선호함.

적중과 부적중의 구별

HTTP는 클라이언트에게 응답이 캐시 적중이었는지 원 서버 접근이었는지 말해줄 방법 제공하지 않음

  • 모두 응답 코드는 200 OK
  • Via 헤더에 추가 정보를 붙이는 상용 프락시 캐시
  • Date 헤더 : 응답의 Date 헤더 값을 현재 시각과 비교함. 응답의 생성일이 더 오래되었다면 클라이언트는 응답이 캐시된 것임을 알아낼 수 있음
  • Age 헤더 : 응답이 얼마나 오래되었는지 말해줌

캐시 토폴로지

개인 캐시 / 공용 캐시

개인 전용 캐시들이 서버에 제각각 접근해서 객체를 가져온다.

  • 새롭고 ‘따끈따끈한’ 문서 → 개인 전용 캐시에 아직 들어있지 않은 문서
  • 같은 문서를 네트워크를 거쳐 여러 번 가져옴

공유된 캐시는 트래픽을 줄일 수 있다

자주 찾는 객체를 한 번만 가져와 모든 요청에 대해 공유된 사본을 제공함으로써 네트워크 트래픽을 줄임.

 

캐시 계층

작은 캐시에서 부적중이 발생했을 때, 더 큰 부모 캐시가 ‘걸러 남겨진’ 트래픽을 처리하자 → 캐시 계층

  • 클라이언트 주위에는 작고 저렴한 캐시
  • 계층 상단에는 많은 사용자들이 공유하는 문서를 유지하기 위한 크고 강력한 캐시

 

프락시 연쇄가 길어질수록 각 중간 프락시는 현저한 성능 저하가 발생함.

  • 실제로 두 개 or 세 개의 프락시만 거치도록 스스로 제한.(책 기준)

캐시망

동적인 캐시 커뮤니케이션 결정

콘텐츠 라우팅

  • URL에 근거하여, 부모 캐시와 원 서버 중 하나를 동적으로 선택한다.
  • URL에 근거하여 특정 부모 캐시를 동적으로 선택한다.
  • 부모 캐시에게 가기 전에, 캐시된 사본을 로컬에서 찾아본다.
  • 다른 캐시들이 그들의 캐시된 콘텐츠에 부분적으로 접근할 수 있도록 허용하되, 그들의 캐시를 통한 Internet Transit은 허용하지 않는다. → 트래픽이 다른 네트워크로 건너가는 것을 금지함

형제 캐시

선택적인 피어링을 지원하는 캐시

  • HTTP는 형제 캐시를 지원하지 않음
    • ICP(인터넷 캐시 프로토콜)이나 HTCP(하이퍼텍스트 캐시 프로토콜)로 HTTP를 확장함.

캐시 처리 단계

  1. 요청 받기
    1. 고성능 캐시는 여러 개의 들어오는 커넥션들로부터 데이터를 동시에 읽어들이고 메시지 전체가 도착하기 전에 트랜잭션 처리를 시작함.
  2. 파싱
    • 요청 메시지 파싱
    • 헤더 부분을 조작하기 쉬운 자료구조에 넣음.
      • 캐싱 소프트웨어가 헤더 필드를 처리하고 조작하기 쉽게 만들어줌
  3. 검색
  4. 신선도 검사
    • 신선도 한계를 넘음 → ‘신선하지 않은 것’
    • 신선하지 않은 문서는 제공하기 전 원 서버와 재검사
  5. 응답 생성
  6. 발송
  7. 로깅 - 선택적으로 트랜잭션에 대해 서술한 로그를 남김
    • Squid log format
    • Netscape extended common log format
    → 많이 쓰이는 로그 포맷. 대부분의 캐시는 커스텀 로그 파일을 허용함.

 

문서 만료

  • Cache-Control
  • Expires

캐시된 문서가 만료되면, 캐시는 반드시 서버와 문서에 변경된 것이 있는지 검사해야 하며, 만약 그렇다면 신선한 사본을 얻어와야 함.(새 유효기간과 함께)

 

헤더 설명
Cache-Control: max-age max-age : 문서의 최대 나이 정의
문서가 처음 생성된 이후~제공하기엔 더 이상 신선하지 않다고 간주될 때까지 경과한 시간의 합법적인 최댓값(초 단위)
Cache-Control: max-age=48400
Expires 절대 유효기간 명시. 유효기간이 경과됐다면, 그 문서는 더 이상 신선하지 않다.
Expires: Fri, 05 Jul 2002, 05:00:00 GMT

서버 재검사

원 서버에게 문서가 변경되었는지의 여부를 물어볼 필요가 있음.

  • 재검사 결과 콘텐츠가 변경되었다면, 캐시는 그 문서의 새로운 사본을 가져와 오래된 데이터 대신 저장한 뒤 클라이언트에게도 보내준다.
  • 콘텐츠 변경 x → 새 만료일을 포함한 새 헤더들 가져옴 → 캐시 안의 헤더들을 갱신함.

문서의 신선도를 매 요청마다 검증할 필요 없이 문서가 만료되었을 때 한 번만 서버를 재검사하면 됨.

  • 신선하지 않은 콘텐츠 제공 x
  • 서버 트래픽 절약
  • 사용자 응답 시간 개선

HTTP는 캐시가 다음 중 하나를 리턴하도록 요구

  • ‘충분히 신선한’ 캐시된 사본
  • 원 서버와 재검사 된 충분히 신선하다고 확신하는 캐시된 사본
  • 에러 메시지(재검사해야 하는 원 서버가 다운된 경우)
  • 경고 메시지가 부착된 캐시된 사본(부정확하다면)

조건부 메서드

  • 조건부 GET → 조건부 헤더
  • 최근 변경 일시 검사 or 엔티티 태그 검사

If-Modified-Since

특정 날짜 이후로 변경된 경우에만 요청한 본문을 보내달라고 함

  • 변경 o : 새 문서가 새로운 만료 날짜와 그 외 다른 정보들이 담긴 헤더들과 함께 캐시에게 반환됨.
  • 변경 x : 304 Not Modified. 본문x(효율)
    • 헤더들 중에서도 갱신이 필요한 것만 보내줌 - 새 만료 날짜
    • 오래된 서버는 ims 헤더를 인식하지 못하고 GET 요청으로 인식함.
      • 변경되지 않은 문서 데이터를 불필요하게 전송 → 덜 효율적

서버 응답 헤더의 Last-Modified 헤더와 함께 동작함.

  • 원 서버는 제공하는 문서에 최근 변경 일시를 붙임.
  • 캐시된 사본이 마지막으로 수정된 날짜가 담긴 IMS 헤더를 포함함.

몇몇 웹서버는 실제 날짜 비교로 구현하지 않는다.

  • “이 날짜 이후로 변경되었다면” (x)
  • “정확히 이 날짜에 마지막 변경이 일어난 것이 아니라면” (o)

If-None-Match

엔티티 태그 검사 방식

  • 만약 엔티티 태그가 변경되었다면, 서버는 200 OK 응답으로 새 콘텐츠를 새 ETag와 함께 반환함.
If-None-Match: "v2.4", "v2.5", "v2.6"
If-None-Match: "foobar", "A32425", "Profiles in Courage"
  • 캐시가 객체에 대한 여러 개의 사본을 갖고 있는 경우, 그 사실을 서버에게 알리기 위해 하나의 If-None-Match 에 여러 개의 엔티티 태그를 포함할 수 있다.

 

HTTP/1.1 은 약한 검사기(weak validator)

약한 검사기 어느 정도 콘텐츠 변경 허용, 중요한 의미가 변경되면 함께 변경됨. W/ 접두사를 붙여서 표현

강한 검사기 콘텐츠가 바뀔때마다 바뀜.
약한 엔티티 태그 대응하는 엔티티에 유의미한 변경이 있을 때 변경
강한 엔티티 태그 대응하는 엔티티 값이 어떻게 바뀌든 매번 반드시 같이 바뀌어야 함.
  • 엔티티 태그 값은 서로 다른 두 엔티티에 대해 재활용 불가

ETag, Last-Modified 일시 사용 시기

  • 서버가 ETag 반환 → 반드시 ETag 검사기 사용
  • 서버가 Last-Modified 반환 → 클라이언트 IMS 검사

클라이언트는 1.0, 1.1 캐시 모두 적절히 응답할 수 있도록 두 가지의 재검사 정책을 모두 사용해야 한다.

HTTP/1.1 캐시

  • HTTP/1.1 원 서버는 실현 불가능하지만 않다면 ETag 검사기를 보내야 함.
  • 이점이 있다면 강 대신 약한 태그 검사기 (+ Last-Modified 일시)
  • IMS, ETag 헤더를 모두 받았다면, 모든 조건부 헤더 필드의 조건에 부합하지 않는 한 304 응답 반환 불가

캐시 제어

헤더

서버가 캐싱 규칙 설정을 위한 헤더를 응답에 첨부할 수 있음.

Cache-Control: no-store 캐시가 그 응답의 사본을 만드는 것을 금지함

Cache-Control: no-cache 재검사 없이 캐시에서 클라이언트에 제공 금지
Cache-Control: must-revalidate 신선하지 않은 객체를 반드시 원 서버와의 최초의 재검사 없이는 제공해서는 안 됨.
  • 원 서버 접근 불가 : 504 Gateway Timeout error 반환
  • 캐시는 성능 개선을 위해 만료된 객체를 제공할 수 있음. | | Cache-Control: max-age | 문서가 서버로부터 온 이후 흐른 시간. (공용 캐시 s-maxage 사용) maximum-aging=0 : 캐시 무효화, 실시간 업데이트, 성능 저하(네트워크 부하, 페이지 로딩 속도) | | Expires | 많은 서버가 동기화되어 있지 않거나 부정확한 시계를 갖고 있음 → 절대 시각 대시 경과된 시간으로 표현.
  • 신선도 수명 근사값 = 만료일 - 생성일
  • Expires: 0 : 문서를 항상 만료되도록 → 문법 위반, 수용 o, 생성 x | | 휴리스틱 | 아무런 만료 정보도 주지 않고, 캐시가 스스로 결정
  • 최대 나이를 계산 |

LM 인자 알고리즘

<aside> 💡

휴리스틱 만료 : 서버가 명시적으로 캐시 제어 헤더를 제공하지 않는 경우 사용

</aside>

  • 문서의 마지막 변경 일시가 매우 예전 → 잘 변경되지 않는 안정적인 문서. 캐시에 더 오래 보관해도 안전함
  • 문서의 마지막 변경 일시가 최근 → 자주 변경, 서버와 재검사하기 전까지 짧은 기간 동안만 캐싱.
$마지막_수정_이후로_경과한_시간 = max(0, $서버의_Date - $서버의_Last_Modified);
$서버_신선도_한계 = int($마지막_수정_이후로_경과한_시간 * $lm_인자);

예: LM 인자 = 0.1

  • 리소스가 10일 전에 마지막으로 수정되었다면, 브라우저는 이 리소스를 추가로 1일(10%) 동안 캐시에 저장하고 사용 가능하다고 판단할 수 있음.

아파치 HTTP 헤더 제어

mod_headers

  • 모든 HTTP 응답 헤더를 제어하는 더 범용적인 도구.
  • 캐시 설정 외에도 보안 및 쿠키 정책 등 다양한 헤더를 추가하거나 수정할 수 있다.
<IfModule mod_headers.c>
    **Header set Cache-Control "max-age=3600, must-revalidate"**
    Header unset X-Powered-By <!-- 서버정보 등 기본적으로 추가된 헤더 제거-->
    Header set X-Frame-Options "DENY" <!-- 보안 헤더 : 클릭재킹 공격 방지 -->
</IfModule>

<Files *.html>
	Header set **Cache-control** no-cache
</Files>

mod_expires : 캐시 만료 헤더를 설정하는 데 사용됨.

Apache 설정 파일 (httpd.conf)이나 .htaccess 파일에 설정 가능

<IfModule mod_expires.c>
    ExpiresActive On
    **Expires**Default "access plus 1 month"
    ExpiresByType text/html "access plus 1 day"
    ExpiresByType image/jpeg "access plus 1 week"
</IfModule>
  • html 파일은 1일 동안, jpeg 이미지는 1주일

mod_cern_meta

  • 메타 파일을 통한 헤더 설정 : 웹 문서 자체와는 별도의 파일로 응답 헤더를 관리함.
    • 서버가 특정 리소스에 접근할 때, 연결된 메타 파일을 확인해서 추가적인 HTTP 헤더를 응답에 포함시킴.
  • 특정 리소스에 대해 개별적인 헤더 설정이 필요할 때 유용함.
  • /var/www/html/index.html이라는 파일이 있다면, 그 파일과 관련된 메타 파일은 /var/www/html/index.html**.meta**로 저장

HTTP-EQUIV 태그

  • HTML 2.0
<meta http-equiv="속성" content="값">

<meta http-equiv="Cache-Control" content="no-cache">

<!--구형 캐시 제어용-->
<meta http-equiv="**Pragma**" content="no-cache">

<meta http-equiv="Expires" content="Wed, 21 Oct 2024 07:28:00 GMT">
  • 클라이언트 측(브라우저)에서만 적용됨. → 서버에서 응답 헤더를 설정하는 것만큼 강력하지 않음.
  • 최신 웹 환경에서는 서버 설정
  • 이 기능을 지원하는 웹 서버나 프록시는 거의 없음.
    • 브라우저와 프락시 캐시는 다른 캐시 제어 규칙을 적용 → 캐시 만료 동작 혼란
  • 서버의 부하를 가중시킴, 설정값이 정적임, HTML 이외 타입 지원 x

나이 계산

HTTP 나이 계산

  • 캐시는 그 문서가 로컬 캐시에 얼마나 오래 머물렀는지 알 수 있음 → 캐시 = 로컬 캐시?
$나이 = $문서가_우리의_캐시에_도착했을_때의_나이 + $사본이_우리의_캐시에_머무른시간;

클록 스큐(clock skew)

두 컴퓨터의 시계 설정 차이로 인한 문제

$겉보기_나이 = **max(0, $응답을받은시각 - $Date헤더값)**;
$문서가_우리의_캐시에_도착했을_때의_나이 = $겉보기_나이;
  • 겉보기 나이는 클록 스큐때문에 부정확한 음수가 되기도 함.
    • 음수 → 0으로 만들어야 함.

점층적 나이 계산

http/1.1

‘동기화된 시계라는 것이 존재하지 않는다’ 우회 → Age 헤더에 프록시를 지날때마다 상대적인 나이를 누적해서 더하도록 함.

  • 서버 간의 시간 비교, 종단 간의 시간 비교를 필요로 하지 않음.
  • HTTP/1.1 장치가 아니면 Age 헤더를 인식하지 못하고 삭제
  • Date 기반 나이보다 보수적인 것(max) 선택 → Date 값 or 나이 계산 값 = 실제보다 작을 수 있음.
$보정된_겉보기_나이 = max($겉보기_나이, $Age_헤더값);
$문서가_우리의_캐시에_도착했을_때의_나이 = $보정된_겉보기_나이;

네트워크 지연에 대한 보상

Date 헤더는 언제 문서가 원 서버를 떠났는지 말해주지만, 캐시로 옮겨가는 도중에 얼마나 시간을 소비했는지는 말해주지 않음.

  • 긴 연쇄 → 상당한 네트워크 지연
  • Date 헤더는 부모 캐시가 아닌 원 서버의 날짜를 반영함
$응답_지연_추정값 = ($응답을_받은_시각 - $요청을_보낸_시각);
**$문서가_우리의_캐시에_도착했을_때의_나이** = $보정된_겉보기_나이 + $응답_지연_추정값;

완전한 나이 계산 알고리즘

$나이 = $보정된_겉보기_나이 + $응답_지연_추정값 + $사본이_우리의_캐시에_머무른시간;

신선도 서버 알고리즘

 

클라이언트가 서버 신선도 한계를 가져와서 클라이언트의 제약에 맞게 수정한다.

 

 

캐시 무력화

캐시는 원 서버가 실제 접근 횟수를 알 수 없게 숨길 수 있음.

  • 접근 횟수를 캐시가 흡수

광고 회사 → 캐시가 광고 시청 수를 가로채지 못하도록

  • 모든 접근에 대해 원 서버와 재검사
    • 본문은 없지만, 트랜잭션을 느리게 만듦.

로그 마이그레이션

  • 캐시 적중 로그를 콘텐츠 제공자에게 제공

단점

  • 적중 로그는 크기 때문에 옮기기 어려움
  • 개별 콘텐츠 제공자별로 분리될 수 있도록 표준화, 조직화 X
  • 인증과 프라이버시 이슈

적중 측정과 사용량 제한

Meter 헤더 : 서버가 캐시된 문서가 적중한 횟수의 정기적인 업데이트를 캐시로부터 받음.

  • 사용량 제한 : 문서를 제공할 수 있는 횟수, 소모할 수 있는 처리시간 등 제어

'HTTP' 카테고리의 다른 글

HTTP 완벽 가이드 스터디 (9)  (0) 2025.03.10
HTTP 완벽 가이드 스터디 (8)  (0) 2025.03.06
HTTP 완벽 가이드 스터디 (6)  (0) 2024.10.08
HTTP 완벽 가이드 스터디 (5)  (0) 2024.10.03
HTTP 완벽 가이드 (4)  (0) 2024.10.02