2017년 캘리포니아주 산호세에서 열린 O’Reilly Fluent 컨퍼런스에 참석한 일이 있습니다. 당시 귀국하는 길 비행기에서 작성했던 노트입니다. HTTP2를 사용하면 보다 빠른 자원 로딩이 가능합니다. PWA의 Fast 컨셉과 잘 어울리는 요소입니다.

HTTP2(H2)는 어떤 일을 하는거야?

full request / response multiplexing 으로 latency 를 줄이며 HTTP 헤더에 대한 효율적인 압축으로 프로토콜 전송과 관련된 비용을 최소화한다. 더불어 request 우선순위 기능과 server push를 지원한다.

메커니즘

HTTP 시멘틱을 수정하지는 않는다. (HTTP method, status code, URI, header field 등) 대신 서버와 클라이언트간의 전송 방식이나 데이터 구성을 변경한다. (모든 어플리케이션은 변경없이 h2를 적용 가능함. Good News!)

성능

request prioritization, flow control, server push같은 기능은 본질적으로 로딩 성능 향상에 큰 기여를 하고 있다. 또한 내부적으로 Framing Layer을 두었는데 유저는 기존 코드에 변경이 없다. (web server를 쓰던, raw TCP 컨트롤을 하고 있던 아무 상관없다.)

Google의 SPDY 프로토콜 - HTTP2의 시작

2009년 발표되고 개발된 (현재 사용중인!) 실험적인 프로토콜. HTTP/1.1 의 제약사항을 개선하여 다음의 목적을 두고 개발하였음.

  • PLT(page load time) 50%감소
  • Website 코드에는 어떠한 변경도 없음
  • 네트워크 인프라에 상관없이 개발 복잡성을 최소화함
  • 오픈 소스 커뮤니티와 협업
  • 실험 기능을 검증할 성능 데이터를 취합

50%의 PLT 향상을 위해 TCP connection을 더 효율적으로 사용하고자 했는데, Binary Framing Layer를 두었고 request/response multiplexing과 우선순위 기능, 헤더 압축을 제공

Twitter, Google, Facebook 등이 사용을 시작하였고 표준화로 진행함 -> HTTP Working Group에서 2015 5월 HTTP/2 & HPACK RFC’s 발표

2016 년 Google은 SPDY 와 NPN (TLS Extension)에 대한 사용 중단을 권고하였고 HTTP/2 와 ALPN으로 전환하기를 강력 권장

다시 HTTP/1.x 에 대해서 이야기하자면

HTTP/1.x 는 구현의 단순성을 제공했는데, 이는 성능에 일정부분 비용을 발생시킴. 예를 들어 동시성과 지연을 줄이기 위해 multiple connection 을 사용 (그럼에도 connection 의 비용 때문에 완벽히 concurrency 를 제공하지 못 함. 크롬 디버깅에서 확인 가능), request/response 헤더에 대한 압축도 제공하지 않기 때문에 네트워크 트래픽이 증가하는 결과를 만듬.

큰 치명적인 결점은 아니지만 웹 앱의 복잡성과 범위가 확장되는 요즘 성능 문제는 웹을 개발하는 개발자와 사용자인 유저에게 성능 문제를 일으킴.

SPDY는 deprecated되었으며 HTTP2는 표준 스펙이 되었다. 각 서버의 가이드를 참조하면 된다.

결론

Multiplexing을 통한 Binary Framing(Binary압축과 Streaming)은 더 적은 connection 으로 동시에 많은 일을 할 수 있게 함. -> 빠른 응답

중요한 포인트 HTTP/2 는 확장개념이다. HTTP1/1.x 의 HTTP 표준을 변경하지 않았고 이는 H2 의 범위가 아니다. -> hight level api 는 전혀 바뀌지 않음.

Raw Level은 변경이 되었다.

HTTP2 Binary Framing Layer

