MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

HTTP/1.x의 커넥션 관리

현재 번역은 완벽하지 않습니다. 한국어로 문서 번역에 동참해주세요.

커넥션 관리는 HTTP의 주요 토픽입니다: 대규모로 커넥션을 열고 유지하는 것은 웹 사이트 혹은 웹 애플리케이션의 성능에 영향을 줍니다. HTTP/1.x에는 몇 가지 모델이 존재합니다: 단기 커넥션, 영속적인 커넥션, 그리고 HTTP 파이프라이닝.

HTTP은 전송 프로토콜로 TCP에 거의 의존합니다. TCP는 클라이언트와 서버 사이의 커넥션을 제공합니다. 프로토콜의 유아기에, HTTP는 이런 커넥션들을 다루기 위해 단일 모델을 제공했습니다. 커넥션들은 단기만 유지되었죠: 전송해야 할 요청마다 새로운 커넥션이 만들어지고 응답이 오면 닫는 걸 말합니다.

이런 단순한 모델은 성능을 제한합니다: TCP 연결을 여는 것은 시간을 소비하는 동작입니다. 몇몇 메시지들은 클라이언트와 서버 사이에서 교환되어야만 하며, 네트워크의 레이턴시와 대역폭은 요청이 전송되어야 할 때마다 성능에 영향을 줍니다. 현대의 웹 페이지들은 필요로 하는 정보를 제공하기 위해 많은 요청(12개 이상)을 필요로 하므로, 이런 초창기 모델로는 불충분하다는 것이 자명합니다.

두 가지 추가적인 모델은 HTTP/1.1에 들어서 만들어졌습니다. 영속적인 연결 모델은 성공적인 요청 사이에서 새로운 연결을 절약하도록 커넥션을 열어놓습니다; 파이프라이닝은 한 단계 더 나아가, 네트워크 레이턴시에 대한 거래 과정을 줄이도록 응답을 기다리지 않고 몇 개의 요청들을 연속적으로 보냅니다.

Compares the performance of the three HTTP/1.x connection models: short-lived connections, persistent connections, and HTTP pipelining.

HTTP/2는 커넥션 관리의 모델을 좀 더 추가합니다.

명심해야 할 중요한 점은 HTTP 내 커넥션 관리가 end-to-end가 아닌 hop-by-hop인 두 개의 연속된 노드 사이의 커넥션에 적용된다는 것입니다. 클라이언트와 클라이언트의 첫번째 프록시 사이의 커넥션 모델은 프록시와 목적지 서버(혹은 중간 프록시들) 간의 것과는 다를 수도 있습니다. Connection와 Keep-Alive와 같이, 커넥션 모델 정의 내로 개입되는 HTTP 헤더들은 hop-by-hop 헤더이며 중간 노드에 의해 그 값들이 변경될 수 있습니다.

단기 커넥션

HTTP 본래의 모델이자 HTTP/1.0의 기본 커넥션은 단기 커넥션입니다. 각각의 HTTP 요청은 요청의 커넥션 상에서 실행됩니다; 그렇다는 것은 각각의 요청과 직렬화되기 전에 일어나는 TCP 핸드쉐이크가 존재한다는 것을 의미합니다.

TCP 핸드쉐이크 자체는 시간을 소비하는데, TCP 커넥션은 로드에 그 자신을 채택했으며 장기 커넥션과 함께 좀 더 효율적으로 변화했습니다. 이 모델은 TCP의 이런 기능을 사용하지 않으며 열띤 커넥션보다는 항상 한가한 커넥션으로 전송함으로써 성능이 최적의 조건에서 멀어졌습니다.

이 모델은 HTTP/1.0과 함께 사용되었던 기본 모델입니다(Connection 헤더가 존재하지 않거나, 그것의 값이 close로 설정된 경우에 사용되었던 모델입니다). HTTP/1.1에서 이 모델은 Connection 헤더가 close 값으로 설정되어 전송된 경우에만 사용됩니다.

