Chapter1. HTTP
1-1. HTTP의 특징
1-2. HTTP Headers의 종류와 특징
Chapter2. Web Cache
2-1. 캐시 검증 헤더
2-2. 프록시 캐시
Chapter1. HTTP
HTTP 역사
HTTP/1.1, HTTP/2 : TCP 기반 프로토콜
HTTP/3 : UDP 기반 프로토콜

HTTP 특징
- HTTP 헤더와 바디
- HTTP 헤더
- 형식 :
<field-name>:<field-value>
field-name은 대소문자 구분 없다.
- 용도
- HTTP 전송에 필요한 모든 부가정보를 담기위해 사용
- 표준 헤더가 너무 많음
- 필요시 임의 헤더 추가 가능
- HTTP 바디
- 데이터 메세지 본문(Message body)을 통해 표현(Representation) 데이터를 전달
- 데이터를 나르는 부분 :페이로드(Payload)
- 표현은 요청이나 응답에서 전달할 실제 데이터
- 표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공
ex)데이터 유형(html, json), 데이터 길이, 압축 정보 등
앞에 content가 붙어있음.
- 표현 헤더는 요청, 응답 둘 다 사용함
- Content-Type : 표현 데이터의 형식 설명
- 미디어 타입, 문자 인코딩
- Text/html; charset=utf-8
- application/json
- Image/png
- Content-Endocing: 표현 데이터의 압축 방식
- 표현 데이터를 압축하기 위해 사용
- 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
- 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
- gzip, deflate, identity
- Content-Language: 표현 데이터의 자연 언어
- 표현 데이터의 자연 언어를 표현
- ko, en, en-US
- Content-Length : 표현 데이터의 길이
- 바이트 단위
- Transfer-Encoding(전송코딩)을 사용하면 Content-Length를 사용하면 안됨, chunked의 방식으로 사용
- 현재는 Content-Encoding을 사용
HTTP 요청/응답 주요 헤더

