HTTP3이 나왔다고?

업데이트:

HTTP 프로토콜의 TCP/IP 기반에 대한 얘기를 하던 중 HTTP/3에 대한 키워드를 들었다.

HTTP/2 버전도 사용해본 적 없는 와중에 3버전이 나온지가 1년이 넘었다는 것을 알고는 놀랍기 그지없었다. HTTP/1.1 이후 2가 나오기까지 18년이 걸렸던 것에 비하면 4년만에 3버전이 나왔다. 거기다 TCP 기반이었던 지난 버전과는 다르게 UDP 기반으로 설계 되었다는 것도 신선한 소식이었다.

아직까지 HTTP/1.1만 사용한다고 2에 대해서도 제대로 알아보지 않았다는 것을 반성하며 HTTP 프로토콜의 과거부터 현재까지 알아보려고 한다.

HTTP 버전 정리

HTTP/0.9

버전번호가 따로 없는 채 세상에 나왔던 초기 HTTP는 요청이 단일 라인으로 구성되어 있었고 메서드는 get이 유일했다.

GET /index.html

Header도 없었으며 상태 오류 코드도 없었기 때문에 문제가 생겼을 때 특정 HTML 파일을 오류에 대한 설명과 함께 보냈다.

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

HTTP/1.0

1.0 버전부터 여러 메타정보(Header)가 포함되어 기존의 것에 비해 여러 기능을 추가할 수 있게 되었다. 여기서 버전을 1.0으로 달게 되었고, 그 이전의 초기버전은 구분을 위해 0.9로 부르게 되었다. 어떤 기능이 추가됐는지 살펴보자.

  • 버전 정보가 GET 요청 라인에 붙은 형태로 전송
  • 상태 코드가 응답의 시작 부분에 추가
  • HTTP Header가 추가
    • 다른 타입의 문서 전달 가능(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>

이미지파일 요청 메시지

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.0 발표가 된지 얼마 지나지 않아 HTTP의 첫번째 표준 버전인 1.1이 발표되었다. HTTP/1.1 버전은 많은 개선사항을 도입하였다.

  • 커넥션의 재사용 가능(기존 연결에 대해서 handshake 생략가능)

    Untitled

    STN과 ACK을 통해 TCP 3 handshake가 일어난 후에 Client가 다시 css 파일을 요청하게 되면 다시 3 handshake를 하는 게 아니라 기존의 커넥션을 재사용하게 되어 응답에 걸리는 시간을 줄였다. Connection:close가 올 때까지 계속해서 지속 커넥션으로 취급한다.

  • 파이프라이닝 추가, 이전 요청에 대한 응답이 완전히 전송되기 전에 다음 전송이 가능하여 커뮤니케이션 레이턴시를 낮춤

    Untitled

  • 청크된 응답 지원(응답 조각)
  • 캐시 제어 메커니즘
  • 언어, 인코딩 타입 등을 포함한 컨텐츠 전송
  • 동일 IP 주소에 다른 도메인을 호스트하는 기능 가능 (HOST header)
GET /flag HTTP/1.1
Host: www.modusecurity.xyz
User-Agent: curl/7.66.0
Accept: */* HTTP/1.1
Host: www.modusecurity.xyz
User-Agent: curl/7.66.0
Accept: */*

HTTP/2

웹이 발전함에 따라 웹페이지를 가져오는데 필요한 리소스의 수가 크게 늘어남에 따라 FIFO(선입선출)의 방식이던 파이프라이닝 한계(HOL blocking)가 있었고 TCP 병렬 수행이 늘어남에 따라 연결 비용이 증가하였다.

이를 해결하기 위해 streams라는 개념을 도입하였다. 서로 다른 HTTP 연결들을 하나의 TCP 스트림으로 다중화하여 추상화 하는 개념으로, 보다 효율적으로 TCP 연결을 재사용 할 수 있도록 지원하는 개념이다. 스트림을 통해 응답 다중화(멀티플렉싱)이 가능해졌다.

하지만 이러한 노력에도 피해갈 수 없는 문제인 HOLB라는 걸림돌이 있었다. HOLB(Head of line Blocking)은 TCP 패킷이 네트워크 경로에서 손실되면 스트림에 공백이 생겨, 손실 된 바이트 다음에 오는 올바른 바이트들도 재전송으로 인해 전달이 되지 않아 발생하는 불필요한 지연을 말한다. 프로토콜이 TCP를 사용하는 한 피해갈 수 없는 문제인 것이다.

특히, HTTP/2의 경우에는 여러개의 HTTP 스트림을 하나의 TCP 커넥션으로 처리하기 때문에 더 크게 영향을 받게 된다.

HTTP/3.0 - with QUIC

위에서 본 것 처럼 TCP를 사용하는 한 해당 이슈를 고치기 쉽지 않다고 판단하여 UDP를 사용하면서 신뢰성을 높이는 방안을 고민했다.

Untitled

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

또한 QUIC은 위에서 언급된 TCP의 HOL block 문제도 해결했다. 각 스트림을 스트림 식별자로 식별하면서 독립적인 스트림을 갖게 하면 스트림 중 하나에서 어떤 패킷이 손실 되더라도 해당 스트림만 멈추게 된다.

Untitled

정리

최대한 간단하게 정리해보려고 했는데 쓰다 보니 모르는 것이 계속 나와 머리 속에서 그림을 그리기 어려웠다. 지금은 온전히 이해하기 보다는 어떻게 해서 1.1에서 2로, 그리고 3을 향해 가고 있는지 흐름을 중점적으로 생각하면 좋을 거 같다.

참고

https://evan-moon.github.io/2019/10/08/what-is-http3/

https://velog.io/@seeker1207/HTTP-0.9에서-HTTP-3.0까지

태그:

업데이트:

댓글남기기