HTTP 2.0
HTTP 2.0
HTTP 2.0 이라고도 불리는 HTTP/2는 Hypertext Transfer Protocol Version 2의 약자로서, 2015년 IETF에 의해 공식적으로 발표된 HTTP/1.1(기존 표준)의 차기 버전이다.
(IETF: Internet Engineering Task Force): 국제 인터넷 표준화 기구를 의미하며, 인터넷의 운영, 관리, 개발에 대해 협의하고 프로토콜과 구조적인 사안들을 분석하는 인터넷 표준화 작업기구이다.
HTTP/2은 서버와 클라이언트 사이의 TCP 커넥션 위에서 동작한다. 이때 TCP 커넥션을 초기화하는 것은 클라이언트이다. HTTP/2 요청과 응답은 길이가 정의된(최대 16383바이트) 한 개 이상의 프레임에 담긴다. 프레임들에 담긴 요청과 응답은 스트림을 통해 보내지는데, 한 개의 스트림이 한 쌍의 요청과 응답을 처리한다. 하나의 커넥션 위에 여러개의 스트림이 동시에 만들어질 수 있으므로 여러 개의 요청과 응답을 동시에 처리하는 것이 가능하다. 또한 스트림에 대한 흐름 제어와 우선순위 부여 기능도 제공한다. 서버는 클라이언트에게 필요하다고 생각하는 리소스라면 그에 대한 요청을 명시적으로 받지 않더라도 능동적으로 클라이언트에게 보내줄 수 있다.
SPDY(스피디/speedy)
SPDY(스피디/speedy)는 Google이 개발한 비표준 네트워크 프로토콜로 웹 환경이 계속해서 변해(리소스 증가, 다수의 도메인, 동적 웹 서비스, 보안의 중요성 대두 등) 오면서 패킷 압축, Multiplexing 을 기반으로 인터넷에서의 전송 지연(latency) 문제의 해결을 집중하며 HTTP를 고속화하기 위해 새로 고안된 프로토콜이다. 초창기 크롬 브라우저에 탑재되어 높은 로딩 속도를 자랑하게 했던 구글의 자체 프로토콜이다. SPDY는 ‘speedy’라는 단어를 기반으로 Google이 만든 조어로, Google이 자신들의 ‘Make the Web Faster’ 노력의 하나로 제안한 새로운 프로토콜이다.
HTTP/2는 바로 이 SPDY 에 기반을 둔 HTTP 프로토콜 Layer 하위의 TCP 통신 레이어에 새로운 Binary 계층을 도입하여 HTTP 의 기반이 되는 TCP 연결의 호율성을 추구하였다.
SPDY는 실제로 HTTP/1.1에 비해 상당한 성능 향상과 효율성을 보여줬고 이는 HTTP/2 초안의 참고 규격이 되었다.
SPDY의 특징을 정리하면 아래와 같은데, 개념적인 설명은 HTTP/2와 겹치는 부분이 많으니 HTTP/2에서 더 자세하게 설명하도록 하겠다.
- 항상 TLS 위에서 동작
- HTTPS로 작성된 웹 사이트만 적용 가능하다.
- HTTP 헤더 압축
- 요청이 많아질 수록 압축률은 커지고, 대역폭이 작은 모바일 환경에서 효과가 크게 보인다.
- 텍스트가 아닌 바이너리 프로토콜
- 파싱이 더 빠르고, 오류 발생 가능성이 낮다.
- Multiplexing
- 하나의 커넥션 안에서 다수의 독립적인 스트림을 동시에 처리한다.
- Full-duplex interleaving & Prioritization
- 다른 스트림이 끼어드는(interleaving) 것을 허용한다.
- Server Push 결국, SPDY는 HTTP의 데이터 전송 포맷과 커넥션 관리 부분을 고쳐서 TCP 커넥션을 보다 효율적으로 쓰도록 만든 것이라고 볼 수 있다. 다시 한 번 언급하지만, SPDY은 HTTP/2의 참고 규격이 되었다. 그 만큼 비슷한 구조가 많은데, 위의 특징들의 대부분이 HTTP/2에서도 존재한다.
주요 특징
주요 특징들은 성능 향상을 목적으로 아래와 같은 특징을 가진다.
Packet Capsulation - 패킷 캡슐화
HTTP/2 의 패킷들은 더 작은 단위로 캡슐화(Capsulation)가 되면서 Frame과 Message, Stream 이라는 개념이 도입된다.
- Frame
- HTTP/2 의 통신 최소 단위로 모든 패킷에는 하나의 Frame Header가 포함된다.
- 이 Frame Header는 최소한으로 Frame이 속하는 스트림을 식별한다.
- HEADERS Type Frame, DATA Type Frame이 존재한다.
- Message
- 논리적 요청 또는 응답 메시지에 매핑되는 프레임의 전체 시퀀스 데이터를 말한다.
- Stream
- 연결의 흐름을 의미하며 구성된 연결 내에서 전달되는 바이트의 양방향 흐름, 하나 이상의 메시지가 전달 가능하다.
HTTP/2 의 모든 연결은 TCP 기반의 Stream 이며 양방향으로 Frame Header 를 지닌 Message 들을 통신한다.
데이터는 Binary 인코딩된 데이터들이며 Multiplexing 과 성능 최적화 알고리즘들이 적용된다.
Request multiplexing - 병렬 요청
HTTP/2는 하나의 TCP 연결을 통해 병렬로 여러 데이터 요청을 전송 받을 수 있다.
스트림은 HTTP/2 커넥션을 통해 클라이언트와 서버 사이에서 교환되는 프레임들의 독립된 양방향 시퀀스이다. 한 쌍의 HTTP 요청과 응답은 하나의 스트림을 통해 이루어진다. 클라이언트는 새 스트림을 만들어 HTTP 요청을 보내고, 이 요청을 받은 서버가 그 요청과 같은 스트림으로 응답을 보내고 나면 스트림이 닫히게 된다.
기존 HTTP/1.x에서는 한 TCP 커넥션을 통해 요청을 보냈을때 그에 대한 응답이 도착하고 나서야 같은 TCP 커넥션으로 요청을 보낼 수 있었다. 그러나, HTTP/2에서는 하나의 커넥션에 여러 개의 스트림이 동시에 열릴 수 있게 되어 여러개의 요청이 동시에 보내질 수 있게 되었다.
이는 한 서버에서 비동기적으로 웹 파일을 다운로드할 수 있게 해주기 때문에 HTTP/2 프로토콜의 가장 진보된 기능이다. 대부분의 최신 브라우저는 TCP 연결을 하나의 서버로 제한한다.
이는 추가 RTT(왕복 시간)를 줄여 최적화 없이 웹사이트를 더 빠르게 로드하고 도메인 샤딩을 불필요하게 만든다.
Header Compression - 헤더 압축
기존 HTTP/1.1 까지의 HTTP 헤더는 아무런 압축 없이 그대로 전송되었다. 과거에는 웹 페이지 하나를 방문했을 때의 요청이 지금처럼 많지 않았지만, 최근 웹들을 무수히 많은 요청을 보내는 형태로 변화했고 그만큼 헤더의 크기가 회전 지연과 대역폭 양쪽 모두에 영향을 끼치게 되었다.
그래서 HTTP/2에서는 HTTP 메시지의 헤더를 압축 및 중복되는 필드를 재전송하지 않도록 변경되었다.
- 기존에 HTTP Header가 Plain Text(평문)이었지만, HTTP/2에서는 허프만 코딩(Huffman coding)을 사용하는 HPACK이라는 Header 압축방식을 이용하여 데이터 전송 효율을 높였다.
- ‘헤더 블록 조각’들로 쪼개져서 전송하여, 수신 측에서 이 조각들을 이은뒤 압축을 풀어 원래의 헤더 집합으로 복원한다.
허프만 코딩(Huffman coding): 데이터 문자의 빈도 수에 따라서 다른 길이의 부호를 사용하는 알고리즘이다.
Binary protocol - 바이너리 프로토콜
최신 HTTP 버전은 텍스트 프로토콜에서 바이너리 프로토콜으로의 변환로 기능 및 속성 측면에서 크게 발전하였다. HTTP/1.x는 요청-응답 주기를 완료하기 위해 텍스트 명령을 처리하는데 사용되었지만, HTTP/2는 바이너리 명령(1과 0)을 사용하여 동일한 작업을 실행한다. 이 속성은 frame과 관련된 복잡성을 완화하고, 텍스트 및 선택적 공백이 포함된 명령으로 인해 혼란스럽게 혼합된 명령의 구현을 단순화 하였다.
HTTP/2 구현을 사용하는 브라우저는 네트워크를 통해 전송하기 전에 동일한 텍스트 명령을 바이너리로 변환한다.
바이너리 프로토콜의 이점
- 데이터의 파싱이 더 빠르고, 오류 발생 가능성이 낮다.
- 네트워크 리소스의 효과적 사용할 수 있다.
- 네트워크 지연 시간을 줄이고 처리량을 개선된다.
- 텍스트 특성과 관련된 보안 문제를 해결된다.
- 예) Response Splitting Attacks
- HTTP/2의 다른 기능을 활성화 수 있다.
- 압축, 멀티플렉싱, 우선 순위 지정, 흐름 제어 및 TLS의 효과적인 처리 등
Server Push - 서버 푸시
HTTP/2은 서버가 하나의 요청에 대해 클라이언트가 요청 하지 않은 JavaScript, CSS, Font, 이미지 파일 등과 같이 필요하게 될 특정 파일들을 서버에서 단일 HTTP 요청 응답 시 함께 전송할 수 있다.
이 기능은 서버가 클라이언트에서 어떤 리소스를 요구할 것인지 미리 알 수 있는 상황에서 유용하다. HTML 문서를 요청받은 서버가 그 HTML 문서가 링크하고 있는 이미지, CSS 파일 등의 리소스를 클라이언트에게 푸시할 수 있다. 이는 클라이언트가 HTML 문서를 파싱해서 필요한 리소스를 다시 요청하여 발생하게 되는 트래픽과 회전 지연을 줄여준다.
서버 푸시의 이점
- 클라이언트는 푸시된 리소스를 캐시에 저장한다.
- 캐시된 리소스를 여러 페이지에 걸쳐 재사용할 수 있다.
- 서버는 멀티플렉싱으로 요청한 정보와 함께 푸시된 리소스를 전송 가능하다.
- 서버는 푸시되는 리소스의 우선 순위를 지정할 수 있다.
- 클라이언트의 선택적 리소스 관리할 수 이다.
- 푸시된 리소스를 거부하거나 서버 푸시를 비활성화할 수 있다.
- 클라이언트가 멀티플렉싱되는 푸시 스트림 수 제한 가능하다.
Stream Prioritization - 스트림 우선순위
스트림은 우선순위를 가질 수 있다. 즉, 클라이언트가 선호하는 응답 수신 방식을 지정해서 응답을 받을 수 있다.
문서 내에 CSS 파일 1개와 이미지 파일 2개가 존재하고 이를 클라이언트가 요청한다고 가정해 보자. 이미지 파일보다 CSS 파일의 수신이 늦어진다면 브라우저 렌더링에 문제가 생기게 될 수 있는데, HTTP/2에서는 이러한 상황을 고려하여 리소스 간의 의존관계에 따른 우선순위를 설정하여 리소스 로드 문제를 해결할 수 있다.
그리고 모든 스트림은 고유한 식별자를 갖는다. 커넥션에서 한번 사용한 스트림 식별자는 다시 사용할 수 없다.
참조
- HTTP2 | Github
- Introduction to HTTP/2
- HTTP/2: the difference between HTTP/1.1, benefits and how to use it