상세 컨텐츠

본문 제목

[HTTP] 파이프라이닝 & HTTP 버전별 특징 (1.0, 1.1, 2.0, 3.0)

CS/네트워크

by young1403 2023. 9. 16. 02:34

본문

 

TCP ?
전송 제어 프로토콜(Transmission Control Protocol)의 약자

 

멱등 ?

한 번 혹은 여러 번 실행됐는지에 상관없이 같은 결과를 반환한다면 그 트랜잭션은 멱등(idempotent)하다고 합니다. 
GET, HEAD, PUT, DELETE, TRACE, OPTIONS 메서드들은 멱등하다고 이해하면 됩니다.

 

지속 커넥션 ?
HTTP/1.1을 지원하는 기기에서 작업 처리가 완료된 후에도 TCP 커넥션을 유지하여 앞으로 있을 HTTP요청에 재사용할 수 있다. 이렇게 처리가 완료된 후에도 연결된 상태가 지속되는 TCP 커넥션을 지속 커넥션이라고 부릅니다. 지속 커넥션을 사용하면 커넥션을 맺기 위한 사전 작업과 지연시간을 줄여주어 커넥션 수를 줄일 수 있습니다. 하지만 커넥션을 잘못 관리할 경우, 계속 연결된 상태로 있는 수많은 커넥션이 쌓이게 될 것입니다. 

HTTP 완벽가이드 커넥션부분

[Keep-Alive 커넥션]

커넥션 중 하나. HTTP/1.0+에는 'keep-alive'커넥션이 있습니다.

위의 사진을 보면 (a)는 4개의 작업을 위해 4번의 커넥션을 맺어 처리하는 방식이고 (b)는 하나의 커넥션으로만 처리하는 방식입니다. 커넥션을 맺고 끊는데에 필요한 작업이 없기 때문에 (b)에서 시간이 단축됨을 알 수 있습니다.

HTTP/1.0 keep-alive 커넥션을 구현한 클라이언트는 커넥션을 유지하기 위해서 요청에 Connection:Keep-Alive 헤더를 포함시킵니다. 이 요청을 받은 서버는 그다음 요청도 이 커넥션을 통해 받고자 한다면, 응답메세지에도 같은 헤더를 포함시켜 응답을 해야합니다. 만약 응답메시지에 Connection:Keep-Alive 헤더가 없으면, 클라이언트는 서버가 keep-alive 를 지원하지 않으며, 응답 메시지가 전송되고 나면 서버 커넥션을 끊을 것이라 추정합니다. 

 

그렇다고해서 Keep-Alive헤더가 있다고 커넥션을 반드시 유지하는것은 아닙니다. 언제든지 keep-alive 커넥션을 끊을 수 있습니다. Keep-Alive 헤더 사용은 선택 사항이지만 Connection:Keep-Alive 헤더가 있을 때만 사용할 수가 있습니다. 또한 default값이 아니기 때문에 keep-alive 커넥션을 유지하기 위해선 Connection:Keep-Alive 요청 헤더를 매번 보내줘야 커넥션을 유지할 수 있습니다.

 

[HTTP Pipelining] (파이프라인 커넥션)

이전글에서는 TCP통신에서 이루어지는 4-wayhandshake에 대해 알아보았습니다. 연결을 끊기 위한 4way-handshake나 연결을 수립하기 위한 3-wayhandshake 모두 논리적인 TCP 연결수립과 해제를 거쳐야합니다. 그 논리적인 과정이라 함은 송신측에서 수신측으로 request를 보내고, 또 수신측에서 받았다는 응답으로써 response를 보내는 이러한 일련의 과정들이 어쩌면 Overhead로 볼 수도 있고, 줄일 수 있는 시간(자원)으로 보면 Latency라고도 비춰질 수 있겠습니다. 

 

 이러한 점을 효율적으로 만든 기술이 Pipelining(파이프라이닝) 기술입니다.( 위쪽 책 사진에서 '(c)' 부분) 먼저 보낸 요청이 완료되기 전에 송신측에서 요청을 계속해서 보냄으로써 다음 응답까지의 대기시간을 없애 네트워크 기능을 향상시킵니다. Keep-Alive를 전제로 하며 서버는 요청이 들어온 순서대로 응답을 반환해야 합니다.

 

