나만 모르고 있던 – HTTP/2

자그마치 15년여의 시간을 웹 통신 프로토콜의 절대권좌의 자리에 올라 꿋꿋이 버텨오신 당신의 똥고집에 세삼 존경심 마져 듭니다.

하지만 이제 그 자리를 내려 놓으셔야 겠습니다. 드디어 우리에겐 당신의 불편함과 느림을 대체할 새로운 분이 찾아 오셨거든요~

HTTP(HyperText Transfer Protocol)/1.1
굿바이~ 그 동안 수고 많으셨습니다!

HTTP는 1996년 처음 1.0버전이 release되고 1999년 현재 우리가 공식적으로 가장 많이 사용하고 지원하는 버전인 1.1이 출시된 이후 15년동안 발전없이 사용되고 있다.

현재의 웹은 다량의 멀티미디어 리소스를 처리 해야하고 웹페이지 하나를 구성하기 위해 다수의 비동기 요청이 발생되고 있고 이를 처리하기엔 HTTP1.1 스펙은 너무 느리고 비효율적이다.
특히 요즘과 같은 모바일 환경에선 더욱더 HTTP1.1의 스펙은 거지같다. 🙁

자 그럼 HTTP/1.1의 동작방식에 대해 알아보자.

HTTP/1.1 동작방식

이 글을 읽은 대 다수의 분들이 잘 알고 있다시피 HTTP는 웹상에서 Client ( Internet Explorer, Chrome, Firefox) 와 Server ( 웹서버 eg: httpd, nginx, etc…)간 통신을 위한 Protocol이다.

HTTP 1.1 프로토콜은 클라이언트와 서버간 통신을 위해 다음과 같은 과정을 거치게 된다.
http1_connection

너무 간단해서 설명할것도 없다. HTTP/1.1는 기본적으로 Connection당 하나의 요청을 처리 하도록 설계 되어있다. 그래서 위 그림과 같이 동시전송이 불가능하고 요청과 응답이 순차적으로 이루어 지게된다.
그렇다 보니 HTTP문서안에 포함된 다수의 리소스 (Images, CSS, Script)를 처리하려면 요청할 리소스 개수에 비례해서 Latency(대기 시간)는 길어지게 된다.

HTTP1.1의 단점을 좀 더 알아보자.

HOL (Head Of Line) Blocking – 특정 응답의 지연

Web환경에서 HOLB는 실제로 두 종류가 존재한다.

  • HTTP의 HOL Blocking
  • TCP의 HOL Blocking

우리의 관심은 HTTP의 HOLB이고 이에 대해 알아보자
– TCP의 HOLB는 개념적으로 HTTP의 HOLB 비슷하지만 실체는 다르므로 자세한건 직접 찾아 보길 권함. 🙂

HTTP/1.1의 connection당 하나의 요청처리를 개선할 수 있는 기법중 pipelining이 존재하는데 이것은 하나의 Connection을 통해서 다수개의 파일을 요청/응답 받을 수 있는 기법을 말하는데 이 기법을 통해서 어느정도의 성능 향상을 꾀 할 수 있으나 큰 문제점이 하나 있다.
하나의 TCP연결에서 3개의 이미지(a.png, b.png, c.png)를 얻을려고 하는경우 HTTP의 요청순서는 다음 그림과 같다.

순서대로 첫번째 이미지를 요청하고 응답받고 다음 이미지를 요청하게 되는데 만약 첫번째 이미지를 요청하고 응답이 지연되면 아래 그림과 같이 두,세번째 이미지는 당연히 첫번째 이미지의 응답처리가 완료되기 전까지 대기하게 되며 이와 같은 현상을 HTTP의 Head of Line Blocking 이라 부르며 파이프 라이닝의 큰 문제점 중 하나이다.

RTT( Round Trip Time ) 증가

앞서 말한것처럼 http/1.1의 경우 일반적으로 하나의 connection에 하나의 요청을 처리 한다.  이렇다 보니 매 요청별로 connection을 만들게 되고 TCP상에서 동작하는 HTTP의 특성상 3-way Handshake 가 반복적으로 일어나고 또한 불필요한 RTT증가와 네트워크 지연을 초래하여 성능을 저하 시키게 된다.

무거운 Header 구조 (특히 Cookie)

http/1.1의 헤더에는 많은 메타정보들이 저장되어져 있다.  사용자가 방문한 웹페이지는 다수의 http요청이 발생하게 되는데 이 경우 매 요청시 마다 중복된 헤더값을 전송하게 되며(별도의 domain sharding을 하지 않았을 경우) 또한 해당 domain에 설정된 cookie정보도 매 요청시 마다 헤더에 포함되어 전송되며 어쩔땐 요청을 통해서 전송하려는 값보다 헤더 값이 더 큰경우도 비일비재 하다.(심지어 User-Agent 정보 하나만 해도 대략 120Byte가 넘는다. ㅜㅜ )
즉 배보다 배꼽이 더 큰 경우도 많다는 것이다.

 

