이번 포스팅에서는 HTTP/2 에 대해 정리해 본다.
HTTP/2 는 기본적으로 속도 향상을 위한 노력이 전부라고 봐도 과언이 아니다.
HTTP/1.1 에서 응답 속도 측면에서 극복하기 힘든 제약 사항들에 대해 HTTP/2에서 많은 개선이 있었다.
크게 5가지 정도가 있으며 이에 대해 상세히 알아 보도록 하자.
#1. 멀티플렉싱 (Multiplexing)
HTTP/1.1 은 Persistent 와 Pipelining 기능을 통해 하나의 TCP 세션에 여러개의 요청을 보낼 수 있다.
하지만, 요청은 반드시 순차적으로 서버에서 처리되어 브라우저로 전달되어야 한다. 그렇지 못하면 웹페이지 접속의 지연이 발생되며 이를 HOLB (Head of Line Blocking) 이라고 한다.
순차적 요청 처리와 HOLB를 다소 낮추기 위해 도메인 샤딩(Domain Sharding) 이란 기술을 사용한다고 앞선 글에서 소개한 바 있다.
하지만 도메인 샤딩 기술도 서버의 커넥션 부하를 고려하면 막연히 늘릴 수 있는 것이 아니기에 완벽한 해결 방법은 되지 못한다.
HTTP/2 의 멀티플렉싱은 이런한 HTTP/1.1 의 부족한 부분을 완벽히 해소한다.
멀티플렉싱은 하나의 TCP 커넥션만으로 해당 웹페이지의 모든 요청과 응답 데이터를 전송하며, 바이너리 프레임의 스트림 전송 방식을 통해 응답 순서에 무관하게 데이터를 처리한다.
아래 그림을 보면 멀티플렉싱에 대한 이해가 쉬울 것이라 생각된다.
HTTP/1.1 의 PIPELINING 과 멀티플렉싱의 가장 큰 차이는 순차적 응답 처리에 따른 HOLB 를 완벽하게 해결했다는 것이다.
#2. 헤더 압축 (Header Compression)
HTTP/1.1 은 요청과 응답에 헤더(Header) 를 이용해서 여러 기능을 지원한다.
예컨대, Host 헤더를 이용해서 가상 호스팅(Virtual Hosting) 을 가능하게 하고, Referer 헤더를 통해 어느 경로를 통해 사이트에 접근했는지를 확인할 수 있고, User-Agent 헤더를 이용해서 사용자 환경을 조사할 수도 있다.
HTTP 헤더는 이처럼 다방면에서 활용할 수 있는 좋은 구성 요소이지만 요청/응답마다 같은 정보를 반복해서 전달해야 하는 비효율적인 측면도 존재한다.
이는 대역폭(Bandwidth)를 점유를 높여 Throughput 을 높여 회선 비용을 증가시키고, 패킷 사이즈 증가는 PPS (Packets Per Second)를 높여 네트워크 장비의 처리 부담을 높힌다.
이러한 내용들은 모두 HTTP 응답 시간(Latency) 에 관련된 것들이기에 개선이 필요하다.
HTTP/2 에서는 중복되는 헤더의 반복 전송을 효율적으로 낮추기 위해 압축(Compression) 을 이용한다.
압축은 허프만 코드를 이용하는 HPACK 알고리즘을 이용하며, 중복 내용의 반복 비율이 높을 수록 압축 효율은 커지게 된다.
다음은 허프만 코드의 예를 다룬 그림이다.
#3. 서버 푸쉬 (Server Push)
HTTP 는 클라이언트의 요청으로 부터 시작되며, 요청한 컨텐츠에 대해서만 응답으로 전송하는 것이 일반적이다.
하나의 HTML 웹페이지를 구성하는데 다양한 컨텐츠가 존재한다. 이를 테면 JS, CSS, JPG 등과 같은 여러 컨텐츠들이 하나의 HTML 페이지의 구성 요소라고 할 수 있다.
따라서 웹페이지 하나를 브라우징 하기 위해서는 클라이언트는 HTML, CSS, JS, JPG 등 구성에 관련된 모든 컨텐츠를 요청해야 했다.
HTTP/2 에서는 서버 푸쉬 기능을 통해 클라이언트가 요청하지 않은 데이터에 대해서 서버가 스스로 전송해 줄 수 있다.
예를 들어 아래와 같이 main.html 을 구성하는 요소에 style.css, script.js, image.jpg 가 있다고 가정하자.
클라이언트가 main.html 을 요청하면 HTTP/1.1 은 main.html 의 응답을 받고 main.html 안에 링크되어 있는 style.css, script.js, image.jpg 를 추가로 요청한다.
요청한 모든 컨텐츠가 전송되면 main.html 의 페이지를 브라우저에서 보여주게 된다.
HTTP/2 에서는 main.html 을 요청하면 서버는 main.html 의 구성 요소가 style.css, script.js, image.jpg 라고 정의된 경우 main.html 의 응답을 전송할 때 이 3개의 컨텐츠를 같이 전송한다.
이렇게 되면 HTTP 트랜잭션은 기존 4개에서 1개로 줄기 때문에 RTT 가 감소하여 응답속도를 개선한다.
#4. 우선 순위 (Stream Prioritization)
HTTP/1.1 에서는 웹페이지 렌더링에 대해 효과적으로 할 수 있는 옵션이 없었다.
예를 들면, css 와 jpg 가 전달되는 과정에서 css 가 느리게 전달되는 경우 페이지 렌더링에 지연이 발생된다.
따라서 페이지의 스타일을 정의한 css 가 먼저 처리될 수 있도록 우선순위를 HTTP/2에서는 정의할 수 있는데 이 기능을 Stream Prioritization 이라고 한다.
아래 그림과 같이 페이지를 구성하는 요소가 html, css, jpg, js 가 있다고 가정하면 이에 대한 우선순위를 부여하여 먼저 전송처리 될 수 있도록 하는 기능이다.
#5. 보안 통신 (HTTPS)
HTTP/2 는 평문 통신과 보안(TLS) 통신을 모두 지원하고 있고 이를 표현하는 방법은 다음과 같이 구분하고 있다.
- h2 : HTTP/2 + TLS
- h2c : HTTP/2
하지만 구글이나 네이버등 유명 홈페이지에 접속해 보면 HTTP/2 가 기본적으로 적용된 것을 볼 수 있으며, 보안 접속을 기본으로 하고 있음을 알 수 있다.
따라서 HTTP/2 는 보안 접속을 기본으로 한다고 이해하는 것이 좋다.
이처럼 HTTP/2 는 HTTP/1.1 프로토콜에서 극복하기 어려운 처리 속도 지연 (latency) 에 대한 구조적 문제를 크게 해결하였다.
그러면서도 동시에 HTTPS 의 보안 통신 채널을 통해 안전한 데이터 전송을 보장한다.
흔히 보안과 처리 속도는 반비례 관계에 있다고 알고 있을 것이다.
보안 수준을 높히면 속도가 느려지고 반대로 속도를 개선하려면 보안 수준을 낮추어야 했다.
HTTP/2 는 보안과 속도 라는 어찌보면 2마리의 토끼를 한번에 잡은 훌륭한 프로토콜인 셈이다.
마지막으로 HTTP/1.1 과 HTTP/2 의 응답 속도 차이를 담은 테스트 영상을 통해 보안 통신을 하면서도 속도 개선이 얼마나 빨라졌는지 체감해 보도록 하자.
CASE I
- 사용자와 웹서버간 RTT : 1ms
- 이미지 개수 : 900개 ( 하나의 이미지를 900개로 나눔 )
- 사용자와 웹서버간 RTT : 500ms
- 이미지 개수 : 900개 ( 하나의 이미지를 900개로 나눔 )