하지만 완전한 멀티플렉싱(하나의 서버에서 두 클라이언트를 동시에 모두 처리하는 것)이 아닌 응답을 기다리는(미루는) 방식으로 동작하기 때문에 처리가 순차적으로 처리가 됩니다. 결국 후순위의 요청에 대한 응답은 지연될 수 밖에 없습니다. 이것이 HTTP HOLB(Head Of Line Blocking)이라고 불리며 한 요청이 오래걸리면 그 다음 요청이 지연된다는 것을 뜻합니다.

 

이러한 파이프라이닝을 함으로써 어떻게 TCP 커넥션 지연을 제거하는지와 전송 대기 시간을 단축 시키는지를 알 수 있었습니다. 이러한 파이프라이닝에는 여러가지 제약 사항이 있는데 아래와 같습니다.

  • HTTP클라이언트는 커넥션이 지속커넥션이어야 파이프라인을 이을 수 있다.
  • HTTP 응답은 요청 순서와 같게 와야한다(큐 형태). 순번이 없어서 정렬시킬 방법이 없다.
  • HTTP 클라이언트는 커넥션이 언제 끊어지더라도 완료되지 않은 요청이 파이프라인에 있으면 언제든 다시 요청을 보낼 준비가 되어 있어야한다. 그래서 요청을 보내다가 연결이 끊기면 끊긴 커넥션을 다시 맺고 요청을 보낼 수 있어야 한다.
  • HTTP 클라이언트는 POST나 PATCH와 같이 멱등하지 않은 요청은 파이프라인을 통해서 보내면 안된다. 왜냐하면 pipelining은 어떤 요청을 보냈지만 응답이 오기전에 끊기면  클라이언트는 서버에서 얼마만큼의 요청이 처리되었는지 알 방법이 없기 때문입니다. 그래서 POST와 같이 비멱등한 요청메서드를 재차 보내면 문제가 생길 수 있습니다. 

파이프라이닝과 멱등성을 엮은 설명도 알아가시면 좋을 것 같습니다.

 

 

[HTTP / 1.0]

HTTP/1.0에서 커넥션을 유지하기 위한 방법으로 위에서 설명한 Keep-Alive 커넥션 기능을 사용합니다. 기본적으로 제공되진 않고 선택적으로 Connection:keep-alive 헤더를 요청 헤더에 포함하여 Keep-Alive 기능을 사용할 수 있습니다.

 

[HTTP / 1.1]

HTTP/1.1에서는 keep-alive 기능을 기본적으로 사용할 수 있습니다. Connection:keep-alive 헤더를 사용하지 않아도 되며 연결이 지속적으로 열린상태로 유지됩니다. 다만 더 향상된 지속커넥션을 요청을 파이프라이닝 할 수 있습니다.  keep-alive 커넥션의 성능을 더 높힌 형태가 HTTP-파이프라이닝 입니다. 위에서 설명한 HTTP Pipeline 기술이 그 예입니다. HTTP/1.1지속 커넥션은 기본적으로(default) 활성화가 되어 있습니다. HTTP/1.1 클라이언트는 응답에 Connection:close 헤더가 없으면 응답 후에도 HTTP/1.1 커넥션을 계속 유지하는 것으로 추정합니다. 하지만 언제든 서버나 클라이언트에서 커넥션을 끊을 수 있으며 Connection:close를 보내지 않는것이 꼭 커넥션을 끊지 않기 때문에 영원히 유지한다라는 개념은 아닙니다.  또 다른 특징으로는 위에서 설명한 하나의 커넥션에서 처리하는 파이프라이닝은 Head Of Line Blocking 문제가 발생하는 단점이 있다는 점도 확인하시면 좋을 것 같습니다.

 

[HTTP / 2.0]

HTTP / 2.0에서는 요청과 응답의 멀티 플렉싱(Multi plexing)을 지원합니다. 멀티 플렉싱이란 한개의 TCP연결에서 여러개의 데이터를 섞이지 않게 보내는 기법으로 이 각각의 데이터 흐름을 Stream이라고 합니다. 요청과 응답이 동시에 이루어 지니 여러개의 데이터를 보내게 되고, 데이터를 식별할 수 있으니 데이터간 섞임이 발생하지 않습니다. 이러면 여러개의 TCP 연결을 수립하지 않아도 되고 여러개의 요청을 병렬로 처리할 수 있기 때문에 HOLB문제도 해결할 수 있습니다.

 

