HTTP1.x / HTTP2.0 / QUIC

정종일·2023년 2월 21일
0

Web

목록 보기
2/6

HTTP

HTTP(Hyper Text Transfer Protocol)은 웹 브라우저와 웹 서버간 통신을 위해 디자인된 프로토콜로 HTML 문서와 같은 리소스, 데이터를 가져올 수 있도록 도와준다.

연결 방식

HTTP 요청시 브라우저는 HTTP 요청 메시지를 생성하고 TCP/IP 프로토콜을 이용해 웹 서버와 통신하며 3-way handshake를 통해 논리적 연결을 수립하게 됩니다.

구성

HTTP 요청 메시지는 크게 Startline, Header, Body로 구성되며

Startline에는 메서드, 경로, 프로토콜의 버전

Header에는 요청에 설정한 HTTP헤더

Body에는 Http Method에 따라 내용이 추가된다.

HTTP 프로토콜의 특징

비연결성(connectionless)

비연결성은 클라이언트와 서버가 연결을 수립한 후 요청 및 응답을 마치면 연결을 끊는 특성을 말한다.

이에 따라 서버는 클라이언트의 수가 증가해도 지속적인 연결을 하지 않기 때문에 서버의 리소스 소모를 줄일 수 있지만 클라이언트의 반복된 요청에도 일일이 연결 및 해제 과정을 거쳐야 하기에 오버헤드가 발생할 수 있다.

무상태성(Stateless)

연결을 지속적으로 수립하고 있지 않기 때문에 클라이언트가 어떤 상태인지 알 수가 없다. 회원이 로그인한 상태에서 요청을 보낸 후 다른 페이지로 넘어가 다시 요청을 보냈을 때 이 회원이 로그인한 상태인지 알 수 없게 되는 것이다.

무상태성을 보완하기 위해 쿠키, 세션, 토큰 개념이 등장했다. (추후 포스팅)


HTTP/1.1

위에서 언급한 것처럼 HTTP 프로토콜은 매 요청마다 연결 수립 및 해제를 진행했고 이에 따른 오버헤드가 치명적이었다. HTTP/1.1에서는 이러한 단점을 보완하기 위해 기존 연결 방식을 표준화하는 동시에 한 가지 연결 방식을 추가했다.

HTTP/1.1에 보완된 연결 방식

Persistent connection

Persistent connection은 연결 지속 시간을 미리 설정하고 연결하는 방식이다. HTTP/1.0에도 존재했지만 표준화가 된 것은 HTTP/1.1에서이다

다만 연결 수립 및 해제의 과정을 1번으로 줄였을 뿐, 요청에 대한 응답을 기다리는 동안 다른 동작을 수행할 수 없다는 점은 여전했다.

Pipelining

요청 후 응답을 기다리는 동안 다른 동작을 수행할 수 없던 부분을 해결한 모델로 클라이언트에서 필요한 데이터에 대한 요청을 응답에 상관없이 모두 보내면 서버에서 요청이 들어온 순서대로 응답을 해주는 방식이다. 클라이언트에서는 응답의 순서가 잘못되거나 누락된 데이터가 있다면 다시 요청을 보낸다.

단점이 보완된 듯 했으나..

HOL(Head Of Line) Blocking

Pipelining에도 문제는 있었다. HOL(Head Of Line) Blocking이다.

클라이언트에서 3가지 데이터를 요청했다고 가정할 때 서버가 응답하는 데에 1번 요청은 20초, 2번 요청은 10초, 3번 요청은 1초가 걸린다고 하자.

서버는 요청이 들어온 순서대로 응답을 하기 때문에 1번 요청을 가장 먼저 응답하게 되는데, 다른 요청의 응답 시간이 아무리 짧다 하여도 1번 요청의 응답 시간이 길다면 클라이언트는 1번 응답부터 받아야하기에 다른 응답을 받을 수 없는 것이다.

문제점은 또 존재했다.

중복된 헤더

바로 연속된 요청에 존재하는 중복된 헤더들이다.

위 그림처럼 요청 1과 요청 2의 헤더는 path만 다를 뿐 다른 요소들은 동일하다. 그러나 HTTP/1.1에서는 여전히 중복된 헤더를 포함해 요청을 주고받고 있었다.


HTTP/2.0

