HTTP 0.9에서 HTTP 3.0까지

seeker1207·2021년 9월 23일
1

http의 역사는 웹개발자로서 알아야할 필수교양 같은것이라고 생각한다.
웹이 어떻게 발전되어 왔는지를 한눈에 알 수 있고 프론트엔드 개발 뿐만 아니라 rest API를 이용하는 수많은 분야의 개발자들이 알아야할 부분이 아닌가 싶다.
그래서 공부도 할겸 한번 정리해보는게 나을것 같아 정리하였다.

HTTP/0.9

HTTP 초기버전에는 버전이 없었으며, 차후 버전과 분리하기위해 0.9로 불리우게 되었다. 가능한 메서드는 GET이 유일했으며 요청과 응답이 극히 단순하였다.
상태 오류 코드도 없었기 때문에 문제가 발생한 경우 특정 HTML 파일을 오류에 대한 설명과 함께 보내졌었다.

요청은 한줄이 다였다.

GET /mypage.html

응답도 body만이 전부였다.

<HTML>
	A very simple HTML page
</HTML>

HTTP/1.0 - 헤더의 등장

1.0부터 여러 메타정보(헤더)가 포함되기 시작했다.

  • 버전 정보가 GET라인에 붙은 형태로 전송되기 작했다.
  • 상태 코드가 응답의 시작부분에 붙어 전송되었고, 그 결과에 대한 동작을 할 수 있게 되었다.
  • HTTP 헤더 개념이 추가되어 유연하고 확장 가능하도록 만들어주었다.
  • HTML 파일 형식 외에 다른 문서들을 전송하는 기능이 추가되었다.(Content-Type 덕분에)

일반적인 요청 메세지

GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
A page with an image
  <IMG SRC="/myimage.gif">
</HTML>

HTML이 아닌 파일인 이미지파일 요청 메세지

GET /myimage.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:32 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/gif
(image content)

HTTP/1.1 - 커넥션 재사용

  • 1.1의 가장 큰 특징은 사용된 커넥션을 다시 열어 시간을 절약하게 했다는 것이다.

위 그림을 살펴보면 만약에 사용된 커넥션을 다시 사용하지 않는 다면 TCP 3 handshake가 html 파일, css 파일을 요청할때 각각 성립이 되어야 할것이지만 기존의 커넥션을 재사용함으로써 시간을 줄였다.

  • 파이프라이닝
    파이프 라이닝은 여러개의 요청을 보낼때 처음 요청이 응답될 때까지 기다리지 않고 바로 요청을 보내는 것을 의미합니다.
    이로인해 많은 대기 시간을 줄일 수 있습니다.

    하지만 여기에서 중요한 점은 FIFO(선입선출) 방식으로 response가 보내져야 한다는 것이다.
    위의 그림에서 만약 서버가 두 요청을 동시에 처리하게 되면 어떻게 될까?

  • http/1.1의 한계(HOL block)
    css 리소스에 대한 요청이 먼저 처리된다고 하더라도 HTML요청이 먼저 도착했기 떄문에 HTML 응답이 전송될 때까지 css응답은 block 된다.
    이를 HOL(head-of-line) block이라고 부르고 이런경우 때문에 첫번째 요청이 오래걸릴 경우 다른 모든 요청이 차단되어 기다려야하는 배우 비효율적인 상황이 발생하게 된다.

따라서 위의 문제점과 여러 구현 복잡성에 의해 파이프라이닝은 기능활용이 매우 제한적이었으며 대부분의 브라우저에서는 여러개의 tcp 연결을 만들어 병렬적으로 이용하는 방식을 많이 사용하였다.

하지만 여러개의 연결을 만들어 사용하는 것도 추가 메모리와 cpu리소스를 낭비하는 단점이 있었고 이러한 점을 보완해야했다.
이러한 단점들을 보완하고자 나온것이 2.0 이었다.

HTTP/2.0 - 멀티플렉싱