하지만 TCP프로토콜 특성상 request에 대해 response가 받아져야 통신이 수립이 됩니다. 하나의 TCP 커넥션으로 통신이 진행되기 때문에 TCP패킷이 네트워크 경로에서 손실되어 스트림에 공백이 발생하게 되면, 패킷 재전송으로 인해 전체적인 전송이 지연되게 됩니다. 이렇게 HTTP / 2.0 은 여러개의 HTTP 스트림을 하나의 TCP커넥션으로 처리하기 때문에 전체 데이터의 통신이 지연될 수 있다는 단점이 있습니다. 이렇듯 HTTP / 2.0 또한 전송 제어 프로토콜(TCP)로 호스팅되는 HTTP/2는 어떠한 TCP 패킷이라도 지연되거나 소실될 경우 모든 다중화 스트림에 대해 Head Of Line Blocking 지연 문제가 발생할 수 있습니다.

 

[HTTP / 3.0]

이러한 문제들을 해결하기 위해 또 나온게 HTTP / 3.0 입니다. 이 프로토콜의 가장 큰 특징은 TCP가 아닌 UDP를 사용한다는 것입니다. TCP와 UDP는 연결수립과정, header의 크기차이, 신뢰성, 주사용처, 전송속도 등 여러 차이점을 갖고 있습니다. 하지만 HTTP3는 구글에서 개발한 QUIC라는 프로토콜위에서 돌아가는 HTTP입니다.

 

QUIC란 (Quick UDP Internet Connection)의 약자로 UDP를 사용하는 프로토콜입니다. TCP를 사용하는 연결 지향 웹 애플리케이션의 성능을 개선해 handshake과정을 최적화 하는것에 초점이 되어 설계된 형태이며, UDP방식이기 때문에 패킷 간 순서가 존재하지 않고 다른 스트림을 수반하는 패킷 손실에 독립적입니다.

 

HTTP3의 특징 중 하나는 클라이언트의 IP가 바뀌어도 그대로 유지된다는 점입니다. TCP는 발신지IP, 수신지IP, 발신지 port, 수신지 port를 식별해 클라이언트 IP가 바뀌면 연결을 끊습니다. 이를 다시 연결하려면 3-wayhandshake를 거쳐야 하기에 레이턴시가 발생합니다. 요즘처럼 모바일 통신이 많은 상황에서 wifi에서 셀룰러로 전환하는 등 문제가 심각할 수 있습니다.

 

하지만 QUIC는 connection ID를 사용해서 서버와 연결을 생성합니다. (QUIC의 Connection ID는 QUIC 연결을 식별하고 관리하는 데 중요한 역할을 하는 고유한 식별자입니다.) 이는 클라이언트 IP와는 전혀 무관하기 때문에 클라이언트의 IP가 변경되어도 기존의 연결을 계속 유지할 수 있습니다.

 

youtube나 google페이지에서 개발자도구를 켜보면 protocol란에 h3(http3)라고 표시됨을 확인할 수 있습니다. QUIC는 구글 크롬에서부터 구글 서버에 이르는 모든 연결의 절반 이상에 사용된다고 합니다. 네이버 홈페이지에서 확인해보니 http1.1과 http2가 섞여 나옴을 볼 수 있었는데 앞으로 국내 웹사이트들의 http 프로토콜이 udp기반의 http3로 서서히 바꾸어 나갈지 혹은 개선된 tcp기반 프로토콜로 바뀔지 트렌드가 어느 방향으로 향할지 궁금해 지기도 합니다.  

 

http 프로토콜을 공부하던 중 pipeline에 대해 궁금하여 작성한 글입니다.

 

많은 조언 환영합니다.  읽어 주셔서 감사합니다.

 

참고
책 : HTTP 완벽 가이드
HTTP Pipelining에 관한 글 :  https://ijbgo.tistory.com/26
HTTP / 3.0에 관한 글 : https://evan-moon.github.io/2019/10/08/what-is-http3/

 

관련글 더보기

댓글 영역