Application 레벨에 Binary Framing Layer만 추가 되었다. HTTP1 에서 delimiter 로 데이터를 구분했던 것과 다르게 데이터를 binary로 바꾸고 frame 조각으로 나누어서 전송한다. 어쨌든 server와 client(browser)는 binary format data(via HTTP/2 protocol)를 알아야한다. (우리의 어플리케이션은 몰라도 된다!)

H2에서 사용하는 용어에 대해서

Stream

연결된 커넥션 사이에서 바이트의 양방향 흐름. 하나 또는 하나 이상의 message를 전송함

Message

프레임들의 완성된 배열. Request/Response의 논리적인 배열이라고 보면 된다.

Frame

HTTP/2 통신에서 가장 작은 단위의 유닛. 각각의 frame 은 헤더를 포함하고 있음. 헤더는 현재 전송되는 프레임이 어디에 포함되는 것인지 알려주는 최소 단위.

HTTP2 Frame

Request & Response Multiplexing에 대해서

HTTP/2 는 HTTP 요청을 프레임들로 나누고 이 프레임들은 메세지에 매핑된다. 그리고 메세지는 특정 스트림에 속한다. 모든 요청이 하나의 Connection에 속하게 된다.(multiplexing) H2 성능 향상의 기본 개념

HTTP2 Multiplexing

H1 에서 동시에 다중의 요청을 동시에 보내려면 connection 을 여러개 맺어야 한다. 그러면 각각의 response들은 response 큐에 담기게 되고 head-of-line blocking이나 connection 증가로 성능 저하가 발생하게 된다.

H1에서는 커넥션을 최대 6개까지 맺는다.

HTTP1 Connection 비용

H1에서는 요청마다 하나의 커넥션을 맺는다. 그 결과..

  1. h1에서는 74%의 요청이 하나의 커넥션에서 하나의 트렌잭션만 처리함
  2. h2에서는 25%의 요청이 하나의 커넥션에서 하나의 트렌젝션만 처리함

H2 Multiplexing은 다음과 같은 효과가 있다.

  • 여러개의 응답을 블록킹 없이 응답들 사이에 끼워넣을 수 있음
  • 단일 연결로 여러개의 요청/응답을 전달할 수 있음!
  • H1 에서 했던 불필요한 성능 향상 작업들을 제거 가능! 파일 쪼개기, 이미지 스프라이트, 도메인 샤딩 등
  • Network 캐퍼시티의 사용성을 높임. 불필요한 지연을 제거하여 PLT를 최소화함
  • 등등등

H2는 latency만 줄여주는게 아니라 결국 네트워크를 효율적으로 사용할 수 있게 하고 그 결과 네트워크 비용을 줄여준다.(특히 클라우드 시스템을 이용한다면 비용과 직결된다.)

HTTPs을 사용하는 경우 TLS 핸드쉐이크 비용을 줄여준다. 세션 재활용성을 높이고 서버/클라이언트의 전반적인 자원 요청 트래픽을 낮춰준다.

Stream Prioritization

  • 각각의 스트림은 1-256 까지의 가중치를 갖음
  • 하나의 스트림은 다른 스트림에게 명확한 의존성을 갖음

HTTP2 Stream Prioritization

Root부터 가중치에 따라 공평하게 분배받음. 1의 경우 A 가 2/3, B가 1/3 만큼 할당받음

Stream Dependency 와 Weight 은 transport preference 에 불과함. 그렇기 때문에 client 는 server에게 특정 순서대로 요청을 처리하도록 강제할 수는 없음. 직관적이지 않게 느껴지겠지만 이는 높은 우선순위의 요청 때문에 server가 블록킹 되는 경우라도 낮은 요청의 자원도 서버에서 처리되도록 하기 위함이다.

H2에서 Browser Request Prioritization

최신 브라우저들은 자원(또는 asset)의 종류, 페이지가 로드된 위치 그리고 이전 페이지 방문에서 학습한 결과에 따라 자원 요청의 우선순위를 결정한다.

