IT_etc/유용한 전산 지식들..

[펌] SPDY는 무엇인가?

JJun ™ 2015. 9. 14. 11:32



 출처

 : http://d2.naver.com/helloworld/140351

 : http://www.dreamy.pe.kr/zbxe/CodeClip/157076



최근 Google의 SPDY 프로토콜을 Facebook에서도 지지하며 Facebook도 SPDY 구현을 시작했다는 기사가 발표됐습니다.
웹 속도를 빠르게 하기 위해 다양한 방법을 고안하고 제시하는 Google의 노력 중에서, 새로운 산업 표준을 만들 정도로
가장 빛을 보고 있는 것이 바로 SPDY가 아닐까 싶은데요. SPDY는 HTTP 2.0에 포함될 예정입니다.

SPDY는 'speedy'라는 단어를 기반으로 Google이 만든 조어로, Google이 자신들의 'Make the Web Faster' 노력의 하나로
제안한 새로운 프로토콜입니다. 이는 초창기 인터넷 환경에서 고안된 HTTP의 단점들을 보완하여,
지금과 앞으로의 인터넷 환경을 보다 효율적으로 이용할 수 있는 프로토콜로 제안된 것입니다.

이 글에서는 SPDY의 기능과 장점을 간단히 소개하고, SPDY 지원 현황을 살펴 본 후,
SPDY 도입 시의 고려 사항에 대해 살펴보도록 하겠습니다.


너무 오래 버전 업이 없었던 HTTP

HTTP는 1991년에 0.9 버전이 처음 발표되었고, 1996년에 1.0 버전, 1999년에 1.1 버전이 나온 뒤로 10년이 넘는 시간 동안
전혀 변화가 없었다. 그러나 오늘 날의 웹 페이지는 1990년대의 웹 페이지에 비하여 그 규모와 페이지당 HTTP 요청 개수가
20배 가량 증가했다. 표 1은 Google I/O 2012에서 Google이 발표한 자료에서 발췌한 것이다.

표 1 2010년과 2012년의 평균 웹 페이지 규모 비교

 평균 페이지 크기페이지당 평균 요청 개수평균 도메인 개수
2010년 11월 15일702KB7410
2012년 5월 15일1059KB8412

1996년도의 Yahoo 메인 페이지 용량은 34KB 정도였다. 이는 2012년 평균 웹 페이지 용량의 30분 1 수준이다.

1990년대와의 비교는 물론이고, 근자인 2010년과 2012년을 비교해도 상당한 차이가 있다.
초고속 인터넷 보급과 함께 점점 더 미려한 사용자 UX 덕분에 페이지 크기와 요청 개수의 평균 값이 증가하고 있는 것이다.

이와 같이 과거에 비해 달라진 오늘날의 웹 페이지의 특징을 정리하면 다음과 같다.

  • 훨씬 더 많은 리소스로 구성되어 있다.
  • 다수의 도메인을 사용한다.
  • 과거에 비해 매우 동적으로 동작한다.
  • 보안이 보다 중요한 이슈가 되었다.

예전과 달라진 오늘 날의 웹 환경을 고려하여 Google에서는 HTTP를 보완한 SPDY 프로토콜을 발표하게 된 것이다.

이 SPDY 프로토콜은 특히 전송 지연(latency) 문제의 해결에 주로 집중하고 있다.


SPDY 특징

전통적인 TCP/IP 계층 모델과 비교하여 SPDY의 계층을 표현하면 그림 1과 같다.


그림 1 HTTP와 SPDY 비교

SPDY의 특징을 간단히 살펴보자.

  • 항상 TLS(Transport Layer Security) 위에서 동작

따라서 HTTPS로 작성된 웹 사이트만 적용 가능하다.

TLS는 SSL(Secure Sockets Layer)의 다음 버전이다.
같은 프로토콜의 예전 버전 이름과 현재 버전 이름이므로 종종 혼동되어 사용되며 
이 기사에서도 TLS와 SSL을 구별해서 사용하지는 않는다.

  • HTTP 헤더 압축

HTTP 헤더에는 요청마다 반복되는 내용이 매우 많으므로 헤더 압축만으로도 충분한 성능 향상 효과를 얻을 수 있다.
Google의 발표 자료에 따르면 HTTP 헤더 압축으로 최초 요청 시에도 10~35%의 크기를 감소시킬 수 있고,
여러 번 요청이 있을 경우에는(long-lived 커넥션) 80~97%까지 헤더 크기를 감소시킬 수 있다고 한다.
또한 모바일과 같이 업로드 대역폭이 상대적으로 작은 경우에는 이런 HTTP 헤더 압축 방법이 특히 유용하다.
오늘날의 HTTP 헤더는 평균 2KB 가량이고, 점점 더 커지는 추세이기 때문에 HTTP 헤더 압축의 가치는 앞으로는
더 커질 것이라고 보고 있다.

  • 바이너리 프로토콜

프레임을 텍스트가 아닌 바이너리로 구성하므로 파싱이 더 빠르고, 오류 발생 가능성이 낮다.

  • Multiplexing

하나의 커넥션 안에서 다수의 독립적인 스트림을 동시에 처리한다. 따라서 하나의 커넥션에서 한 번에 하나만의 요청을 처리하며, 요청에 대한 응답이 순차적으로 이뤄지는 HTTP와 달리 적은 수의 커넥션으로 다수의 요청, 응답을 동시에 처리할 수 있다. 또한 FIFO(First In, First Out)로 처리되기 때문에 하나가 지연되면 나머지 응답도 모두 지연되는 HTTP 파이프라이닝(pipelining)과는 달리, 각각의 요청, 응답이 모두 독립적으로 처리된다.

  • Full-duplex interleaving과 스트림 우선순위

한 스트림이 진행 중이더라도 다른 스트림이 끼어드는(interleaving) 것을 허용하고 스트림의 우선순위 설정도 지원하므로 
우선순위가 낮은 데이터 전송 도중에 우선순위가 높은 데이터가 끼어들어서 더 빨리 전달되게 할 수 있다.

  • Server Push

