Persitent Connections - HTTP 요청은 TCP 프로토콜을 이용하기 때문에 요청을 전송하기 위해선 3-way-handshake 과정을 거쳐 연결을 설정 해야한다. 하지만 매 요청마다 3-way-handshake를 하는 과정에서 많은 시간이 소요되기 때문에 HTTP 1.1 이전에는 keep-alive 헤더를 이용하여 일정 시간동안 연결을 끊지않고 여러 요청에 재사용하도록하여 TCP handshake하는 비용을 아끼고 성능을 향상시켰다.
하지만 HTTP 1.1 부터는 기본적으로 요청에 대한 연결을 일정시간동안 끊지않도록 되어있기 때문에 keep-alive 헤더를 사용할 필요가 없다.
Pipelining - 기본적으로 HTTP 요청은 순차적이기 때문에 요청에 대한 응답을 받고 나서야 새로운 요청을 보낸다. 하지만 HTTP 1.1 부턴 응답을 기다리지 않고 요청을 연속적으로 보내는 기능인 Pipelining 스펙이 추가되었다.
하지만 모든 요청에 Pipelining이 적용되는 것은 아니다. GET, HEAD, DELETE, PUT과 같은 멱등성이 보장되는 요청에만 적용된다.
Pipelining의 문제점도 있다. 응답순서는 보장되어야하기 때문에 앞의 요청을 처리하는데 많은 시간이 소요된다면 뒤의 요청들이 늦게 응답 받게되는 Head Of Line Blocking이 발생한다.
HTTP/2.0은 새로운 기능이 도입되기 보단 HTTP/1.1의 성능을 개선시키는데 많은 노력을 쏟았다. 즉, 성능 향상에 초점을 맞춘 프로토콜이다.
Multiplexed Streams
한 커넥션에서 여러개의 메세지를 주고받을 수 있으며, 응답은 순서에 상관없이 stream으로 주고 받는다. HTTP/1.1의 Connection Keep-Alive, Pipelining의 개선이라고 보면 된다.
아래의 이미지 처럼, 하나의 커넥션에서 여러 병렬 스트림(3개)이 존재 할 수 있다. stream이 뒤섞여서 전송 될 경우, stream number를 이용해 수신측에서 재조합된다.
Server Push
서버는 클라이언트 요청에 대해 요청하지도 않은 리소스를 마음대로 보낼 수 있다.
한마디로 클라이언트(브라우저)가 HTML문서를 요청했고 해당 HTML에 여러개의 리소스(CSS, Image 등) 가 포함되어 있는 경우 HTTP/1.1에서 클라이언트는 요청한 HTML문서를 수신한 후 HTML문서를 해석하면서 필요한 리소스를 재요청한다.
하지만 HTTP/2.0에선 Server Push
기법을 통해서 클라이언트가 요청하지도 않은 (HTML문서에 포함된 리소스) 리소스를 Push 해주는 방법으로 클라이언트의 요청을 최소화 해서 성능 향상을 이끌어 낸다.
이를 PUSH_PROMISE 라고 부르며 PUSH_PROMISE를 통해서 서버가 전송한 리소스에 대해선 클라이언트는 요청을 하지 않는다.
Header Compression
Header의 내용과 중복되는 필드를 재전송 하지 않도록 하여, 데이터를 절약한다. 또한 기존에 HTTP Header가 Plain Text(평문)이었지만, HTTP/2에서는 Hash Table과 Huffman Coding을 사용하는 HPACK이라는 Header 압축방식을 이용하여 데이터 전송 효율을 높였다.