요청(Request)에서 사용되는 헤더
- From : 유저 에이전트의 이메일 정보
- Referer: 이전 웹 페이지 주소
- User-Agent: 유저 에이전트 애플리케이션 정보
- Host: 요청한 호스트 정보(도메인)
- Origin: 서버로 POST 요청을 보낼 때, 요청을 시작한 주소를 나타냄
- Authorization: 인증 토큰(e.g. JWT)을 서버로 보낼 때 사용하는 헤더
응답(Response)에서 사용되는 헤더
- Server: 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
- Date: 메시지가 발생한 날짜와 시간
- Location: 페이지 리디렉션
- Allow: 허용 가능한 HTTP 메서드
- Retry-After: 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
-
앞에 Accept가 붙어있다.
-
협상 헤더는 요청 시에만 사용한다.
-
원하는 콘텐츠에 대한 우선순위를 지정할 수 있다.
- Quality Values(q) 값 사용
- 0~1, 클수록 높은 우선순위
- 생략하는 경우, 1
- Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
- ko-KR;q=1 (q생략)
- ko;q=0.9
- en-US;q=0.8
- en:q=0.7
=> 1순위인 한국어를 서버에서는 지원하지 않지만 2순위인 영어를 지원하기에 서버에서는 우선순위에 있는 영어를 독일어보다 클라이언트가 선호하기에 영어로 응답을 주게 된다.
-
Accept: 클라이언트가 선호하는 미디어 타입 전달
-
Accept-Charset: 클라이언트가 선호하는 문자 인코딩
-
Accept-Encoding: 압축 인코딩
-
Accept-Language: 자연 언어
Chapter2. Web Cache
캐시(cache): 컴퓨터 과학에서 데이터나 값을 미리 복사해 놓는 임시 장소.
웹에서도 동일한 요청의 경우 같은 데이터를 다시 다운로드하지 않고 이를 웹 캐시로 저장하여 빠르게 불러올 수 있다
캐시가 없을 경우
- 데이터가 변경되지 않아도 계속 네트워크를 통해 데이터를 다운받아야함
- 인터넷 네트워크는 매우 느리고 비쌈
- 브라우저 로딩 속도 느림
- 느린 사용자 경험 제공
캐시 적용
첫번째 요청
- 캐시의 접근 시간에 비해 원래 데이터를 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용
- 캐시에 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터에 접근할 수 있다.
- 브라우저에 캐시를 저장할 땐 헤더에 cache-control 속성을 통해 캐시가 유효한 시간을 지정할 수 있다.
- 60초로 설정한다면 60초 동안은 해당 캐시 유효
- 응답을 받았을 때 브라우저 캐시에 해당 응답 결과를 저장하며 이는 60초간 유효하다
두번째 요청 - 캐시 시간이 초과했을 경우
- 두 번째 요청에선 캐시를 우선 조회하게 됨
- 캐시가 존재하고 아직 60초가 지나지 않아 유효한 캐시라면 해당 캐시에서 데이터를 가져온다.
- 만약 시간을 초과했을 경우
- 다시 서버에 요청을 하고 60초간 유효한 데이터를 응답받음
- 이때 다시 네트워크 다운로드가 발생하게 된다.
- 응답 결과를 브라우저가 렌더링 하면 브라우저 캐시는 기존 캐시를 지우고 새 캐시로 데이터를 업데이트한다.
💡 유효시간이 초과하면 다시 요청을 보내 새로운 데이터로 캐시를 업데이트
캐시 유효시간이 지났지만 변경이 없기 때문에 해당 데이터를 써도 되는 상황이라면 ...
📌 캐시 검증 헤더
검증 헤더와 조건부 요청
첫번째 요청
- 검증 헤더 Last Modified를 이용해 캐시의 수정시간을 알 수 있다.
- Last Modified는 데이터가 마지막으로 수정된 시간 정보를 헤더에 포함한다
- 이로 인해 응답 결과를 캐시에 저장할 때 데이터 최종 수정일도 저장된다.
두번째 요청
- 캐시 유효시간이 초과되더라도 If-Modified-Since 헤더를 이용해 조건부 요청을 할 수 있음
- 데이터가 수정되었는지 검증
- 수정되지 않았다면 바디를 제외한 HTTP 헤더만 전송
- 브라우저 캐시에서 응답 결과를 재사용, 헤더 메타데이터 또한 갱신
- 브라우저는 캐시에서 조회한 데이터를 렌더링
Last-Modified와 If-Modified-Since 정리
- 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면
- 304 Not Modified + 헤더 메타데이터만 응답(바디X)
- 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타데이터를 갱신
- 클라이언트는 캐시에 저장되어 있는 데이터 재활용
- 결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드
- 매우 실용적인 해결책
Last-Modified와 If-Modified-Since 단점
- 1초 미만(0.x초)단위로 캐시 조정 불가능
- 날짜 기반의 로직 사용
- 데이터를 수정해서 날짜가 다르지만 같은 데이터를 수정해서 데이터 결과가 똑같은 경우
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
e.g. 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우
ETag(Entity Tag)와 If-None-Match 검증 헤더
Last-Modified와 If-Modified-Since보다 간단한 방식
- 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠
e.g. ETag: "v1.1", ETag: "61df5ee64dd7261cd4dc6c62c7d957a1"
- 데이터가 변경되면 이 이름을 바꿔서 변경함 (Hash 재생성)
e.g. ETag: "845eed07c5887cf" -> ETag: "3ac587fa90544fdc"
- 단순하게 ETag만 보내서 같으면 유지, 다르면 다시 받는 방식
첫번째 요청
서버에서 헤더에 ETag를 작성해 응답
-> 브라우저 렌더링
-> 클라이언트 캐시에서 해당 ETag 값을 저장
두번째 요청
캐시 시간이 초과돼서 재요청 해야한다면 ETag 값을 검증하는 If-None-Match를 요청헤더에 작성해서 보냄
- 데이터가 수정되었는지 검증
- 수정되지 않았다면 바디를 제외한 HTTP 헤더만 전송
- 브라우저 캐시에서 응답 결과를 재사용, 헤더 메타데이터 또한 갱신
- 브라우저는 캐시에서 조회한 데이터를 렌더링
ETag와 If-None-Match 정리
- 단순하게 ETag만 보내서 같으면 유지, 다르면 다시 받는 방식
- 캐시 제어 로직을 서버에서 완전히 관리
- 클라이언트는 단순히 이 값을 서버에 제공(클라이언트는 캐시 매커니즘을 모름)
e.g. 서버는 베타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지 -> 애플리케이션 배포 주기에 맞춰 ETag 갱신
Cache-Control
캐시 지시어(directives)
- Cache-Control: max-age
: 캐시 유효 시간. 초 단위
- Cache-Control: no-cache
: 데이터는 캐시해도 되지만, 항상 원(Origin) 서버에 검증하고 사용
- Cache-Control: no-store
: 데이터에 민감한 정보가 있으므로 저장하면 안됨. 메모리에서 사용하고 최대한 빨리 삭제
Expires
캐시 만료일 지정(하위 호환)
- Expires: Mon, 01 Jan 1999 00:00:00 GMT
- 캐시 만료일을 정확한 날짜로 지정
- HTTP 1.0부터 사용
- 지금은 더 유연한 Cache-Control: max-age 권장
- Cache-Control: max-age와 함께 사용하면 Expires는 무시됨
검증 헤더와 조건부 요청 헤더
정리
- 검증 헤더(Validator)
- ETag: "v1.0", ETag: "845eed07c5887cf"
- Last-Modified: Wed, 26 Dec 2022 12:01:11 GMT
- 조건부 요청 헤더
- If-Match, If-None-Match: ETag 값 사용
- If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용
📌 프록시 캐시
프록시(Proxy) : 클라이언트와 서버 사이에 대리로 통신을 수행하는 것
프록시 서버 : 그 중계 기능을 하는 서버
클라이언트, 혹은 반대로는 서버가 다른 네트워크에 간접적으로 접속할 수 있기 때문에, 보안, 캐싱을 통한 성능, 트래픽 분산 등의 장점을 가진다.
private 캐시: 클라이언트에서 사용하고 저장하는 캐시
public 캐시 : 프록시 캐시 서버의 캐시
Cache-Control
캐시 지시어(directives) - 기타
- Cache-Control : public
- Cache-Control: private
- 응답이 해당 사용자만을 위한 것. private 캐시에 저장해야 함 (기본값)
- Cache-Control: s-maxage
- Age: 60 (HTTP 헤더)
- 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)
캐시 무효화 :웹 브라우저가 임의로 캐싱을 할 때 무효화할 수 있는 헤더
- Cache-Control : no-cache
- 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용
- Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨
(메모리에서 사용하고 최대한 빨리 삭제)
- Cache-Control: must-revalidate
- 캐시 만료 후 최초 조회 시 원 서버에 검증해야함
- 원 서버 접근 실패 시 반드시 오류가 발생해야함 - 504(Gateway Timeout)
- must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
- Pragma: no-cache
캐시 무효화를 확실하게 해야 하는 경우 Pragma와 같은 하위 호환까지 포함하여 아래와 같이 적용해야 함
- Cache-Control: no-cache, no-store, must-revalidate
- Pragma: no-cache
no-cache vs must-revalidate
모두 원 서버에 검증해야 하지만 그에 대한 응답이 다르다.
no-cache
- 캐시 서버 요청
- 프록시 캐시 서버에 도착하면 no-cache인 경우 원 서버에 요청을 하게 됨
- 그리고 원 서버에서 검증 후 304 응답을 하게 됨
만약 프록시 캐시 서버와 원 서버 간 네트워크 연결이 단절되어 접근이 불가능하다면 200OK를 응답한다. (오류가 아닌 오래된 데이터를 보여줌)
must-revalidate
원 서버에 접근이 불가할 때 504 Gateway Timeout 오류를 보냄