우리의 눈물겨운 노력들

우리는 이러한 http/1.1의 문제점과 비효율성을 극복하고자 눈물겨운 노력을 해왔으며 지금 이순간도 노력하고 있다.  이런 우리의 눈물겨운 노력의 대표적인 몇가지 경우를 소개해 보겠다.

Image Spriting

웹페이지를 구성하는 다양한 아이콘 이미지 파일의 요청 횟수를 줄이기 위해 아이콘을 하나의 큰 이미지로 만든다음 CSS에서 해당 이미지의 좌표 값을 지정해 표시한다.

출처: Google 검색

 

Domain Sharding

요즘 브라우저들은 http/1.1이 단점을 극복하기 다수의 Connection을 생성해서 병렬로 요청을 보내기도 한다.  하지만 브라우저 별로 Domain당 Connection개수의 제한이 존재하고 이 또한 http/1.1의 근본 해결책은 아니다.

출처: Google 검색

 

Minify CSS/Javascript

http를 통해서 전송되는 데이터의 용량을 줄이기 위해 CSS, Javascript 코드를 축소하여 적용하기도 한다.

출처: Google 검색

 

Data URI Scheme

Data URI 스킴은 HTML문서내 이미지 리소스를 Base64로 인코딩된 이미지 데이터로 직접 기술하는 방식이고 이를 통해 요청 수를 줄이기도 한다.

출처: Google검색

Load Faster

  • 스타일시트를 HTML 문서 상위에 배치
  • 스크립트를 HTML문서 하단에 배치

이런 우리의 눈물겨운 노력들도 HTTP/1.1 단점을 근본적으로 해결 할 수 는 없었고 구글은 더 빠른 Web을 실현하기 위해 throughput 관점이 아닌 Latency 관점에서 HTTP를 고속화한 SPDY(스피디) 라 불리는 새로운 프로토콜을 구현하였다. 다만 SPDY는 HTTP를 대치하는 프로토콜이 아니고 HTTP를 통한 전송을 재 정의하는 형태로 구현이 되었다.
SPDY는 실제로 HTTP/1.1에 비해 상당한 성능 향상과 효율성을 보여줬고 이는 HTTP/2 초안의 참고 규격이 되게 된다.
(구글은 SPDY 지원을 올 해 말까지만 한다고 한다. 현재 google.com, google.co.kr 은 spdy를 통해서 통신하고 있으나 이도 곧 http/2로 변경될 예정이다.)

출처 : Naver D2

 

어서오세요~ HTTP/2

자 이제 우리가 영접해야 하는 바로 그분 HTTP/2에 대해서 알아 보자. HTTP/2는 앞서 설명한것 처럼 SPDY를 기반으로 http2 작업그룹이  2012년 10월 부터 시작한 새로운 프로토콜 구현 프로젝트 이다. http2 공식 github 페이지의 서문을 보면 http2의 목적을 명확히 알 수 있다.

“HTTP/2 is a replacement for how HTTP is expressed “on the wire.” It is not a ground-up rewrite of the protocol; HTTP methods, status codes and semantics are the same, and it should be possible to use the same APIs as HTTP/1.x (possibly with some small additions) to represent the protocol.

The focus of the protocol is on performance; specifically, end-user perceived latency, network and server resource usage. One major goal is to allow the use of a single connection from browsers to a Web site.”

발번역 해보면 “HTTP/2는 HTTP가 유선상에서 표현 방법을 대치 하는것이다. 이것은 프로토콜을 완전히 다시 작성하는게 아니라 HTTP 메소드, 상태 코드 및 의미는 동일하며 프로토콜을 나타 내기 위해 HTTP/ 1.x와 동일한 API (일부 작은 추가 기능 포함)를 사용 할 수 있어야 한다. HTTP/2의 초점은 성능에 있다. 특히 최종 사용자가 대기 시간, 네트워크 및 서버 리소스 사용을 인식한다. 주요 목표 중 하나는 브라우저에서 웹 사이트로의 단일 연결을 허용하는 것입니다.” 라고 소개되어 있다.  즉 완전히 새로운 프로토콜을 만들었기 보단 성능향상에 초점을 맞춘 프로토콜 이라는것이다.

HTTP/2가 어떤 방식으로 성능을 향상 시키고 있는지 주요 요소에 대해 알아보자.

Multiplexed Streams

한 커넥션으로 동시에 여러개의 메세지를 주고 받을 있으며, 응답은 순서에 상관없이 stream으로 주고 받는다. HTTP/1.1의 Connection Keep-Alive, Pipelining의 개선이라 보면 된다.

출처 : kinsta.com

Stream Prioritization

예를 들면 클라이언트가 요청한 HTML문서안에 CSS파일 1개와 Image파일 2개가 존재하고 이를 클라이언트가 각각 요청하고 난 후 Image파일보다 CSS파일의 수신이 늦어지는 경우 브라우저의 렌더링이 늦어지는 문제가 발생하는데 HTTP/2의 경우 리소스간 의존관계(우선순위)를 설정하여 이런 문제를 해결하고 있다.

