HTTP는 HyperText Transfer Protocol의 약자로, HTML 문서와 같은 리소스들을 가져올 수 있게 해주는 프로토콜입니다. 팀 버너스 리가 WWW과 함께 만든 HTTP는 현대 인터넷 통신의 기본이 되는 프로토콜로 진화해 왔습니다.
HTTP는 HTTP/1.0을 시작으로 가장 대중적으로 사용되는 HTTP/1.1, 응답 속도를 향상시킨 HTTP/2.0을 거쳐 HTTP/3.0까지 지속적으로 발전하고 있습니다. 이 버전들의 차이가 어떤 것인지 살펴보도록 하겠습니다.
HTTP/1.0
HTTP/1.0은 HTTP의 초기 버전(HTTP/0.9라고 불림)에 비해 좀 더 프로토콜의 구색을 갖춘 형태를 띄게 되었습니다. 현재 우리에게 익숙한 상태 코드(200, 404 등)가 도입되어 브라우저가 요청에 대한 성공과 실패를 알 수 있었으며, 그 결과에 따라 특정 동작을 할 수 있게 되었습니다.
또한 HTTP 헤더 개념이 요청과 응답 모두에 도입되어, 여러 메타데이터 전송이 가능하게 되었습니다. 이로써 HTTP 프로토콜은 굉장히 유연하고 확장성 있는 프로토콜로 거듭나게 되었습니다. 기존에는 HTML 파일만 전송이 가능했다면, 헤더에 Content-Type을 추가해 HTML 파일 외의 다른 문서도 전송이 가능하게 되었습니다.
그러나 HTTP/1.0은 기본적으로 한 연결 당 하나의 요청을 처리하도록 만들어졌습니다. 서버에서 파일 하나를 가져올 때마다 TCP 연결을 위해 3-way handshake를 열어야 했고, 이 때문에 서버의 부하가 커지고 RTT가 증가하여 사용자 응답 시간이 길어진다는 단점이 있었습니다.
RTT(Round Trip Time)
RTT는 왕복 시간을 의미하며, 패킷이 목적지에 도달하고 나서 해당 패킷에 대한 응답이 다시 출발지로 돌아오기까지의 시간을 의미합니다.
HTTP/1.0을 사용하던 당시에는 이를 보완하기 위해 코드의 크기를 최소화하거나, 여러 이미지를 하나로 묶어서 한번에 가져오는 등의 방법을 사용했지만 HTTP/1.0이 공개된지 몇달 뒤에 바로 HTTP의 첫번째 표준 버전인 HTTP/1.1이 나오면서 이 문제가 해결되게 되었습니다.
HTTP/1.1
HTTP/1.1은 HTTP의 첫번재 표준 버전으로, HTTP/1.0의 모호함을 명확히 하고 많은 개선 사항들을 도입했습니다. 이 HTTP/1.1은 1997년에 공개되었으나, 현재까지도 아직 많은 곳에서 사용하고 있는 안정적인 프로토콜입니다.
HTTP/1.1에서는 대표적으로 다음과 같은 개선 사항들이 도입되었습니다.
- 커넥션을 재사용할 수 있는 keep-alive 옵션이 기본 옵션으로 설정되었습니다. 이로써 서버에서 파일을 가져올 때마다 TCP 연결을 할 필요가 없어졌고, 처음에 한 번 TCP 초기화(3-way handshake)를 한 후에는 연결된 커넥션을 다시 사용할 수 있게 되어 RTT를 줄일 수 있게 되었습니다.
- 파이프라이닝을 추가하였습니다. 기존 HTTP/1.0에서는 첫번째 요청을 보내면 해당 요청에 대한 응답이 오기 전까지 두번째 요청을 보낼 수 없었습니다. 그러나 HTTP/1.1에서는 파이프라이닝을 제공하면서 첫번째 요청에 대한 응답이 오기 전에 두번째 요청을 보낼 수 있게 되었습니다. 이를 통해 요청에 대한 레이턴시를 줄일 수 있게 되었습니다.
이 외에도 추가적인 캐시 제어 메커니즘, 청크된 응답 지원 등 여러 개선 사항이 추가되었으며, 헤더를 손쉽게 추가할 수 있는 확장성 덕분에 15년이 넘도록 새로운 버전을 내지 않고 리비전만으로 1.1버전을 유지해 왔습니다.
HTTP/2.0
HTTP/1.1은 15년이 넘도록 버전 업이 없었고, 그 사이에 웹 페이지 규모와 요청량은 어마어마하게 늘어났습니다. HTTP/1.1이 처음 공개된 1997년에 비해 현대에 달라진 웹 페이지의 특징은 다음과 같습니다.
- 훨씬 더 많은 리소스로 구성되어 있다.
- 다수의 도메인을 사용한다.
- 이전에 비해 훨씬 더 동적으로 동작한다.
- 보안이 더 중요한 이슈가 되었다.
이렇게 달라진 웹 환경을 고려해서, 구글은 HTTP를 보완한 SPDY라는 프로토콜을 발표하게 되었습니다. SPDY는 'speedy'라는 단어를 기반으로 구글이 만든 조어입니다. SPDY는 특히 HTTP/1.1의 레이턴시 문제에 집중했으며, 실제로 이 문제를 효과적으로 해결하였습니다.
이 SPDY를 참고하여, HTTP/1.1이 공개된지 무려 18년만인 2015년에 드디어 HTTP/2.0이 공식적으로 표준화되었습니다. HTTP/2.0의 대표적인 특징들은 다음과 같습니다.
Binary framing
기존 HTTP/1.x 버전에서는 요청, 응답 메시지가 plain text 형식으로 전달되었으나, HTTP/2.0에서는 메시지를 프레임 단위로 나누고 바이너리 형식으로 인코딩해서 전송합니다.
프레임(Frame)은 HTTP/2.0 통신의 최소 단위로, Header나 Data중 하나입니다. 요청, 응답 메시지는 각각 헤더 프레임과 데이터 프레임으로 구성되어 있으며, 요청의 경우에 따라(ex. GET) 메시지에 데이터 프레임 없이 헤더 프레임만 존재할 수도 있습니다.
Multiplex streaming
HTTP/2.0에서는 스트림을 이용해서 데이터를 송수신합니다. HTTP/1.1에서는 요청과 응답이 메시지라는 단위로 완벽하게 구분되어 있었으나, HTTP/2.0에서는 스트림이라는 단위를 통해 요청과 응답 메시지가 하나의 단위로 묶일 수 있게 되었습니다.
위 그림은 클라이언트 - 서버 간 하나의 TCP 연결 상태에서 여러 개의 스트림이 구성되어 있는 것을 나타냅니다. 하나의 스트림 안에 요청 메시지와 응답 메시지가 모두 포함되어 있는 것을 확인할 수 있습니다. 또한 메시지 안에서도 헤더 프레임과 데이터 프레임으로 쪼개져있는 것을 확인할 수 있습니다.
이처럼 데이터 전송에 스트림을 사용하게 되면서, 서버에서 만들어진 응답 프레임들을 요청 순서에 상관 없이 응답이 만들어진 순서대로 클라이언트에 전달할 수 있게 되었습니다. 즉, 병렬로 여러 개의 요청과 응답이 비동기 방식으로 이루어지게 된 것입니다. 이를 통해 HTTP/1.1의 문제였던 HOL Blocking을 해결할 수 있게 되었습니다.
HOL Blocking (Head Of Line Blocking)
HOL Blocking은 네트워크에서 패킷이 자신과 같은 큐에 있는 첫번째 패킷에 의해 전송이 지연될 때 발생하는 성능 저하 현상을 의미합니다. 즉, 먼저 요청된 파일의 응답 속도가 느리면 이후에 요청된 파일의 응답이 지연되는 현상을 의미합니다.
예를 들어 용량이 큰 image.jpg 파일을 요청하고 이후에 용량이 작은 style.css 파일을 요청한다면, image.jpg 파일을 응답으로 받을 때까지 style.css는 받지 못하게 됩니다. 이런 경우 style.css는 받는데 더 짧은 시간이 걸리더라도 앞서 요청한 파일 때문에 제때 응답을 받을 수 없게 됩니다.
헤더 압축
HTTP/1.1에서는 헤더에 쿠키 등 많은 메타데이터가 들어가지만 별도의 압축이 되지 않아서 헤더가 매우 무겁다는 단점이 있었습니다. HTTP/2.0에서는 이를 해결하기 위해 HPACK이라는 압축 방식을 이용해서 헤더를 압축해서 전송합니다.
HPACK은 허프만 코딩(Huffman coding) 압축 알고리즘을 이용한 압축 방식입니다. 허프만 코딩은 문자열을 문자 단위로 쪼개서, 출현 빈도수가 높은 문자는 적은 비트 수를 사용해서 표현하고, 빈도수가 높은 문자는 많은 비트 수를 사용해서 표현하는 방식입니다. 허프만 코딩의 자세한 방식은 아래 글을 참고 바랍니다.
https://http2.tistory.com/1
Server push
HTTP/1.1에서는 클라이언트가 서버에 필요한 모든 파일을 요청해야 서버에서 파일을 보내줄 수 있었지만, HTTP/2.0에서는 특정 파일에 대한 요청이 왔을 때 클라이언트의 요청 없이 해당 파일에 필요한 다른 파일들을 같이 보내줄 수 있습니다.
예를 들면 html 파일에는 css나 js 파일이 포함되기 마련인데, 이 때 html 파일 요청 시 html 파일 안에 있던 css와 js 파일을 서버에서 푸시하여 클라이언트의 요청 없이 보내줄 수 있습니다.
HTTP/3
HTTP/3은 HTTP의 세번째 버전으로, 이전 버전과의 가장 큰 차이점은 TCP 기반 통신이 아닌 UDP 기반의 프로토콜인 QUIC 기반으로 통신한다는 것입니다.
QUIC(Quick UDP Internect Connection)는 TCP가 가지고 있는 레이턴시 문제(3-way handshake 때문에 초기 연결 시간이 오래 걸리는 문제)를 해결하기 위해 구글에서 개발한 UDP 기반의 프로토콜입니다.
UDP(User Datagram Protocol)는 데이터그램 방식을 사용하여 각 패킷 간의 순서가 존재하지 않는 독립적인 패킷을 사용합니다. 또한, 정보를 주고받을 때 정보를 보내거나 받는다는 신호절차를 거치지 않습니다. 즉, 핸드쉐이크가 없습니다. 이 때문에 TCP보다 속도가 빠를 수밖에 없지만, TCP가 가지던 신뢰성과 패킷의 무결함을 보장할 수 없게 됩니다.
그럼 QUIC는 신뢰성을 보장할 수 없는 프로토콜일까요? 그렇지 않습니다. 구글은 UDP의 확장성에 주목했습니다. TCP는 핸드쉐이크를 포함한 각종 기능들을 제공하기 위해 헤더에 이미 많은 기능들이 설정되어 있습니다. 이 때문에 추가적인 기능을 설정하기가 어렵고, 이미 설정된 기능을 수정하기도 어렵습니다.
그러나 UDP는 데이터 전송 자체에만 초점을 맞추고 있기 때문에 개발자가 얼마든지 기능을 확장할 수 있는 여지가 있습니다.
즉, UDP 프로토콜 자체는 TCP보다 신뢰성이 낮고 패킷의 무결성도 보장할 수 없지만, 개발자가 어떻게 구현하는지에 따라서 TCP와 비슷한 수준의 기능을 가질 수도 있게 됩니다. QUIC는 TCP의 레이턴시를 개선하기 위해 만들어졌기 때문에, 구글은 QUIC를 만드는 데 이러한 UDP의 확장성을 적극 활용했습니다.
HTTP/3에서는 이러한 QUIC의 3-way handshake를 사용하지 않아도 된다는 가장 강력한 장점을 이용해 연결 시 레이턴시를 효과적으로 감소시킬 수 있습니다. TCP는 첫 연결 시 핸드쉐이크로 인해 3-RTT를 소요하지만, QUIC는 1-RTT만 소요합니다. 클라이언트가 서버에 신호를 한 번 주고, 서버가 거기에 응답하면 바로 통신을 시작할 수 있게 됩니다.
참고자료
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP
http://ktword.co.kr/test/view/view.php?m_temp1=1687
https://d2.naver.com/helloworld/140351
https://brunch.co.kr/@sangjinkang/3
'CS > 네트워크' 카테고리의 다른 글
홉바이홉 통신, ARP (2) | 2022.11.13 |
---|---|
네트워크 기기 (4) | 2022.11.06 |
네트워크 기초 (1) | 2022.10.31 |
[HTTP] URI와 URL (0) | 2022.08.19 |
[HTTP] IP / TCP / DNS (0) | 2022.07.08 |