단점은 없는거야?

  • HTTP level에서 head-of-line 현상은 줄였지만 TCP level에서는 여전히 존재
  • Effects of bandwidth-delay product may limit connection throughput if TCP window scaling is disabled.
  • When packet loss occurs, the TCP congestion window size is reduced8, which reduces the maximum throughput of the entire connection.

그럼에도 장점이 더 많다. 일부 패킷 로스에 대한 우려보다는 싱글 커넥션에서의 압축과 우선순위의 장점이 더 크다. -> TCP 레벨에서 최적화와 튜닝이 필요함. H2는 UDP라던지 다른 transport layer를 사용할 수 있는 가능성을 갖고 있음

그 외 컨셉들

Flow Control

클라이언트가 video 스트리밍 같은 요청을 서버에 보내면서 동시에 다른 여러 요청을 보낸다고 하면 분명 서버에는 과부하가 걸림. 이를 방지하는 것. TCP 레벨에서 이미 flow control이 수행되고 있지만 여전히 HTTP 레벨에서도 컨트롤이 필요하다. 하지만 H2 레벨에서는 flow control에 대한 구현을 제공하지 않음. client/server에 책임을 미룬다. 자원 사용과 할당과 관련된 통제를 client와 server 에서 구현해야 한다.

Server Push

서버 푸시가 가능하다!! client polling이제 그만!

HTTP2 Server Push

사실 HTML 에 script나 style을 정의하는 행위 자체가 서버가 클라이언트에 데이터를 전달해주는 서버 푸시다. 서버는 클라이언트가 무엇을 필요로 하는지 보통 알고 있다. ‘미리 전달해주면 어떨까?’가 서버 푸시 개념의 시작이다.

서버 푸시는 서비스 워커(Service Worker)의 캐시 기능과 결합하면 더욱 강력해진다. 이는 ‘‘즉시 모든 자원을 로딩’을 가능하게 한다.

Header Compression

H1에서 요청별로 보내는 헤더의 크기는 500-800바이트. 쿠키를 실어 보내면 보통 1kb가 넘는다. H2는 헤더 오버헤드를 줄이기 위해 HPACK으로 압축한 포맷을 전송한다.

원래 zlib 을 이용해서 압축했고 85%-88%의 사이즈를 줄였으나, SDPY와 TLS compression 알고리즘에 대한 해킹 시도가 있어서 HPACK으로 변경. 쓸만하다고 한다.

HTTP/2로 업그레이드 하기

최신 브라우저는 HTTP2를 지원한다. 하지만 여전히 오래된 브라우저를 사용하는 유저가 있고 또 서버도 오래된 것들이 많다. 이런 부분은 해결에 오래 걸릴 것으로 보인다. 어쨌든 앞으로 서버는 H1/H2를 동시에 지원해야한다. 다음 요소는 서버에 구현되어야한다.

  • TLS와 ALPN을 통한 안전한 연결을 고려해야함
  • HTTP1 요청을 처리해야한다. (클라이언트에서 무언가 따로 알아야할 것은 없어야 한다.)
  • HTTP2 요청을 처리해야한다. (클라이언트에서 무언가 따로 알아야할 것은 없어야 한다.)

H2 에서 TLS사용을 강제하는 건 아니지만 가장 안전한 방법임. TLS & ALPN 이 권장됨. TLS/ALPN을 사용한다고 해도 H2에서는 추가적인 지연이나 round-trip (handshaking을 위한 round trip)이 발생하면 안 된다.

요약

변경없이 우리의 어플리케이션을 H2로 업그레이드 할 수 있다. HTTP 의 시맨틱 그리고 핵심 기능에 아무 변경이 없다. 더불어 Server Push라던지 cache 등을 통해 어플리케이션을 최적화할 수 있다.

Reference

O’Reilly Fluent 2017
Learning HTTP/2 - A Practical Guide for Beginners By Stephen Ludin, Javier Garza, O’Reilly Media