Comet, 롱 폴링(long-polling) 같은 것과는 달리 클라이언트의 요청이 없어도 서버에서 콘텐츠를 직접 push할 수 있다.
inlining 같은 방법과는 달리 리소스 캐싱이 가능하며, inlining과 같거나 더 적은 대역폭을 사용한다.
다만 server push를 구현할 때에는 웹 서버 애플리케이션 로직에 대한 추가 구현이 필요하다.

  • 웹 사이트를 재작성할 필요 없음

server push와 같이 추가 구현을 요구하는 기능을 제외하면, SPDY 적용 자체를 위해 웹 사이트 자체가 바뀌어야 할 필요는
없다. 다만 브라우저와 서버가 SPDY를 지원해야만 한다. SPDY는 브라우저 사용자에게 완전히 투명하게 적용 가능하다.
즉, spdy:// 같은 프로토콜 scheme이 없다. 또한 브라우저에서도 SPDY 프로토콜 사용 여부에 대한 어떤 표시도 하지 않는다.

이와 같은 특징들을 가지고 HTTP와 SPDY의 차이점을 표로 나타내면 다음과 같다.

표 2 HTTP(1.1)와 SPDY 비교

 HTTPSPDY
SecureNot DefaultDefault
Header CompressionNoYes
MultiplexingNoYes
Full-DuplexNoYes
PrioritizationNo(브라우저 자체 휴리스틱 사용)Yes
Server PushNoYes
DNS LookupMoreLess
ConnectionsMoreLess

(자세한 내용은 Google I/O 2012 콘퍼런스 자료 36쪽을 참조한다.)

결국, SPDY는 HTTP의 데이터 전송 포맷과 커넥션 관리 부분을 고쳐서 TCP 커넥션을 보다 효율적으로 쓰도록 만든 것이라고
볼 수 있다.