영속적인 커넥션을 지원하지 않는 매우 낡은 시스템을 다루는 것이 아니라면, 이 모델을 사용하려고 애쓸 필요가 없습니다.

영속적인 커넥션

단기 커넥션은 두 가지 결점을 지니고 있습니다: 새로운 연결 수립에 드는 시간이 상당하다는 것과 내재된 TCP 연결의 성능이 어떤 경우(열띤 커넥션)에 사용될 경우에만 좀 더 나아진다는 것입니다. 이런 문제를 완화시키기 위해, HTTP/1.1 전부터 영속적인 커넥션의 컨셉이 만들어졌으며 때로는 keep-alive 커넥션이라고도 불렸습니다.

영속적인 커넥션은 얼마간 연결을 열어놓고 TCP 핸드쉐이크와 TCP 성능을 좀 더 나아지게 만들도록 몇몇 요청에 대해 재사용될 수 있는 커넥션입니다. 커넥션은 영원히 열려있는지 않을 겁니다: 유휴 커넥션들은 얼마 후에 닫힙니다(서버는 그들이 열어놔야 하는 최소 시간을 제공하기 위해 Keep-Alive 헤더를 사용할 겁니다).

영속적인 커넥션도 결정을 가지고 있습니다; 서버 리소스를 소비하고 무거운 로드 하에 놓여있을 때조차, DoS attacks이 일어날 수 있습니다. 이런 경우에, 커넥션이 유휴 상태가 되자마자 닫히는 비영속적 커넥션은 더 나을 성능을 보입니다.

HTTP/1.0 커넥션은 기본적으로 영속적이지 않습니다. close이 아닌 다른 것, 특히 retry-after로 Connection를 설정하게 되면 영속적으로 동작하게 될 겁니다.

반면, HTTP/1.1에서, 커넥션들은 기본적으로 영속적이며 헤더를 필요로 하지 않습니다(그러나 종종 추가되므로 HTTP/1.0으로 동작하는 경우에 고려되어야 합니다).

HTTP 파이프라이닝

HTTP 파이프라이닝은 모던 브라우저에서 기본적으로 활성화되지 않습니다:

  • 버그가 있는 프록시들이 여전히 많은데 이들은 웹 개발자들이 쉽게 예견하고 분석해낼 수 없는 이상하고 오류가 있는 동작들을 야기합니다.
  • 파이프라이닝은 정확히 구현해내기 복잡합니다: 전송 중인 리소스의 크기, 사용될 효과적인 RTT, 그리고 효과적인 대역폭은 파이프라인에 의해 제공되는 향상의 직접적인 영향 범위 내에 있게 됩니다. 이런 내용을 모른다면, 중요한 메시지는 덜 중요한 메시지 뒤에서 딜레이될 것입니다. 중요한 개념은 페이지 레이아웃 중에도 진화합니다! 그러므로 파이프라이닝은 대부분의 경우 미미한 수준의 향상만을 가져다 줍니다.
  • 파이프라이닝은 HOL 문제의 대상입니다.

이런 이유들로, 파이프라이닝은 더 나은 알고리즘인, HTTP/2에 의해 사용되는 멀티플렉싱으로 대체되었습니다.

기본적으로, HTTP 요청은 현재의 요청에 대한 응답이 완전히 수신되고 난 뒤에야 다음 요청을 발행하기에, 순차적으로 발급됩니다. 네트워크 레이턴시와 대역폭 제한에 걸려, 이것은 서버가 다음 요청을 보기 전까지 상당한 딜레이를 발생시킬 수 있습니다.

