HTTP/1.1의 메시지 포멧은 구현의 단순성과 접근성에 주안점을 두고 최적화 되었기 때문에 성능이 일정부분 희생되었다. 존재하는 하나의 커넥션을 통해 요청을 하나 보내고 그에 대한 응답 하나만을 받는 HTTP의 메시지 교환 방식은 단순하지만, 응답을 받아야 그다음 요청을 보낼 수 있기 때문에 심각한 지연 문제가 발생하였다. 이 문제를 해결하기 위해서 병렬 커넥션, 파이프라인 커넥션등이 도입 되었지만, 근본적인 해결책은 아니다.
2009년 구글이 SPDY라는 프로토콜을 내놓았고, SPDY는 기존 HTTP에 속도를 개선하기위한 여러 기능을 추가한 프로토콜이다. 헤더를 압축하여 대역폭을 절약하고, 단 한개의 TCP커넥션에 여러 요청을 동시에 보내 회전 지연을 줄였으며, 클리아언트가 요청을 보내지 않아도 서버가 리소스를 푸시하는 기능도 갖추고 있다.
이러한 기능들은 회전 지연을 줄이기 위한 것이고, SPDY를 적용했을때 RTT(Round-trip delay time) 20ms인 상황에서는 약 12%의 성능 개선 효과가 있었으며, 80ms인 상황에서는 약 24%, 200ms인 상황에서는 약 27%의 개선 효과가 있다.(https://www.chromium.org/spdy/spdy-whitepaper/)
HTTP2.0은 이런 SPDY를 기반으로 설계되었으며, SPDY의 특징을 대부분 유지하고 있다.
HTTP/2.0은 서버와 클라이언트 사이의 TCP커넥션 위에서 동작한다. HTTP 요청과 응답은 한개 이상에 프레임에 담기고 헤더는 압축되어 담긴다.
프레임에 담긴 요청과 응답은 스트림을 통해 보내지는데, 한 개의 스트림이 한 쌍의 요청과 응답을 처리한다. 하나의 커넥션 위에 여러개의 스트림이 동시에 만들어 질 수 있으므로, 여러개의 요청과 응답을 동시에 처리하는 것 역시 가능하다. HTTP2.0은 스트림에 대한 흐름 제어와 우선순위 부여 또한 제공한다
기존의 요청-응답 모델 뿐만 아니라 서버 푸시 모델 또한 도입했다. 서버는 클라이언트에게 필요하다고 생각되는 리소스라면 요청을 받지 않더라도 능동적으로 클라이언트에게 보내줄 수 있다.
SSE와 어떻게 다른지 조금 찾아봤는데, SSE는 이벤트에 포커스가 맞춰져 있는 기능이고, HTTP/2.0의 서버 푸시는 서버의 능동적인 리소스 캐싱에 포커스가 맞춰져 있는 기능인듯하다.
스트림은 HTTP/2.0커넥션을 통해 클라이언트와 서버 사이에서 교환되는 프레임들의 독립된 양방향 시퀀스이이다. 한 쌍의 HTTP 요청 응답은 하나의 스트림을 통해 이루어지는데, 클라이언트는 새 스트림을 만들고 그걸 통해 새 HTTP 요청을 보낸다. 요청 받은 서버는 해당 스트림으로 응답을 보내게 되고 그 후 스트림은 닫힌다.
HTTP/1.1에서는 한 TCP커넥션을 통해 요청을 보냈을 때, 그에대한 응답이 도착 하고 나서야 같은 TCP커넥션으로 다시 요청을 보낼 수 있는데, 웹 브라우저들은 지연을 줄이기 위해 여러개의 TCP 커넥션을 만들어 동시에 여러 개의 요청을 보낸다. 하지만 커넥션은 무한 할수 없으며, 파이프라인 커넥션을 통해 최대한 피할 수 있으나, 널리 사용되지는 않고 있다.
HTTP2.0에서는 한 커넥션에 여러개의 스트림이 동시에 열릴수 있기 때문에 여러 요청이 동시에 보내질 수 있다.
또한 스트림은 우선순위를 가질 수 있기 때문에 보다 중요한 시소스에 대하여 더 높은 우선순위를 부여할 수 있다.
HTTP1.1에서는 헤더는 무압축 상태로 전송되었고 과거에는 서버에 요청하는 HTTP 요청이 많으므로 헤더의 크기가 대역폭에 영향을 끼치게 된다. 때문에 HTTP2.0에서는 HTTP메시지의 헤더를 압축하여 전송한다.