HTTP/1이든 HTTP/2이든, HTTP 버전들에 대해 알아보기 전에 그 HTTP가 도대체 무엇인가를 한 번 살펴본 후에 버전들에 대해 자세히 알아보려한다.
😊 아래 글을 번역 및 참고한 것으로, 어색한 부분이 있을 수 있습니당 😊
https://cs.fyi/guide/http-in-depth
https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/
HTTP
HTTP(HyperText Transfer Protocol)는 WWW(World Wide Web) 기반으로 하이퍼텍스트 링크를 사용해 웹 페이지를 로드하는데 사용된다.
HTTP Request
HTTP request는 웹 브라우저와 같은 인터넷 통신 플랫폼이 웹 사이트를 로드하는데 필요한 정보를 요청하는 방식이다.
HTTP 메소드
GET, POST 등
HTTP request Headers
모든 HTTP request에 포함되어 있으며 key - value의 형태로 저장된 텍스트 정보들을 포함하고 있다.
client가 사용중인 브라우저, 요청중인 데이터 등 중요한 정보를 전달한다.
HTTP request Body
요청이 전달하고 있는 정보의 'body' 부분으로 유저이름, 패스워드 또는 폼에 입력된 기타 다른 데이터와 같은 웹 서버에 제출된 모든 정보를 포함한다.
HTTP response
웹 client가 서버로부터 받은 HTTP 요청에 대한 응답이다.
응답에는 HTTP request에서 요청된 내용을 기반으로 중요한 정보들이 들어있다.
HTTP status code
HTTP 상태 코드는 HTTP request가 성공적으로 끝났는지 아닌지를 나타내는 3자리 숫자로, 다음과 같은 종류가 있다.
(xx는 00부터 99까지의 숫자임.)
- 1xx : Informational
- 2xx : Success
- client가 웹 페이지를 요청하면 대부분 200, OK 라는 요청이 제대로 완료되었다는 상태코드를 볼 수 있다.
- 3xx : Redirection
- 4xx : Client Error
- client측 에러로, 가장 많이 볼 수 있는 에러는 404, NOT FOUND로 URL에 오타가 있을때 볼 수 있는 상태코드이다.
- 5xx : Server Error
- 서버측 에러
HTTP response Headers
HTTP request와 비슷하게 HTTP response도 헤더와 같이 오게 되는데, body에 담겨 오는 언어나 데이터 형식 등 중요한 정보를 담고 있다.
HTTP response body
GET 요청에 대한 성공적인 응답에는 일반적으로 요청된 정보가 포함된 body가 있다.
대부분 웹 브라우저가 웹 페이지로 변환하는 html 데이터이다.
HTTP/0.9
HTTP의 가장 첫번째 버전으로, GET 메소드만 있는 가장 단순한 프로토콜이다.
GET /index.html //이렇게 요청하면
//아래와 같은 응답을 받을 수 있다.
(response body)
(connection closed)
- 서버가 요청을 받으면 html으로 응답한다. (응답이 html로 이루어져 있다.)
- 내용이 전달되자마자 연결이 끊어진다.
- 헤더가 없다.
- GET이 유일한 메소드이다.
HTTP/1.0
그 다음 버전인 HTTP/1.0에서는 0.9에서 부족했던 부분이 많이 개선되었다.
- html로만 구성된 0.9와 달리 이미지, 비디오 파일, 텍스트 등 다양한 content-type 응답 형식을 다룰 수 있게 되었다.
- GET 이외에 POST, HEAD 메소드가 추가되었다.
- request/response 형식이 바뀌었다.
- HTTP Headers가 요청과 응답 두개 모두에 추가되었다.
- 응답을 식별하기 위한 응답 코드도 추가되었다.
- 문자 집합 지원, multi-part types, 인증, 캐싱, 인코딩 등등..
HTTP/1.0에서의 요청과 응답은 아래와 같다.
//요청
GET / HTTP/1.0
Host: cs.fyi
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
// 응답
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
(response body)
(connection closed)
client는 요청과 함께 개인 정보, 필수 응답 유형 등을 전송한다.
0.9에서는 header가 없었기 때문에 이런 정보 또한 전송할 수 없었다.
응답 가장 첫 줄을 보면 HTTP 버전과 상태코드를 볼 수 있다.
Content-Type에서 이미지, 비디오, html, 텍스트 등.. 여러가지가 지원되는 것을 확인할 수 있다. 이제 어떤 타입이든 client에게 보낼 수 있게 된 것이다.
유일한 단점은 한 번 연결되면 여러 번 요청을 할 수 없다는 것이다. 즉, client가 서버에 여러 요청을 했는데, 새로운 TCP 연결을 하고 나서 단 하나의 요청만 수행되고 연결은 끊기게 되는 것이다. 그리고 그 다음 요청을 위해서는 또 다시 새로운 연결을 해야한다.
이게 왜 단점인가 하면, 이미지 10개, 스타일시트 5개, 자바스크립트 파일 5개 총 20개가 있는 웹 페이지를 방문한다고 했을 때, 웹 페이지가 만들어지려면 데이터를 요청해야 한다. request가 수행되자 마자 연결을 끊기 때문에 20개가 다 따로 연결되어 있을 것이다. 이렇게 많은 연결은 성능 저하를 낳게된다.
HTTP/1.1
PUT, PATCH, OPTIONS, DELETE 등 새로운 HTTP 메소드가 추가된 새로운 버전이 1999년에 나왔다.
Hostname Identification
HTTP/1.0 호스트 헤더에서는 필요 없었는데 HTTP/1.1에서는 필요해졌다.
라고는 하는데 이건 뭔지 잘 모르겠다..
Persistent Connection
HTTP/1.0에서는 한 연결 당 하나의 요청만 가능했지만 1.1에서는 연결이 끊기지 않고 여러번의 요청에도 계속 열려있다.
연결을 끊기 위해서는 또 다른 헤더를 사용해야하고 client는 가장 마지막 request에 헤더를 보내 안전하게 연결을 끊는다.
Pipelining
클라이언트가 동일한 연결에서 서버의 응답을 기다리지 않고 서버에 여러 요청을 보낼 수 있으며, 서버가 요청 받은 순서대로 응답을 보내야하는 파이프라이닝을 도입했다.
클라이언트가 첫번째 응답 후, 다음 응답에 대한 내용이 시작되는 지점이라는 것을 어떻게 아는가?
Content-Length 헤더가 있다. 응답 끝부분에서 client가 식별할 수 있는 것으로, 다음 응답을 위해 대기를 시작할 수 있다고 한다.
Chunked Transfers
동적 컨텐츠에서 서버가 Content-Length를 찾지 못하면, contents를 조각들로 보내기 시작하고, 보내질 때 각각의 덩어리에 대한 Content-Length를 추가한다. 이 모든 덩어리들이 보내지고나면 빈 chunk 하나를 보낸다. 비어있는 chunk에는 Content-Length가 zero로 세팅되어있으며 이걸로 전송이 완료된 client를 식별할 수 있다.
이외에도 digest와 proxy 인증, 캐싱, byte ranges, language negotiation, client cookies, status codes, 등등!!
HTTP/2
HTTP/2는 컨텐츠 전송 시에 지연되는 시간을 짧게 하기 위해서 설계되어 나왔다.
주요 특징 및 1.1과의 차이점은 아래와 같다.
Binary instead of Textual
HTTP/2는 HTTP/1.x를 바이너리 프로토콜로 만들어 대기 시간 증가 문제를 해결한다.
바이너리 프로토콜이 되면서 내부적으로 대기 시간 감소나, 분석이 더 쉬워지긴 했지만 더이상 사람이 읽을 수 있는 형태는 아니다.
Multiplexing
단 한번의 연결로 여러 비동기 HTTP를 요청할 수 있다.
TCP 연결이 되면 모든 스트림이 다른 연결 필요 없이 같은 연결 내에서 비동기로 보내진다. 이후 서버는 같은 비동기 방향으로 응답을 한다. 딱히 순서는 없으며 client는 특정 패킷과 함께 있는 스트림을 시별하기 위한 스트림 ID가 할당되어 사용할 수 있다. 이제 요청을 하고 받을 때까지 기다릴 필요가 없어진 것이다.
HPACK을 이용한 헤더 압축
지연시간이 길어지는 것을 해결하기 위해 Header를 압축한다.
문자 값이 허프만 코드로 인코딩되고 헤더 테이블은 client와 서버에 의해 유지되며 client와 서버는 다음 요청에서 반복되는 헤더를 생략한다. 그리고 둘 다 유지/관리하는 헤더 테이블에서 참조해서 사용한다.
Server Push
한 번의 요청에 대해 여러 응답이 가능하다.
client가 특정 리소스에 대해 요청하려는 것을 아는 상황일 때, 서버는 client가 요청하기 전에 push할 수 있다는 것이다.
예를 들어, 웹 페이지를 로드한다 하면 전체 페이지를 분석하고 서버에서 로드해야하는 원격 콘텐츠를 찾은 후 해당 컨텐츠를 가져오기 위해서 서버에 request를 보낸다. client가 요청할 데이터를 서버가 push 함으로써 왕복하는 일을 줄이도록 했다. 서버는 PUSH_PROMISE라 불리는 특정 프레임을 client에 보낸다.
응답 우선순위
client는 스트림이 열려있을 때 HEADERS 프레임에 우선순위 정보를 포함해 스트림에 우선순위를 할당할 수 있다. 이미 정해진 우선순위를 수정(변경)하기 위해서는 PRIORITY 프레임을 보낼 수 있다. 우선순위 정보가 없다면 서버는 비동기적으로 처리하게 되지만 우선순위가 할당되어 있다면 서버는 어떤 요청을 처리하기 위해 얼마나 많은 리소스를 제공해야하는 지 미리 결정하게 된다.
HTTP/3도 있는데, 그건 다음에 QUIC랑 함께 묶어 따로 작성할 예정이다.
원래 아주 옛것까지 공부해내는 역사공부를 즐겨하지 않는다. 새로 생겨나는 것을 알아가는 것보다는 흥미가 덜해서.. 단순 이런 이유긴 하지만😅 이번에 HTTP를 0.9버전부터 보면서 문제점이라 생각되었던 게 그 다음 버전에서는 해결이 됨이 반복되면서 더 재미있게 공부한 것 같다.
무엇보다 이 글을 보시는 분들도 계시겠지만, 나는 원어로 작성된 글을 보는 것이 더 도움이 되는 것 같다. 어떤 블로그든 쉽게 찾을 수 있는 정보이지만 조금 더 전문화되어있는 느낌도 있고, 여기저기 블로그 글에 휘둘리지 않고 내가 공부한 것에 확신이 든다고나 할까..😅
끝!
'TIL' 카테고리의 다른 글
[TIL] 비트 연산자 (&, |, ^, ~, <<, >>) (0) | 2024.06.02 |
---|---|
[TIL] How does the Internet work (0) | 2023.04.16 |