HTTP/1.x에서의 문제점을 해결하기 위해 HTTP/2.0이 등장했다. 정확히 하자면 기존의 1.1을 대체하는 프로토콜이 아니라 성능의 개선을 위해 확장한 프로토콜이다.

변경된 점

binary framing

기존 HTTP/1.1에서 text 형식으로 전달되었던 요청 및 응답 메시지는 프레임 단위로 나누어지고 바이너리 형식으로 인코딩된다. 때문에 컴퓨터가 이해하기 더 수월해지고 오류 발생 가능성도 낮아졌으며 파싱, 전송속도가 증가했다.

multiplex streaming

TCP 연결이 수립되고 N개의 스트림을 생성할 수 있게 되었다.

스트림은 양방향 데이터 흐름이 가능하며 각 스트림에 고유 식별자와 우선순위 정보가 담겨있다. 때문에 순서에 상관없이 처리되는대로 응답을 보내도 클라이언트에서 스트림 식별자를 통해 프레임을 재조립해 메시지 확인이 가능하다.

위에서 언급한대로 각 메시지는 논리적 HTTP 메시지(요청 및 응답)이고 하나 이상의 프레임으로 구성된다.

요청 및 응답 병렬 처리

기존 HTTP에서 발생하던 HOL Blocking을 해결한 방식으로 위 그림처럼 병렬 스트림 처리가 가능해졌다.

  1. 요청 1에 대한 data를 프레임 단위로 응답
  2. 요청 3에 대한 Header, data를 프레임에 담아 응답
  3. 요청 5에 대한 데이터를 서버로 보냄

스트림 우선순위 지정 가능

먼저 응답받을 우선순위를 지정할 수 있게 되었다.

Header Compression

기존 HTTP의 문제점이었던 헤더 중복을 해결한 방식이다.

압축에는 HPACK이라는 알고리즘을 사용하는데 이 알고리즘에는 정적 테이블과 동적 테이블이 존재한다.

정적테이블에서는 공용 HTTP 헤더 필드를 제공하고 동적 테이블에서는 특정 연결시에만 값에 따라 업데이트 된다.

각각의 값은 index 값을 가지고 헤더 전송이 시작될때 정적테이블, 동적테이블에 존재할 경우에는 index의 번호를 보내고 두개의 테이블에 없을 경우에는 Huffman 인코딩 방식을 사용하여 전송한다.

Server Push

클라이언트가 요청하지 않아도 서버에서 임의로 데이터를 보낼 수 있게 되었다.

클라이언트가 HTML 문서를 요청했을 때 서버에서 “이 다음에 당연히 script 파일이랑 css 파일 요청하겠지” 라고 판단해 두 파일도 같이 보내는 것이다.


추가

QUIC

구글에서 개발한 전송 계층 프로토콜

현재 구글 관련 제품 대부분의 기본 프로토콜로 사용중

기존의 HTTP 프로토콜과는 다르게 UDP 기반의 프로토콜

TCP는 신뢰성을 확보하지만 그 때문에 많은 기능들이 있어 지연을 줄이기 힘든 구조

반면 UDP는 데이터 전송에 집중한 설계이기 때문에 원하는 기능을 구현 가능

때문에 TCP의 지연을 줄이면서 TCP만큼의 신뢰성 확보가 가능하다.

QUIC의 통신 구조

첫 연결 설정에서 필요한 정보와 함께 데이터를 전송하기 때문에 요청의 횟수가 적고 연결 성공 시 설정을 캐싱해 다음 연결 때 확인 과정 없이 바로 연결할 수 있다.

그렇다면 연결 대상을 어떻게 구분할까?

서버와 연결할 때 Connection UUID라는 고유한 식별자를 가지고 연결하기 때문에 이를 통해 연결 대상을 구분해 커넥션을 재수립할 필요가 없다.

TCP Multiplexing의 한계점 보완

기존 TCP Multiplexing은 여러 스트림이 이어져 전송되기 때문에 일부 데이터가 손실될 경우 다시 받아올 때까지 후속 데이터가 대기해야 하는 문제가 있다.

QUIC은 이를 독립된 스트림으로 설계해 일부 데이터가 손실되더라도 다른 스트림에 영향이 가지 않도록 설계해 조금 더 향상된 Multiplexing 기능을 제공한다.

profile
제어할 수 없는 것에 의지하지 말자

0개의 댓글