처음 http/2.0의 초기모델을 제시한것은 구글에서 만든 시험용 프로토콜인 SPDY였다. SPDY를 주시하고 있었던 HTTP Working Group이 HTTP/2 의 출발점으로 SPDY 사양을 채택했다. 그래서 SPDY는 HTTP/2.0의 시험용 브랜치가 되었고 나란히 발전하여 HTTP/2 표준이 발행되었다.

  • 바이너리 프레이밍 계층
    HTTP/2.0 의 핵심은 기존의 요청메세지를 작은 프레임으로 쪼개었다는 것이다.

    헤더부분과 컨텐트 부분을 하나의 프레임으로 분리 시켰고 기존의 텍스트 형식의 요청메세지를 새 바이너리 인코딩을 통해 최적화 시켰다.

이렇게 하나의 논리적인 스트림(요청하고 응답하는 하나의 데이터 양방향 흐름)을 여러개의 프레임으로 분리 시켰다.

따라서 각 프레임에는 이것이 어떤 스트림인지 고유한 식별자가 있다.
그리고 더 중요한 지점은 이러한 여러개의 스트림을 인터리빙 한다는 것이다. 여기서 인터리빙은 여러개의 스트림에서 쪼개진 프레임들을 서로 끼워넣는 것을 얘기한다.

위의 그림에서 스트림 1,3,5 총 3개의 스트림이 동시에 병렬적으로 하나의 연결안에서 이루어지는 것을 알 수 있다. 이로써 응답 다중화 (멀티플렉싱)을 가능하게 하고 위에서 언급 되었던 HOL block 문제를 해결 할 수 있다. 또한 여러 개의 연결이 없어도 되기 때문에 리소스 비용이 더 절감될 수 있는 장점이 있다.

정리한 그림은 다음과 같다.

파이프라이닝과 멀티플렉싱의 차이를 주목해서 보면 될것 같다.

HTTP/3.0 - with QUIC

앞서 보았듯이 2.0에서 http 의 HOL(head-of-line) 문제를 해결하였다.
하지만 TCP에 기반을 둔 headof line 블록킹 문제가 남아있었다.


2.0에서는 하나의 연결안에서 여러개의 스트림이 전송되는데 여기서 하나의 패킷이 빠지거나 없어지면 없어진 패킷을 다시 전송하고 목적지에 도달하는 동안 전체 TCP 연결이 중단되게 된다. TCP 자체가 신뢰성 이 보장된 프로토콜이기 때문에 이와 같은 문제가 발생하게 되었다.
그래서 TCP를 이용하는 한 이 이슈를 고치는 것은 쉽지 않다고 판단되었고 그래서 UDP를 이용하면서도 TCP의 혼잡제어나 신뢰성을 보장하는 장점을 살리는 방안을 고민하게 되었다.

그래서 QUIC 프로토콜이 등장하게 되었다. UDP가 데이터 전송의 신뢰성을 보장하지 않지만 UDP위에 새로운 전송계층을 추가함으로써 TCP에 존재하는 패킷 재전송, 혼잡 제어, 속도 제어 등 여러 기능들을 제공한다.
또한 QUIC은 위에서 언급된 TCP의 HOL block 문제도 해결했다.

이렇게 각 스트림을 스트림 식별자로 식별하면서 독립적인 스트림을 갖게
하면 스트림 중 하나에서 어떤 패킷이 손실되더라도 해당 스트림만 멈추게 된다.
또한 QUIC는 0-RTT, 1-RTT 핸드쉐이크를 둘다 제공 하기 때문에 기존의 3-way handshake로 발생되는 시간을 줄여준다.



참고자료
https://http2-explained.haxx.se/ko
https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP
https://developers.google.com/web/fundamentals/performance/http2?hl=ko
https://hpbn.co/http1x/#using-multiple-tcp-connections
https://http3-explained.haxx.se/ko/why-quic
https://blog.cloudflare.com/the-road-to-quic/

profile
춤추듯 개발하고 싶은 사람

2개의 댓글

comment-user-thumbnail
2022년 6월 7일

블로그 내용 잘 봤습니당!! . 저도 개발자가 되기 위해서 기술 면접 준비중인데 비공개로 제 블로그에 퍼가도 되나요???

1개의 답글