Google의 SPDY Whitepaper(http://www.chromium.org/spdy/spdy-whitepaper/) 페이지의 'Table 1: Average page load times for top 25 websites' 표를 통해 SPDY가 HTTP+SSL에 비해 39~55%의 속도 향상을 보인다는 점을 확인할 수 있다.


왜 TLS를 필요로 하는가?

TLS 사용으로 인해 암호화/복호화 작업으로 인한 전송 지연이 발생함에도, 왜 SPDY는 TLS를 사용하고 있는가?
이 질문에 대해 Google의 SPDY Whitepaper에서는 다음과 같이 이유를 밝히고 있다.

"장기적으로 보아 웹 환경에서 보안성은 점점 더 강조될 것이므로, SPDY의 하위 프로토콜로 TLS를 지정하여
향후 더 나은 보안성을 얻고자 한다. 현재 네트워크 인프라와의 호환, 즉 기존의 프록시를 거치는 통신과 호환성 문제가
발생하지 않도록 하기 위해 TLS가 필요하다."

이와 같은 이유가 있으나, 실제 SPDY의 구현을 살펴보면 TLS의 NPN(Next Protocol Negotiation) 확장 기능에 SPDY가 크게
의존하고 있음을 알 수 있다. 이 TLS NPN 확장은 서버의 443 포트로 들어온 요청이 SPDY인지 여부 및 요청에서 사용하고 있는
SPDY 버전을 판별하여 이후의 통신을 SPDY로 처리할지 판단할 수 있게 한다. 만약 TLS NPN이 없다면 SPDY 사용을 위해
추가적인 RTT(round-trip time)가 필요할 것이다.


표준화 노력

SPDY는 공개된 프로토콜로 개발되고 있으며 HTTP/2.0의 한 방식으로 IETF(Internet Engineering Task Force)에 제안되어 있다. SPDY는 Google Chromium 프로젝트의 하위 프로젝트로 Chromium 클라이언트 구현 및 서버 도구는 모두 오픈소스로 개발되고 있다.


SPDY의 미래

SPDY는 현재 draft 3까지 발표됐으며, draft 4가 제작 중이다. draft 4에서 추가될 가능성이 높은 기능은 다음과 같다.

  • Name resolution push
  • Certificate data push
  • Explicit proxy support

SPDY의 최종 목표는 하나의 페이지를 '하나의 커넥션 설정 시간 + 바이트/대역폭 시간' 내에 서비스하는 것이다.


SPDY 지원 브라우저, 서버, 라이브러리, 웹 서비스

현재 다양한 브라우저와 서버가 SPDY를 지원하고 있으며, SPDY를 제안한 Google은 이미 자사의 거의 모든 서비스를
SPDY로 제공하고 있다. 이들 SPDY 지원 브라우저, 서버, 라이브러리, 서비스 등을 정리해 본다.


SPDY 지원 브라우저

2012년 7월 현재, SPDY를 지원하는 브라우저 목록은 다음과 같다.

  • Google Chrome/Chromium

Chrome과 Chromium은 초기 버전부터 SPDY를 지원하고 있다.
다음 URI를 입력하면 현재 Chrome/Chromium에서 연결 중인 SPDY 세션을 확인할 수 있다.
chrome://net-internals/#events&q=type:SPDY_SESSION%20is:active
예를 들어 www.gmail.com에만 들어가도 여러 개의 SPDY 세션이 생성되는 것을 확인할 수 있다.
Android 용의 모바일 Chrome도 SPDY를 지원한다.

  • Firefox 11과 그 이후 버전

11 버전부터 SPDY를 지원하기는 하지만 기본 설정으로 제공하지는 않았고, 13 버전부터 기본 설정으로 제공하고 있다.
Firefox 설정을 표시하는 URI인 about:config를 입력하고 network.http.spdy.enabled 항목을 보면 SPDY 지원이 활성화됐는지
확인할 수 있다. Android용의 모바일 Firefox 14 버전도 SPDY를 지원한다.

  • Amazon Silk

Android 기반 eBook인 Kindle Fire에 탑재된 Silk 브라우저는 SPDY를 지원하고 있다.
Amazon EC2 서비스와 SPDY를 이용해 통신한다.

  • Android 3.0 이상의 기본 브라우저

Android 3.0(Honeycomb), 4.0 (Ice Cream Sandwich)의 기본 브라우저는 SPDY를 지원한다.

다음 URL에서 SPDY를 지원하는 브라우저에 대한 상세 정보를 확인할 수 있다.



SPDY 지원 서버 및 라이브러리

주요 웹 서버와 애플리케이션 서버에서 SPDY 지원을 활성화하고 있으며 SPDY를 구현한 라이브러리도 다양하게 개발되고 있다.


SPDY를 사용하는 서비스

앞서 언급한 것처럼 Google은 검색뿐만 아니라 Gmail, Google+ 등 자사의 거의 모든 서비스를 https로 전환하여 SPDY로
제공하고 있다. 또한 Google App Engine도 https를 사용하는 경우에는 SPDY를 지원한다.
Twitter도 https로 서비스를 제공하면서 SPDY를 사용하고 있다.

그러나 실제로 현재의 수많은 웹 사이트 중에서 SPDY를 사용하는 사이트는 그다지 많지 않다.
Netcraft의 2012년 5월 조사(http://news.netcraft.com/archives/2012/05/02/may-2012-web-server-survey.html) 에 의하면
총 6.6억 개의 웹 사이트 중에서 339개 만이 SPDY를 사용하고 있다고 한다.
즉, 아직은 Google과 Twitter 외에는 SPDY를 사용하는 주요 사이트는 거의 없다고 할 수 있다.


SPDY가 그다지 효율적이지 않은 경우

SPDY가 항상 빠른 것은 아니다.
상황에 따라 SPDY로 얻을 수 있는 성능 이점이 거의 없을 수도 있다.
그런 상황들을 정리하면 다음과 같다.

  • HTTP만 사용하는 경우

SPDY는 반드시 SSL을 필요로 하므로 SSL 핸드셰이크 시간이 추가적으로 필요하다.
따라서 HTTP로 개발된 사이트를 SPDY 지원을 위해 HTTPS로 변경하는 경우 SSL 핸드셰이크 처리 시간으로 인해
뚜렷하게 성능 향상이 이뤄지지 않을 수도 있다.

  • 도메인이 많은 경우

SPDY는 도메인별로 동작한다. 즉 커넥션은 도메인 개수만큼 필요하고, 요청을 multiplexing하는 기능도 하나의 도메인 안에서만 가능하다. 또한 모든 도메인이 SPDY를 지원하게 만들기 어려우므로 도메인이 많은 경우에는 SPDY의 장점이 나타나기
어려워진다. 특히 CDN에서 SPDY를 지원하지 않는 경우에는 SPDY로 인한 성능 향상을 기대하기가 어렵게 된다.

  • HTTP가 병목이 아닌 경우

모든 웹사이트에서 HTTP가 병목으로 작용하는 것이 아니다.
다른 리소스 다운로드를 먼저 해야 다음 리소스를 다운로드할 수 있게 되어 있는 등의 이유로
대부분의 페이지에서 HTTP는 병목이 아닌 경우가 많다.

  • RTT가 작은 경우

SPDY는 RTT가 큰 경우에 더 큰 효율을 얻을 수 있다.
IDC 내의 서버 간 통신처럼 RTT가 매우 작은 경우에는 이점이 별로 없다.

  • 페이지 내의 리소스가 매우 적은 경우

6개 이하의 리소스를 가지는 페이지라면 커넥션 재사용의 가치가 떨어지므로 이점이 별로 없다.


SPDY를 도입하는 경우 해야 할 일

SPDY를 최대한 효율적으로 적용하려면 다음과 같은 작업이 필요하다.


애플리케이션 레벨

  • 하나의 커넥션만 사용한다.

SPDY 성능을 위해서 그리고 효율적인 인터넷 리소스 사용을 위해서는 가능한 한 적은 수의 커넥션을 사용하는 것이 유리하다.
SPDY를 사용할 때, 적은 수의 커넥션을 사용해야 데이터를 더 나은 방법으로 패킷에 넣을 수 있고, 헤더 압축 효율이 좋아지며, 커넥션 상태를 덜 확인하고, 핸드셰이크도 적게 하는 등의 이득이 있다. 또한 인터넷 리소스 면에서는 커넥션 개수가 적어야
TCP 효율이 좋아지고 Bufferbloat 현상을 감소시킬 수 있다.

참고

Bufferbloat: 라우터나 스위치에서 패킷을 너무 오래 버퍼링하기 때문에 전체 네트워크의 전송 지연(latency)이 높아지고 처리량(throughput)도 줄어드는 현상을 말한다. 가능한 패킷을 폐기하지 않아야 한다는 인식과 계속 낮아지는 메모리 가격 때문에 라우터나 스위치의 버퍼 크기는 계속 커졌고, 이로 인해 가급적 빨리 폐기돼야 할 패킷이 더 오래 살아남게 됐다.
결국 TCP 혼잡 회피 알고리즘을 방해하여 오히려 전체 네트워크 성능이 낮아지는 결과를 만든 것이다.

  • hostname sharding을 피한다.

hostname sharding은 흔히 웹 애플리케이션에서 브라우저의 동시 다운로드 개수 제한(일반적으로 hostname당 6개)을 피하기 위해 사용하는 일종의 편법이다. 앞서 설명한 단일 커넥션 사용을 권장하는 이유 때문에 SPDY를 쓰는 경우에는 hostname sharding이 불필요하다. 더구나 hostname sharding은 추가적인 DNS 쿼리를 발생시키고, 애플리케이션을 더 복잡하게 만든다.

  • inlining 대신에 server push를 사용한다.

inlining은 웹 애플리케이션에서 RTT를 줄이기 위해 사용한다. 그러나 inlining은 웹 페이지가 보다 덜 캐시되게 하고
base64 인코딩 때문에 웹 페이지 크기를 크게 만든다. 직접 콘텐츠를 push하는 SPDY server push 기능을 사용하면
이로 인한 문제를 피할 수 있다.

  • 요청 우선순위를 사용한다.

SPDY의 기능 중에 요청 우선순위 기능을 사용해서 클라이언트가 서버에 리소스의 상대적인 우선순위를 알리도록 할 수 있다. 일반적으로 적용할 수 있는 간단한 휴리스틱 우선순위로는 'html > js, css > *'를 생각해 볼 수 있다.

  • 적절한 SPDY 프레임 크기를 사용한다.

SPDY 스펙에서 큰 크기의 프레임을 허용하지만, 때때로 작은 프레임이 바람직한 경우도 있다.
프레임이 작은 경우에 프레임 interleaving이 더 잘 동작하기 때문이다.


SSL 레벨

  • 보다 작고 완전한 인증서 체인을 사용한다.

인증서 체인의 크기는 커넥션 초기화 성능에 상당한 영향을 미친다. 인증서 체인 내의 인증서가 많을수록 인증서 유효성 검증에 더 오랜 시간이 걸리고 initcwnd 내의 공간을 더 많이 차지하게 때문이다. 또한 서버가 완전한 인증서 체인을 제공하지 않는 경우에는 클라이언트는 중간에 있는 인증서를 가져오기 위해 추가적인 RTT를 사용하게 된다. 결국 크고 불완전한 인증서 체인을 사용할수록 애플리케이션이 커넥션을 사용할 수 있게 되기까지 더 오랜 시간이 걸리게 된다.

참고

initcwnd: TCP initial congestion window, TCP 혼잡 제어 알고리즘에서 사용되는 초기값. congestion window는 TCP 혼잡 제어 알고리즘에 따라 송신 측에서 크기를 조절하는 window로서, 수신 측에서 크기를 제한하는 일반적인 TCP window와는 다르다.

  • 쓸 수 있다면 와일드카드(wildcard) 인증서(*.naver.com 같은 형태의 인증서)를 사용한다.

와일드카드 인증서를 사용할 수 있다면 커넥션 개수가 줄고, SPDY의 커넥션 공유를 사용할 수 있게 된다.
다만, 와일드카드 인증서는 인증 기관에서 제공하는 것이므로 인증 기관과의 협의 및 추가적인 비용이 발생할 수 있다.

  • SSL 쓰기 버퍼의 크기가 너무 크지 않게 설정한다.

SSL 쓰기 버퍼가 너무 크면 TLS 애플리케이션 record는 여러 개의 패킷에 걸쳐진다. 애플리케이션은 전체 TLS 애플리케이션
record가 완성되어야 처리할 수 있으므로 여러 개의 패킷에 걸쳐진 record는 추가적인 전송 지연을 유발한다.
Google 서버들은 2KB 크기의 버퍼를 사용하고 있다.


TCP 레벨

  • 서버의 initcwnd는 최소 10 이상으로 설정한다.

initcwnd는 페이지의 최초 로딩 시간에 영향을 주는 주된 병목이다. HTTP만 쓴다면 여러 개의 커넥션을 동시에 열어서 'n × initcwnd'의 초기 congestion window 크기를 달성하는 형태로 이 문제를 회피할 수 있으나, SPDY에서는 단일 커넥션이 유리하므로 처음부터 initcwnd를 크게 하는 것이 좋다. 오래된 Linux 커널은 이 값이 2~3 정도의 값으로 고정되어 있고 이를 조절할 방법을 제공하지 않고 있다. 처음 이 값을 고려할 때의 TCP 네트워크 신뢰성과 대역폭에 따라 정해진 값이므로 현대의 보다 안정적이고 높은 대역폭의 TCP 네트워크에는 적합하지 않은 값이다. 최신 Linux 배포판은 10 이상의 기본 값을 사용하고 있다.
Linux 커널 2.6.18부터 이 값을 조절할 수 있다고 알려져 있으나 실제 동작 여부는 Linux 배포판에 따라 다르므로 주의가 필요하다.

  • tcp_slow_start_after_idle 설정을 끈다.

Linux 기본 설정은 tcp_slow_start_after_idle을 1로 설정하고 있는데, 이는 커넥션이 유휴(idle) 상태가 되면
congestion window를 다시 initcwnd 크기로 떨어뜨려서 TCP Slow Start를 다시 실행하게 한다.
이는 SPDY의 단일 커넥션의 이점을 죽이는 일이므로 이 설정을 꺼야 한다.
sysctl 명령어를 이용해서 변경할 수 있다.
HTTP keepalive 사용 시에도 이 설정을 끄는 것이 유리하다.

참고

TCP Slow Start: 처음에는 initcwnd 크기의 congestion window로 패킷을 보내면서 점점 congestion window 크기를 키워
네트워크가 허용하는 최대값 혹은 수신 측의 TCP window까지 키우는 것을 TCP Slow Start라 한다. initcwnd 값이 작으면
네트워크가 허용하는 최대 크기까지 도달하는 동안 더 많은 Round-Trip이 필요하므로 페이지 최초 로딩 시간이 더 길어진다.

마치며

이상에서 살펴본 바와 같이 SPDY를 실제로 도입하기에는 다양한 고민과 애플리케이션 및 서버 수정이 필요하다.
특히 도입에 들어가는 비용을 생각하지 않을 수 없는데, SPDY를 아직 지원하지 않는 Tomcat으로 작성된 웹 애플리케이션이라면 웹 애플리케이션 서버를 바꾸는 비용을 고려해야 하며, Server Push 기능의 추가 구현에 따른 비용도 생각해야 한다.

이 같은 SPDY 도입 자체 비용을 제외하고 당장 실제 서비스에서 SPDY 도입을 시도한다면 무엇을 가장 먼저 고려해야 할까?
3가지를 꼽아 본다.

  • 이미 HTTPS를 사용하는 서비스여야 한다

HTTP만 사용하는 서비스는 SPDY의 이득이 적고, SSL 도입에 따른 추가 비용이 발생한다.

  • Linux 커널을 교체할 수 있어야 한다.

initcwnd 조절로 얻는 성능상의 차이가 크기 때문에, 가급적 initcwnd가 조절 가능하거나 10 이상의 기본 값을 가진 Linux로
교체할 수 있어야 한다. CentOS의 경우 5.6 버전까지는 initcwnd 조절이 되지 않는다. 6.1부터 조절 가능하고, 6.2부터는
기본 값 10을 가지고 있다.

  • SPDY 지원 브라우저 사용자의 비율을 고려한다.

국내 서비스에서는 아직도 SPDY를 지원하지 않는 Internet Explorer 사용자가 태반이다. 모바일에서도 iOS는 아직 SPDY를
지원하지 않으며, Android는 3.0부터 지원을 시작하고 있다. 따라서, SPDY 지원 브라우저 사용자가 충분히 많아지기 전에는
SPDY의 성능 향상으로 얻는 이익과 SPDY 도입 비용을 잘 비교해야 할 것이다.

박세훈|NBP 웹플랫폼개발랩
영화 <코드명 J>의 원작 소설 이 발표된 것은 1981년이다. 저자인 윌리엄 깁슨은 대량의 데이터를 전달하려면 사람의 두뇌를 써야 할 것이라고 생각했다. 30년이 지나 사람은 두뇌를 사용하는 대신 손톱보다 작고 훨씬 대용량인 메모리카드를 만들어냈다. IT 기술이 이렇게 빠르게 발전하고 그만큼 데이터양도 늘어나고 있지만 메모리카드와 비교도 안 되게 좁은 필자의 두뇌에는 아직도 채워야 할 내용이 많은 것 같다. 그래서 언제나 무언가를 채우기 위해 돌아다니고 두리번거리고 있다.








SPDY(스피디) : 더 빠른 웹을 위한 실험적인 프로토콜


 

이 글은 SPDY의 백서 “SPDY : An experimental protocol for a faster web“를 번역한 글입니다.


개요

“웹을 더 빠르게 하자(Let’s make the web faster)” 계획의 부분으로써 우리는 웹페이지들의 반응속도를 높일 수 있는 대안 프로토콜을 실험 중에 있다. 이러한 실험 중에 하나가 SPDY(SPeeDY-스피디라고 읽는다)인데, SPDY는 웹에서 컨텐츠 전송을 위한 애플리케이션 레이어 프로토콜이다. 이 프로토콜 명세와 더불어 우리는 SPDY를 지원하는 구글 크롬 브라우저와 오픈소스 웹서버를 만들었다. 내부 테스트를 통해 우리는 HTTP와 SPDY 위의 어플리케이션의 성능을 비교한 결과 SPDY를 사용할 때 페이지 로드 타임을 64%정도 줄일 수 있었다. 우리는 오픈 소스 커뮤니티에 아이디어, 피드백, 코드, 테스트 결과들을 기여함으로써 보다 SPDY가 빠른 웹을 위한 차세대 애플리케이션 프로토콜이 되길 바란다.


배경 : 웹 프로토콜과 웹 반응속도

현재 웹에서 사용하는 프로토콜은 HTTP와 TCP이다. TCP는 일반적이고 신뢰성있는 전송프로토콜(transport protocol)로써 전송 보증(guaranteed delivery), 중복 제거(duplicate suppression), 순서유지(in-order delivery), 흐름제어(flow control), 혼잡 회피(congestion avoidance) 등을 제공한다. HTTP는 어플리케이션 레벨 프로토콜로써 기본적인 요청/응답의 시맨틱스를 제공한다. 우리는 전송계층(transport layer)에서 반응속도를 개선할 가능성이 더 있다고 생각하지만, 최초에는 어플리케이션 레이어(HTTP) 쪽을 중점적으로 조사를 했다. 불행히도 HTTP는 반응속도에 대해 특별히 고려된 프로토콜이 아니었다. 게다가 현재 네트웍 상에서 전송되는 웹페이지들은 10년 전의 웹페이지들과는 많이 달라졌고, 이에 따라 HTTP가 개발되던 시절에 예상할 수 없었던 개선이 필요하게 됐다. 다음은 HTTP가 최적의 성능을 내는데 저해가 되는 기능들이다.

  • 커넥션 당 하나의 요청
    HTTP가 한번에 하나의 리소스만 가져올 수 있기 때문에(HTTP piplelining이 도움이 되지만 여전히 FIFO queue라는 제약이 있다), 500ms의 서버 지연시간이 다른 요청에 대해서 TCP channel의 재사용을 어렵게 한다. 그래서 브라우저들은 다수의 커넥션을 사용하여 이 문제를 우회하고 있다. 2008년 이후 대부분의 브라우저들은 결국 도메인 당 커넥션 수를 2개에서 6개로 늘렸다.

  • 클라이언트만 가능한 요청
    HTTP하에서 오직 클라이언트만 요청을 보낼 수 있다. 서버 측에서 클라이언트가 어떤 리소스가 필요하리라는 걸 알더라도 클라이언트에 알릴 메커니즘이 존재하지 않는다. 서버는 클라이언트가 요청할 때까지 기다려야만 한다.

  • 압축되지 않는 요청/응답 헤더
    요즘 요청 헤더의 크기는 200byte에서 2KB까지 다양해졌다. 어플리케이션에서 쿠키를 더 많이 사용하고, user agent의 기능이 확장됨에 따라 헤더 크기가 700~800 바이트가 되었다. 업링크 대역폭이 아주 작은 모뎀이나 ADSL 연결에서 헤더의 데이터를 줄이는 것은 요청을 보낼 때의 응답시간을 직접적으로 향상 시킬 수 있다.

  • 중복 헤더들
    같은 채널에서의 대부분의 헤더들은 모든 요청에 반복적으로 사용된다. 그러나 User-Agent, Host, Accept* 등의 헤더 값들은 고정된 값이며 일반적으로 재전송이 필요하지 않다.

  • 선택적인 데이터 압축
    HTTP는 선택적으로 데이터에 대한 압축을 사용할 수 있다. 하지만 컨텐츠는 항상 압축되어 전송되는 것이 좋다.


기존의 접근방법들

SPDY는 HTTP를 빠르게 하려는 유일한 연구는 아니다. 웹의 반응속도 개선에 대한 제안들 있었고, 그 대부분이 전송계층이나 세션계층에서의 연구였다.

Stream Control Transmission Protocol (SCTP)
TCP를 대체하는 전송계층 프로토콜로써 멀티플렉스 스트림과 스트림 기반 혼잡제어를 제공한다.
HTTP over SCTP
SCTP 위에 HTTP를 작동하자는 제안. Comparision of HTTP Over SCTP and TCP in High Delay Networks 는 두 전송프로토콜 위에서의 성능 비교 연구 결과를 보여준다.
Structured Stream Transport (SST)
“structured streams”는 일반적인 전송층 위에서 사용될 수 있는 가볍고, 독립적인 스트림을 만드는 프로토콜. 이것은 TCP를 대체하거나 UDP의 위에서 작동할 수 있다.
MUX와 SMUX
전송계층과 어플리케이션 레이어 사이에 작동하는 중간 레이어 프로토콜. 스트림의 멀티플렉싱을 지원한다. HTTP/1.1과 비슷한 시기에 제안됐다.

상기 제안들은 웹의 반응속도 문제에 대한 부분적인 해결책을 제공한다. HTTP의 압축, 우선순위 등의 고유의 문제는 여전히 남아있고, 그 아래의 전송계층과 별개의 문제다. 현실상황의 어떤 경우라도 전송계층을 변경하는 일은 매우 어렵다. 대신 우리는 어플리케이션 레이어에서의 문제들을 정리하면서 더 쉬운 해결방안 있다고 생각했다. 이 방법은 기존의 인프라스트럭쳐에 최소한의 변경만 필요로 하고, (우리 생각에는) 상당한 성능 향상을 얻어낼 수 있을 것이다.


SPDY의 목표

SPDY 프로젝트는 웹의 반응속도를 개선할 수 있는 어플리케이션 프로토콜을 정의하고 구현한다. SPDY의 상위 수준 목표는 다음과 같다.

페이지 로드 타임 50% 감소
우리의 사전작업 결과는 이 목표에 이미 근접하고 있다. (아래)
도입 복잡도를 최소화
SPDY는 전송계층으로 TCP를 사용하여 기존 네트웍 인프라스트럭쳐에 어떤 변화도 필요로 하지 않는다.
웹사이트의 컨텐츠에 변경이 필요하지 않도록 함.
SPDY는 오직 클라이언트 user agent와 웹서버만 변경하면 되도록 한다.

반응속도의 문제를 해결하기 위한 방법으로 프로토콜을 탐구하는 사람들이 함께 할 수 있도록 한다. 우리는 오픈 소스 커뮤니티와 산업계 전문가들의 협력하에서 이 새로운 프로토콜을 개발하길 원한다.

기타 기술적인 목표들은 다음과 같다.

  • 하나의 TCP 세션을 통해 다수의 HTTP요청을 동시에 수행할 수 있게 한다.
  • 헤더에 대한 압축과 불필요한 헤더를 제거함으로써 HTTP가 현재 사용중인 대역폭을 줄인다.
  • 구현하기 쉬우면서 서버측에 효율적인 프로토콜을 정의한다. 우리는 예외적인 상황들을 줄이고 파싱하기 쉬운 메시지 포맷을 정의함으로써 HTTP의 복잡도를 낮추려고 한다.
  • 전송계층 위의 SSL을 보다 보안성있고 기존 네트웍 인프라스트럭쳐에 보다 호환성이 좋게 만든다. SSL은 반응속도 측면에서는 불리하지만, 장기적인 관점에서 웹은 결국 보안 네트웍 연결에 의존하게 될 것이라 믿는다. 추가적으로 SSL의 사용이 기존의 프락시들을 통한 통신이 깨지지 않도록 보장해야 한다.
  • 서버가 클라이언트와의 통신을 시작할 수 있게 하여, 가능한 상황에서는 클라이언트에 데이터를 push해줄 수 있도록 한다.


SPDY 설계와 기능

SPDY는 SSL 위에 세션계층을 추가했다. 이것은 하나의 TCP 연결 위에서 다수의, 동시수행되는 스트림을 교차배치할 수 있게 한다.

일반적인 HTTP GET과 POST 메시지 포맷은 동일하다. 그러나 SPDY는 연결위에서 데이터를 인코딩하고 전송하는 새로운 프레이밍 포맷을 정의한다.




 

스트림들은 양방향이다. 즉, 스트림은 클라이언트와 서버에 의해서 생성될 수 있다.

기본 기능(항상 활성화됨)과 고급 기능(선택적으로 활성화)을 통해서 SPDY는 빠른 반응속도를 얻을 수 있다.


기본 기능

멀티플렉스 스트림
SPDY는 하나의 TCP 연결 위에 무제한 동시 스트림을 지원한다. 하나의 채널에서 요청들이 교차배치되기 때문에 TCP의 효율은 높아진다. 적은 네트웍 연결만 필요하고, 더 적은 수의 패킷만 사용된다.
요청 우선순위
무제한으로 스트림을 병렬화 할 수 있기 때문에 직렬화 문제를 해결할 수 있지만, 이것은 다른 문제를 만든다. 채널의 대역폭이 제한되어 있다면 채널이 막힐 수 있기 때문에 클라이언트는 요청을 블록할 수 있다. 이 문제를 극복하기 위해서 SPDY는 요청 우선순위를 구현한다 : 클라이언트는 원하는 수 만큼 요청할 수 있고, 각 요청에 우선순위를 부여한다. 이것은 네트웍 채널이 중요하지 않은 리소스들 때문에 혼잡해져서 높은 우선순위의 요청이 지연되는 것을 막는다.
헤더 압축
SPDY는 요청과 응답의 HTTP 헤더를 압축한다. 결과적으로 더 적은 수의 패킷과 더 적은 수의 데이터가 전송된다.

고급 기능 (advanced features)

SPDY는 서버에서 스트림을 생성할 수 있는 기능을 제공한다. 서버에서 생성된 스트림은 클라이언트의 요청이 없어서도 컨텐츠를 클라이언트에 전송할 수 있다. 웹개발자는 이 옵션을 2가지 방식으로 설정할 수 있다.

Server push
SPDY는 서버가 클라이언트에 데이터를 푸쉬(push)하는 것을 X-Associated-Content 헤더를 통해서 실험했다. 이 헤더는 클라이언트가 요청하기 전에 서버가 리소스를 푸시하고 있다는 것을 클라이언트에 알린다. 사용자가 사이트에 처음으로 방문하여 첫 페이지를 다운로드할 때, 이 기능은 사용자 경험을 크게 향상시킬 수 있다.
Server hint
자동으로 클라이언트에 리소스를 push하는 대신, X-Subresources 헤더를 사용하여 클라이언트가 특정 리소스를 요청하도록 제안하지만, 컨텐츠를 보내기 전에 클라이언트의 요청을 기다리게 된다. 네트웍 연결이 느린 경우, 클라이언트가 필요한 리소스들을 파악하는 걸리는 수백 밀리세컨드의 시간을 줄여줄 수 있다. 이 옵션은 초기 페이지가 아닌 페이지에서 더 나은 선택이 될 것이다.

기술적인 세부사항은 SPDY draft protocol specification을 참조하라.


SPDY 구현 : 우리가 만들어온 것들

  • HTTP와 SPDY로 TCP와 SSL 위에서 효율적으로 응답할 수 있는 high-speed의 in-memory 서버. 우리는 조만간 오픈소스로 이 코드를 릴리즈할 예정이다.
  • TCL와 SSL위에서 HTTP나 SPDY를 사용할 수 있는 수정된 구글 크롬. 소스 코드는 여기에 있다. (주: 현재 내부적인 코드네임은 “flip”이지만, 조만간 바뀌게 될 것이다.)
  • 페이지들이 정확하게 복사되었는지 검증할 수 있는 테스팅과 벤치마킹 인프라스트럭처. SPDY는 원래의 서버 헤더들과 컨텐츠 인코딩, URLs 등을 그대로 유지한다. 우리는 곧 테스팅 툴과 우리의 결과를 재활용하기 위한 가이드를 릴리즈할 것이다.

사전 실험 결과

우리가 개발한 구글 크롬 클라이언트와 웹서버를 가지고, SPDY의 HTTP 대비 성능을 벤치마크하기 위해서 많은 실험실 테스트를 수행했다.

우리는 1%의 패킷손실을 가지는 홈 네트워크 시뮬레이션 하에서 “Top 100″ 웹사이트 중 25개를 다운로드 해봤다. 각 사이트를 10번씩 다운로드했고, 평균 페이지 로딩 시간을 계산했다. 그 결과 HTTP 대비 TCP 하에서는 27%~60%정도, SSL하에서는 39%~55% 정도의 성능향상을 확인할 수 있었다.


표1 : Top 25 웹사이트들에 대한 평균 페이지 로딩 타임


DSL 2 Mbps downlink,
375 kbps uplink
Cable 4 Mbps downlink,
1 Mbps uplink

Average msSpeedupAverage msSpeedup
HTTP3111.916
2348.188
SPDY basic multi-domain* connection / TCP2242.75627.93%1325.4643.55%
SPDY basic single-domain* connection / TCP1695.7245.51%933.83660.23%
SPDY single-domain + server push / TCP1671.2846.29%950.76459.51%
SPDY single-domain + server hint / TCP1608.92848.30%856.35663.53%
SPDY basic single-domain / SSL1899.74438.95%1099.44453.18
SPDY single-domain + client prefetch / SSL1781.86442.74%1047.30855.40%
  • 많은 경우 요청 리소스가 속한 도메인의 수와 무관하게 SPDY는 하나의 연결로 모든 요청을 처리할 수 있다. 이 경우에는 모든 다운로드는 완전히 병렬로 진행될 수 있다. 그러나 모든 도메인을 하나의 도메인으로 줄일 수 없는 경우가 있는데, 이 경우에는 SPDY는 각 도메인별로 연결을 만들어야만한다. 이때 연결 생성마다 초기 RTT(round trip time)만큼의 시간이 필요하다.*

그래서 우리는 2가지 모드에 대해서 테스트를 수행했다. 하나는 모든 도메인을 하나로 줄여놓은 경우(즉, 하나의 TCP 연결)와 리소스를 원래 속한 다수의 도메인으로 나누어놓은 경우(즉, 도메인 당 하나의 TCP 연결). 우리는 테스트 결과에 이를 각각 “single-domain”과 “multi-domain”이라고 표기해놓았다. 실제 환경에서의 결과는 이 결과의 사이값이 될 것이다.

헤더 압축의 효과

헤더 압축은 요청헤더의 크기를 88%, 응답헤더의 크기를 85%정도 줄인다. 낮은 대역폭을 갖는 DSL 환경에서(업로드가 375Kbps) 요청헤더 압축은 특정사이트에서 페이지 로딩 시간에 있어서 상당한 성능향상을 보여주었다(리소스 요청이 수가 많은 경우). 헤더압축만 해도 페이지 로딩 시간을 45~1142ms만큼 줄일 수 있었다.

패킷 손실과 RTT(round-trip time)의 효과

우리는 두번째 테스트로 패킷 손실율과 RTT가 결과에 어떤 영향을 주는지 확인하기 위한 테스트를 수행했다. 이 테스트를 위해서 패킷 손실율과 RTT를 실험변수가 아니라 케이블 연결에서 측정을 했다.

우리는 SPDY의 응답시간 향상효과가 패킷손실율이 높아질 수록 증가한다는 것을 알아냈다. 패킷손실율이 2%일때 최대 48%의 성능향상이 있었다. (패킷손실이 2%는 넘어서면 성능향상폭이 줄어들기 시작해서 2.5%가 되면 성능향상율이 떨어진다. 실제 미국내에서 패킷손실율은 일반적으로 1~2%이고, RTT는 평균 50-100ms이다.)

패킷손실율이 증가할 수록 SPDY가 더 나은 이유는

  • SPDY는 HTTP보다 40% 정도 적은 패킷을 전송한다. 즉 패킷손실율의 영향을 덜 받는다.
  • SPDY는 보다 적은 TCP 컨넥션을 사용한다. 이것은 SYN packet이 손실될 가능성을 줄인다. 많은 TCP 구현에서 이것에 대한 지연은 의외로 크다. (3초)
  • SPDY는 재전송 타이머보다는 TCP의 빠른 재전송을 이용하여 TCP를 보다 효율적으로 이용한다.

SPDY는 RTT가 증가하면 더 나은 성능을 보였다. RTT가 200ms일때 최대 27%의 성능향상이 있었다. RTT가 증가할 때 SPDY가 HTTP 대비 더 나은 성능보이는 이유는 SPDY가 모든 요청을 병렬로 처리하기 때문이다. HTTP 클라이언트가 도메인당 4개의 연결을 사용하고, 20개의 리소스를 받아야 한다면, 대략 5RT(round trip)가 걸릴것이다. SPDY는 20개의 리소스를 한번의 RT만에 가져올 수 있다.

표2 : Top 25 웹사이트에 대한 평균 페이지로딩시간 (패킷손실율 별)


Average msSpeedup
Packet loss rateHTTPSPDY basic (TCP)
0%1152101611.81%
0.5%1638110532.54%
1%2060120041.75%
1.5%2372139441.23%
2%2904153747.7%
2.5%30281707

43.63%



SPDY 다음 단계 : 우리를 도울 수 있는 방법

우리의 초기 결과는 좋지만, 우리는 그것들을 어떻게 현실 세계에 적용해야 할지 잘 모르겠다. 게다가 SPDY는 더 개선할 여지들이 있다. 예를 들면

  • 대역폭 효율성은 여전히 낮다. 전화망의 대역폭 효율이 90%에 근접한다고 하지만, 고속망의 효율은 약 32% 밖에 안된다.
  • SSL은 추가적인 지연시간과 도입에 대한 난관들을 가지고 있다. SSL 핸드셰이킹를 위한 추가적인 RTT, 암호화, 프락시에서의 캐싱 문제 등이다. 우리는 SSL에 더 적합하게할 일들이 있다.
  • 우리의 패킷 손실율에 대한 실험결과로는 아직 결론을 내릴 수 었다. 패킷 손실율에 대한 연구들이 있었지만, 우리는 웹을 위한 현실적인 모델을 만들기 위한 충분한 데이터를 가지고 있지 않다. 패킷 손실율 시뮬레이션을 더 정교하게 할 수 있는 데이터들을 더 수집할 필요가 있다.
  • SPDY의 단일 커넥션은 연결이 끊겨서 복구할 경우 다수 컨넥션보다 때로는 성능이 낮을 수 있다. 특히 RTT가 매우 높을 때는 단일 커넥션보다 멀티플 커넥션이 빠를 수 있다. 언제 SPDY 클라이언트가 새로운 커넥션을 만들거나 기존 커넥션을 끊을지, 이것이 서버에 어떤 영향을 줄지를 더 고민할 필요가 있다.
  • 서버는 우리가 만든 것보다 더 지능적으로 구현할 수 있을 것이다. 서버가 스트림을 생성하는 경우, 프리패칭 제안을 위해서 클라이언트 네트웍 정보를 수집하는 등의 케이스에 대해서 더 많은 연구가 필요하다.

이런 문제에 도전하기 위해 당신이 참여하길 원한다면…


SPDY에 대한 FAQ

Q: HTTP piplelining이 이미 응답시간에 대한 문제를 해결하지 않았나요?

A: 아니오. 파이프라이닝이 다수의 요청을 하나의 TCP 연결하에서 병렬로 보내는 것을 지원하고 있지만, 여전히 단일 스트림입니다. 스트립 내의 과정에서 지연이 발생하면(첫 요청이 long request이거나 패킷 손실이 발생하거나해서) 전체 스트림이 지연됩니다. 파이프라이닝은 적용이 어렵기도 해서 대부분의 주요 브라우저에서 기본적으로 비활성화된 채로 남아있지요.


Q: SPDY는 HTTP를 대체하는 겁니까?

A: 아니오. SPDY는 HTTP의 일부분을 대체할 뿐이고, HTTP를 확장합니다. 어플리케이션 계층의 최상위 레벨에서 요청-응답 프로토콜은 여전히 동일합니다. SPDY는 여전히 HTTP 메소드, 헤더 등을 사용합니다. 그러나 SPDY는 커넥션 관리와 데이터 전송 포맷 등의 프로토콜의 다른 부분을 오버라이드합니다.


Q: 왜 이름을 이렇게 지었습니까?

A: 우리는 이름이 ‘속도’의 의미를 내포하길 원했습니다. SPDY(SPeeDY라고 읽음)는 그에 부합할 뿐만 아니라 압축이 어떻게 속도 향상에 도움되는지를 보여주기도 하지요.


Q: SPDY는 전송계층을 변경해야합니까?

A: 전송계층의 보완이 지연을 줄일 수 있는지는 더 연구해봐야 합니다. 그러나 전송계층의 교체는 복잡한 일이고, 어플리케이션 레이어에서 TCP와 HTTP의 비효율적인 부분들을 극복할 수 있다면 현실 적용이 더 쉬울거라고 봅니다.


Q: TCP는 네트웍의 혼잡이나 붕괴를 유발하지 않는지 오랜 시간 사용되면서 검증되었습니다. SPDY가 인터넷을 깨뜨릴 수도 있습니까?

A: 아니오. SPDY는 TCP 위에서 작동하므로 TCP의 혼잡제어 알고리즘들의 혜택을 받습니다. 게다가 혼잡 제어 방법을 수정한 HTTP가 인터넷에서 동작하고 있습니다. 예를 들면, 오늘날의 HTTP 클라이언트는 하나의 서버에 6개의 연결을 동시에 엽니다. 그리고 어떤 HTTP 서버는 초기 congestion window를 4 패킷으로 증가시켰습니다. TCP가 각각의 연결들을 독립적으로 속도를 올릴 수 있기 때문에 서버는 초기부터 효과적으로 24패킷을 보낼 수 있습니다. 다수 연결에서 TCP의 slow-start 문제를 회피한 것이죠. 반면 SPDY는 하나의 연결 위에 다수의 스트림을 구현한 겁니다.


Q: SCTP는 뭡니까?

A: SCTP는 재미있는 대한 전송 프로토콜이에요. 이것은 하나의 커넥션 위에 다수의 스트림을 제공합니다. 그러나 이건 전송계층의 변경을 필요로 해서 가정용 라우터에까지 적용하려면 매우 어렵운 일이 되죠. 또한 SCTP는 은총알(silver bullet)이 아니에요. 서버와 클라이언트 사이의 채널을 효율적으로 사용하려면 어플리케이션 계층의 변경 역시 필요하죠.


Q: BEEP은 뭡니까?

A: BEEP은 비슷한 여러가지 기능을 제공하는 재미있는 프로토콜이지만, 이것은 페이지 로드 타임을 줄이는 것을 목표로 하지 않습니다. 그걸 가능하게 할 몇몇 기능이 없지요. BEEP은 바이너리 프레이밍 대신에 텍스트 기반의 프레이밍을 사용합니다. 이것은 확장성에 있어서 경쟁력있는 좋은 프로토콜이지만, 몇몇 보안 문제들도 있고 정확히 파싱하기가 어렵다는 문제도 있습니다.