파이프라이닝이란 응답을 기다리지 않고 동일한 영속적인 커넥션 상에서 몇 개의 요청들을 연속적으로 보내기 위한 기능을 말합니다. 커넥션의 레이턴시를 회피하고자 하는 그 방법입니다. 이론적으로, 두 개의 HTTP 요청이 동일한 TCP 메시지 안에 채워질 수 있다면, 성능 또한 향상될 수 있습니다. 전형적인 MSS (최대 세그먼트 크기)는 HTTP 요청의 사이즈가 수년간 점점 커져왔지만, 몇 개의 간단한 요청을 포함하기에는 충분히 큽니다.

모든 종류의 HTTP 요청이 파이프라인으로 처리될 수 있는 것은 아닙니다: 오로지 idempotent 메서드, 즉 GET, HEAD, PUT 그리고 DELETE 메서드만 가능한데, 모두 안전하게 재생될 수 있는 것들입니다: 실패가 발생한 경우, 파이프라인 컨텐츠는 바로 재생될 수 있습니다.

오늘날, 모든 HTTP/1.1 호환 프록시와 서버들은 파이프라이닝을 지원해야 하지만, 실제로 많은 프록시와 서버들이 제한을 가지고 있습니다: 모던 브라우저가 이 기능을 기본적으로 활성화하지 않는다는 것이죠.

도메인 샤딩

매우 명확하고 당면해있는 요구사항을 가지고 있지 않다면, 이 제외된 기술을 사용하지 마세요; 그 대신 HTTP/2로 전환하시기 바랍니다. HTTP/2에서, 도메인 샤딩은 더 이상 유용하지 않습니다: HTTP/2 커넥션은 병렬의 우선 순위가 없는 요청들을  매우 잘 다룰 수 있게 되었습니다. 도메인 샤딩은 성능 측면에서조차 좋지 못합니다. 대부분의 HTTP/2 구현은 우발적으로 일어나는 도메인 샤딩을 되돌리기 위해 커넥션 합치기(connection coalescing)라고 불리는 기술을 사용합니다.

요청 사이에 실제 정렬이 없음에도, HTTP/1.x 커넥션이 요청을 직렬화함으로써, 이용 가능한 대역폭이 충분히 큰 경우 그 대역폭을 제대로 활용하지 못합니다. 이런 단점을 피하기 위해, 브라우저들은 각 도메인에 대한 몇 개의 커넥션을 맺고 병렬로 요청을 보냅니다. 원래, 브라우저들은 2개 혹은 3개의 커넥션을 맺어 왔었지만, 점점 증가하여 가장 일반적인 병렬 커넥션의 양은 이제 6개입니다. 브라우저들은 서버 측에서 DoS 보호를 동작시키지 않는 한 이 이상의 커넥션을 열 수 없습니다.

웹 사이트 혹은 애플리케이션이 더 빠르게 동작하기를 서버가 원할 경우, 더 많은 커넥션을 열도록 브라우저를 속일 수 있습니다. 동일한 도메인 상에서 모든 리소스들을 가지고 오는 대신에, , www.example.com 라는 도메인을 www1.example.com, www2.example.com, www3.example.com와 같이 몇 개의 도메인으로 분할하도록 할 수 있습니다. 이런 각각의 도메인들은 동일한 서버로 해석되고, 브라우저들은 그런 각각의 도메인들마다 6개의 커넥션을 맺을 것입니다(예제에서는 총 18개가 됩니다). 이런 기술을 도메인 샤딩이라고 부릅니다.

결론

더 나은 커넥션 관리는 HTTP의 성능 향상을 상당히 이끌어냅니다. HTTP/1.1 혹은 HTTP/1.0과 함께, 영속적인 커넥션 사용 - 적어도 그 커넥션이 유휴 상태가 될 때까지 - 최상의 성능을 이끌어냅니다. 그러나, 수년 넘는 세월과 파이프라이닝의 실패로, 더 나은 커넥션 관리 모델이 고안되었고 HTTP/2에 포함되었습니다.

문서 태그 및 공헌자

 이 페이지의 공헌자: devcken
 최종 변경: devcken,