우클릭방지

글 목록

2021년 7월 23일 금요일

[HTTP]HTTP/2 소개 - HTTP/1.1 제약 사항 (HTTP/2 등장 배경)

HTTP/2 가 출현하게 된 배경에 대해서 정리해 보기로 한다. 

HTTP/1.1은 1997년부터 2015년까지 오랜 시간 동안 많은 사랑을 받아온 프로토콜이다. 

하지만 복잡해지고 다양해지는 최근 웹어플리케이션들의 응답 속도를 개선하기에는 부족한 점이 몇가지가 있고, 이를 프로토콜 자체적으로 개선하기 힘들어 지게 된다. 


#1. PIPELINING 제약 사항

PIPELINING 은 여러개의 요청을 응답 여부에 상관없이 서버로 전달할 수 있는 기능이다. 
(PIPELINING 에 대한 자세한 설명은 여기 를 클릭하여 확인할 수 있다.)
RTT 감소 할 수 있는 획기적인 기술이지만, 아래와 같이 2가지 측면에서 실제 환경에 적용하기 어렵다. 

실제 환경 구현의 복잡성

PIPELINING 이 잘 동작하려면, 클라이언의 요청 순으로 서버의 응답이 처리되어야 한다. 
HTTP는 stateless 프로토콜이기 때문에 서버가 요청 순으로 응답을 처리해서 돌려주지 않으면 클라이언트에서는 이를 각 요청에 대한 올바른 응답으로 매칭 하기가 어렵다. 
즉, 아래와 같이 PIPELINING 요청이 있을 때, 요청 순대로 응답이 전달되어야만 한다는 이야기 이다. 

만약, 서버의 처리 지연 등과 같은 알 수 없는 문제로, 또는 중간 네트워크 장비의 라우팅 홉의 변경 등과 같은 네트워크적 요소로 인해 응답 순서가 바뀔 경우에는 이를 클라이언트는 올바르게 교정할 수 있는 방법이 존재하지 않는다.

PIPELINING 은 순서 바뀜(out-of-order)이 없는 어찌 보면 이상적인 환경에서나 쓸 수 있는 기능이 아닌가 싶다. 

추가적으로 이상적인 환경이라 할지라도 웹애플리케이션 접속 경로 상 존재할 수 있는 프록시 제품들도 PIPELINING 기능을 모두 지원해야 한다. 중간 프록시 장비가 PIPELINING 을 지원하지 않는다면 클라이언트가 전달한 다중 요청이 서버로 전달되지 못하기 때문이다. 
이렇게 되면 궁극적으로는 PIPELINING에 의한 RTT 감소 효과를 기대하기 어렵다. 

성능 이슈

클라이언트와 서버 모두 PIPELINING을 잘 지원한다고 하더라도 HOLB (head of line blocking) 때문에 응답 속도에 지연이 발생될 수 있다. 

HTTP는 stateless 프로토콜이어서 요청 순서대로 처리가 진행되어야 한다. 
어떤 이유로 인해 선행 요청의 처리가 지연되면 후행 응답이 먼저 전달된다고 하더라도 선행 요청의 처리가 완료 될 때까지 처리되지 못하고 대기해야 한다. 

(HOLB 에 대해서는 여기 를 클릭하면 상세한 내용을 확인할 수 있다. )

위에서 설명한 이유들로 인해 아래와 같이 대부분의 브라우저들이 PIPELINING 기능을 지원하지 않거나, 지원한다고 해도 기본적으로 비활성화(disable) 되어 있다.


[출처 : https://en.wikipedia.org/wiki/HTTP_pipelining]


#2. Domain Sharding 제약 사항

PIPELINING 의 현실적 적용의 어려움으로 인해 나온 대안이 바로 Domain Sharding 이다. 

Domain Sharding 은 아래 그림으로 이해하면 쉽다. 



Without Domain Sharding

모든 컨텐츠를 단일 도메인에서 서비스하는 경우이다. 

  • 웹서비스 도메인 : www.example.com 
  • css,js,img 제공 도메인 : www.example.com
With Domain Sharding

www.example.com 의 홈페이지에 사용되는 컨텐츠 별로 아래와 같이 구분한다.
  • 웹서비스 도메인 : www.example.com
  • css 제공 도메인 : css.example.com
  • js 제공 도메인 : js.example.com
  • img 제공 도메인 : img.example.com

HTTP 는 선행 요청이 잘 전달되어야만 후행 요청이 정상적으로 처리된다. 때문에 위와 같이 3개의 컨텐츠(style.css, script.js, img.jpg)를 전달 받기 위해서는 단일 TCP 커넥션으로는 RTT(round trip time) 가 요청 갯수 만큼 늘어나게 된다. 

하나의 웹서비스 도메인을 컨텐츠별로 위와 같이 나눈다면 도메인별로 TCP 세션이 각기 맺어지게 되므로 RTT를 획기적으로 줄일 수 있다. 

Domain Sharding 의 이런 장점을 기반으로 도메인을 많이 나누게 되면 어떻게 될까?
막연히 좋기만 할까? 답은 "그렇지 않다" 이다. 
도메인은 DNS Lookup 과 연관이 된다. 도메인이 많으면 DNS Lookup 을 많이 수행해야 하고 사용되는 도메인들의 커넥션 또한 서비스를 위해 안정적으로 유지하여야 한다. 

야후에서 연구한 바에 따르면 하나의 서비스에 대해 2~4개 정도의 도메인을 운영하는 것이 적당하고, 그 이상이 될 경우에는 성능에 저하를 초래하게 된다고 한다. 

[ 출처 : https://blog.stackpath.com/glossary-domain-sharding/ ]


#3. 프로토콜 자체의 오버헤드

클라이언트와 서버간 통신할 때 HTTP 헤더와 쿠키 정보가 포함된다. 

HTTP 헤더와 쿠키는 웹(WEB)을 발전시키는데 큰 역할을 한 요소임에 틀림없으나 요청/응답마다 동일한 헤더 정보가 반복되어 포함되는 것은 큰 고민거리였다. 

아래는 네이트 홈페이지 접속 시 전달되는 2개의 요청 헤더이다. 


붉은색으로 표시한 부분들이 동일한 내용의 HTTP 요청 헤더 내용이다. 
위에서는 요청에 대한 내용만 정리했으나 응답도 마찬가지이다.

이러한 동일한 내용이 반복되는 헤더와 쿠키 정보는 별도의 압축이나 인코딩 과정이 없기 때문에 전달되는 패킷의 사이즈를 키운다. 
패킷의 사이즈가 커지면 네트워크 대역폭(bandwidth)를 키우게 되고, 이는 pps (packets per second) 를 높여 네트워크 장비의 부담을 높힌다. 
이는 결국 latency 증가로 이어질 수 밖에 없다. 

크게 위 3가지 내용들이 긴 시간 사랑을 받아온 HTTP/1.1을 물러나게 하고 HTTP/2 를 등장 시킨 배경이라 할 수 있다. 

끝~