[HTTP] 헤더 / 쿠키와 캐시
헤더에는 HTTP 전송에 필요한 모든 부가정보가 들어가 있다. (메세지 바디 내용, 크기, 인증, 요청 클라이언트, 서버 정보..)
표준 헤더는 수없이 많고, 임의로 헤더를 추가할 수도 있다.
헤더는 크게 4가지로 분류할 수 있다. (실제로는 더 복잡함)
1. General 헤더 : 메세지 전체에 적용되는 정보
2. Request 헤더 : 요청 정보
3. Response 헤더 : 응답 정보
4. Representation 헤더 : 과거 엔티티 헤더에서 이름이 바뀜. 메세지 바디를 통해 표현 데이터 전달
Representation 헤더
Content-Type : 표현 데이터의 형식을 알려준다. (html, xml, json 등등.. 메세지 바디에 들어가는 내용)
Content-Encoding : 표현 데이터의 압축 방식을 알려준다. (데이터를 전달하는 쪽에서 압축 후 인코딩 헤더 추가)
Content-Language : 표현 데이터의 자연언어를 나타낸다.
Content-Length : 표현 데이터의 길이를 나타낸다. (Transfer-Encoding 사용 시 해당 헤더 사용 불가능.)
협상 헤더 (Content Negotiation)
클라이언트가 선호하는 표현을 요청한다.
Accept : 클라이언트가 선호하는 미디어 타입 전달
Accept-Charset : 클라이언트가 선호하는 문자 인코딩
Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
Accept-Language : 클라이언트가 선호하는 자연언어
협상 헤더는 요청 시 사용한다.
협상 헤더로 우선시되는 언어를 먼저 받는다. (서버가 지원하지 않으면 못 줌)
Quality Values를 사용해 언어별 우선순위를 설정할 수 있다.
기본값은 1으로, 높을수록 우선순위가 높다. (0 ~ 1)
여러 가지 언어를 지원하는 서버에서 우선순위가 가장 높은 언어를 반환받을 수 있도록 하자.
더 구체적으로 설정할수록 우선순위가 높다.
HTTP 의 전송 방식은 네 가지로 구분할 수 있다.
단순 전송
한 번에 요청하고 메세지 바디를 통해 쭉 받는다.
압축 전송
Content-Encoding을 추가해 단순 전송에서 압축한 후 받는다.
분할 전송
하나씩 보낸다.
0 \r\n 은 마지막을 의미함.
이 경우 Content-Length를 넣으면 안된다. (예상할 수 없음)
범위 전송
범위를 지정해서 요청함.
몇 가지 헤더들에 대해 알아보자.
From : 유저 에이전트의 이메일 정보. (잘 안씀) - 요청
Referer : 현재 요청된 페이지의 이전 웹 페이지 주소를 나타냄. - 요청
User-Agent : 클라이언트의 애플리케이션 정보를 나타냄. - 요청
Server : 요청을 처리하는 origin 서버의 소프트웨어 정보. (origin 서버 : 목적지 서버) - 응답
Date : 메서지가 발생한 날짜와 시간. - 응답
Host : 요청한 호스트 정보(도메인). 필수적으로 사용한다. - 요청
하나의 서버가 여러 도메인을 처리할 때 사용된다.
Location : 페이지 리다이렉션에 사용된다. - 응답
Allow : 허용 가능한 HTTP 메서드. 405번 에러에서 응답으로 어떤 메서드가 허용 가능한지 알려준다. - 응답
Retry-After : 클라이언트가 다음 요청을 하기까지 기다려야 하는 시간. 503번 에러에서 서비스가 언제까지 먹통인지 알려줌.
Authorization : 클라이언트의 인증 정보를 서버에 전달한다.
WWW-Authenticate : 리소스 접근 시 필요한 인증 방법 정의. 401번 에러의 응답과 함께 사용함.
HTTP는 Stateless 프로토콜이다. 클라이언트와 서버가 통신한 후에는 연결이 끊겨 서버는 클라이언트의 이전 요청을 기억하지 못한다.
웹 브라우저는 서버에게서 받은 특정 정보를 쿠키로 저장해 서버에게 요청 시 무조건 쿠키 정보를 자동으로 포함하도록 한다.
쿠키 정보는 항상 서버에 전송되기에 트래픽이 추가로 발생하니 보안에 민감한 데이터는 쿠키로 저장하지 말고 최소한의 정보만 쿠키로 저장하도록 하자.
생명주기 : 세션 쿠키는 브라우저 종료 시 까지 쿠키를 유지하고, 영속 쿠키는 지정한 날짜까지 쿠키를 유지한다.
도메인 : 특정 도메인에 요청할 때만 쿠키를 포함시킨다. (생략 시 서브 도메인은 포함하지 않음)
경로 : 도메인으로 한 번 걸러내고 경로를 통해 한 번 더 걸러낸다.
보안 : Secure) https만. HttpOnly) JS에서 접근 x HTTP전송에만 사용. SameSite) 요청 도메인과 쿠키 값이 같을 때만 전송
캐시
캐시가 없을 때 클라이언트가 서버에게 이미지를 요청하면 1.1M 크기의 HTTP 응답 메세지를 반환해준다.
이후 똑같은 요청을 하더라도 계속 1.1M 크기의 응답 메세지를 받게 된다.
즉, 데이터가 변경되지 않아도 네트워크를 통해 데이터를 다운로드 받아야 한다.
인터넷 네트워크는 매우 느리고 매우 비싸 변경되지 않은 데이터에 대해서는 재요청하는 방법 외에 다른 방법을 사용해야 한다.
이 때 캐시를 사용한다.
웹 브라우저에는 캐시를 저장하는 저장소가 있다.
응답 메세지에 캐시가 유효한 시간을 추가해서 보내고, 웹 브라우저는 유효한 시간동안 캐시를 저장해 두 번째 요청 시 캐시 저장소를 찾아 해당 캐시가 있다면 그대로 사용한다.
캐시의 유효기간이 만료되면 어떻게 될까?
요청하는 데이터에 변화가 생겼으면 당연히 다시 다운로드하는게 맞지만, 유효기간이 만료됐을 때 요청하는 데이터에 변화가 없어도 네트워크를 통해 다시 다운로드 해야 할까?
물론 상관없긴 하지만.. 네트워크 비용을 최대한 줄이고 사용자의 편의를 최대한 보장해야 한다.
클라이언트가 가진 데이터와 서버가 가진 데이터가 같다는 사실을 확인할 수 있다면..?
Last-Modified 검증 헤더를 추가해서 가장 마지막에 수정된 날짜를 표시한다.
클라이언트와 서버에서 데이터의 최종 수정일이 같으면 서버는 클라이언트의 요청에 대해 메세지 바디를 생략한 응답 메세지를 보낸다.
훌륭한 방법이지만, 날짜 기반으로 정해진 로직을 사용해 변경 날짜는 다르지만 데이터는 같은 경우를 잡을 수 없고, 1초 미만 단위로 캐시 조정이 불가능하다는 단점이 있다.
이런 단점을 극복하기 위해 ETag가 도입됐다.
캐시용 데이터에 임의의 고유한 버전 이름을 설정해 데이터의 변경을 감지한다.
클라이언트는 ETag만 보내서 같으면 유지, 다르면 다시 다운로드하는 방식으로 사용한다.
관련 헤더
Cache-Control : max-age. 캐시의 유효시간을 설정.
Cache-Control : no-cache. 데이터는 캐시하지만, origin 서버에 검증하고 사용.
Cache-Control : no-store. 데이터에 민감한 정보가 있어 저장하지 말 것.
Cache-Control : must-revalidate. 캐시 만료 후 최초 조회 시 원 서버에 검증하도록 함.
Cache-Control : public. 프록시 캐시 서버에 저장해도 괜찮은 정보.
Cache-Control : private. 개인적으로만 사용하는 정보.
Cache-Control : s-maxage. 프록시 캐시에만 적용되는 max-age.
Pragma : no-cache. Cache-Control의 하위호환이라 잘 쓰지 않는다.
Expires : 캐시 만료일을 지정한다. 보통 Cache-Control 을 사용함.
ETag : 요청 시 If-Match, If-None-Match 헤더를 사용함.
Last-Modified : 요청 시 If-Modified-Since, If-Unmodified-Since 헤더를 사용함.
한국에서 미국에 있는 서버에 요청을 보낸다고 생각해보자.
요청을 보내는데 한참 걸리기 때문에.. 한국 어딘가에 프록시 캐시 서버를 만들어놓고 캐시를 관리한다.
처음 요청을 보내는 클라이언트는 프록시 캐시 서버에 캐시가 없어 느리지만, 그 이후의 클라이언트들은 프록시 캐시 서버에 있는 캐시를 사용해 미국에 있는 origin 서버까지 요청할 필요가 없어 빠르게 응답받는다.
no-cache를 사용하면 원 서버에 접근할 수 없는 경우 오래된 데이터라도 보여주지만, must-revalidate를 사용하면 원 서버에 접근할 수 없을 때 항상 오류를 뱉는다.
'Computer Science > Network' 카테고리의 다른 글
[Nginx] 내부 구조와 리버스 프록시 (1) | 2023.12.21 |
---|---|
[HTTP] HTTP 쿠키와 세션 (0) | 2023.06.12 |
[HTTP] 상태코드 (2) | 2022.08.12 |
[HTTP] HTTP 메서드와 활용 (1) | 2022.08.12 |
[HTTP] URL / HTTP 기본 (1) | 2022.08.12 |
댓글
이 글 공유하기
다른 글
-
[Nginx] 내부 구조와 리버스 프록시
[Nginx] 내부 구조와 리버스 프록시
2023.12.21 -
[HTTP] HTTP 쿠키와 세션
[HTTP] HTTP 쿠키와 세션
2023.06.12 -
[HTTP] 상태코드
[HTTP] 상태코드
2022.08.12 -
[HTTP] HTTP 메서드와 활용
[HTTP] HTTP 메서드와 활용
2022.08.12