출처 : kinsta.com/

Server Push

서버는 클라이언트의 요청에 대해 요청하지도 않은 리소스를 마음대로 보내줄 수 도 있다.
무슨 소리인고 하면 클라이언트(브라우저)가 HTML문서를 요청했고 해당 HTML에 여러개의 리소스(CSS, Image…) 가 포함되어 있는경우 HTTP/1.1에서 클라이언트는 요청한 HTML문서를 수신한 후  HTML문서를 해석하면서 필요한 리소스를 재 요청하는 반면 HTTP/2에선 Server Push기법을 통해서 클라이언트가 요청하지도 않은 (HTML문서에 포함된 리소스) 리소스를 Push 해주는 방법으로 클라이언트의 요청을 최소화 해서 성능 향상을 이끌어 낸다. 이를 PUSH_PROMISE 라고 부르며 PUSH_PROMISE를 통해서 서버가 전송한 리소스에 대해선 클라이언트는 요청을 하지 않는다.

출처 : kinsta.com

 

Header Compression

HTTP/2는 Header 정보를 압축하기 위해 Header TableHuffman Encoding 기법을 사용하여 처리하는데 이를 HPACK 압축방식이라 부르며 별도의 명세서(RFC 7531)로 관리하고 있다.

출처 : Google 검색

위 그림처럼 클라이언트가 두번의 요청을 보낸다고 가정하면 HTTP/1.x의 경우 두개의 요청 Header에 중복값이 존재해도 그냥 중복 전송한다. 하지만 HTTP/2에선 Header에 중복값이 존재하는 경우 Static/Dynamic Header Table 개념을 사용하여 중복 Header를 검출하고 중복된 Header는 index값만 전송하고 중복되지 않은 Header정보의 값은  Huffman Encoding 기법으로 인코딩 처리 하여 전송한다.

출처: Google 검색

 

HTTP/1.1 과 HTTP/2 성능비교

두 프로토콜의 객관적인 성능비교 지표는 테스트 환경과 각각 테스트시 외부 인터넷 품질등의 영향으로 정확하게 알 수는 없지만, 일반적으로 HTTP/2를 사용만 해도 웹 응답 속도가 HTTP/1.1에 비해 15~50%가 향상 된다고 한다.
다음 이미지는 동일 개수/용량의 png이미지를 웹사이트에 로딩시켜 HTTP/1.1 과 HTTP/2의 속도를 비교한 결과이다.
이 테스트의 경우 둘 간의 효율성 차이가 90%이상 나기도 한다.
참으로 놀라지 않을수가 없다.
http/2

http/2 로딩 속도

http/2 로딩 속도

위 그림에선 HTTPS로 나와 있으니 이는 우리가 알고 있는 HTTPS가 아닌 HTTP/2를 말하는것이므로 오해하지 않아도 됨. 속도 테스트 사이트는 절대 모바일에선 클릭하지 마세요!
이유는 테스트 이미지 로딩시 많은 양의 데이터가 소모됨.

 

마치며

아직까지도 대 다수의 사이트(서비스)들은 HTTP/1.1만 지원하고 있다. 하지만 우리가 모르는 사이에 많은 서비스들이 이미 HTTP/2를 적용하고 있고 잘 쓰고 있다.  아무리 서버에서 HTTP/2를 지원한다고 해도 클라이언트에서 HTTP/2를 지원하지 않는 다면 사용 할 수가 없기에 아직까지 PC용 웹페이지에서 HTTP/2 사용은 미지원 클라이언트(브라우저)가 많아  한계가 있다고 생각되지만 작금의 시대는 모바일 시대가 아니던가? 우리가 일반적으로 사용하는 모바일 Device에서 구동되는 대 부분 브라우저는 HTTP/2를 지원하고 있고 ( HTTP/2 지원 브라우저 목록 ) 이는 항상 데이터 부족에 시달리는 많은 사용자들에게 보다 더 적은량으로 동일한 화면을 볼 수 있는 이득을 줄 수 있고 또한 유선망에 비해 상대적으로 느린 LET, 3G망의 사용자가에게 조금 더 나은 서비스 이용 환경을 제공 해 줄 수 있다.  그저 우리의 웹서버에 HTTP/2 지원 모듈을 설치하거나 HTTP/2를 지원하는 웹서버로의 변경을 통해서 말이다.  물론 HTTP/2 도입을 위해 새로운 웹서버로의 변경 작업은 자칫 서비스 장애로 이어질 수 있기에 신중히 판단해서 처리할 작업이겠지만,  이는 변경할 만한 충분한 가치를 가진 작업이라 생각된다.
언제까지 비효율적인 HTTP/1.1을 방치하고 있을텐가?
이미 우리가 알만한 서비스 사이트는 다 지원하고 있다.
우린 그저 모르고 지나갈뿐….

 

참고자료
https://tools.ietf.org/html/rfc7540
http://d2.naver.com/helloworld/140351
https://kinsta.com/learn/what-is-http2/