인터넷에서 정보를 주고 받기 위한 HTTP에 대해서 알아보자

Doa Choi
Cloud Villains
Published in
21 min readJan 25, 2023

개요

지난주, 저희 팀 내에서 ‘HTTP’를 주제로 하여 발표를 진행하게 되었는데요, 내용을 정리 해 보고자 블로그로도 업로드 하게 되었습니다.

이미 알고 계신 분들도 많으시겠지만, HTTP는 우리에게 가장 친근한 프로토콜로 인터넷에서 웹 서핑을 하기 위해서 가장 먼저 만나볼 수 있는 프로토콜입니다.

이처럼 인터넷을 통해 가장 먼저 만나볼 수 있는 친구인 HTTP는 현재 UDP 프로토콜 기반의 HTTP/3 메이저 버전이 배포되었는데요, HTTP/1 버전에서 HTTP/2으로 발전하는 데만 약 15년 정도의 시간이 흘렀고, HTTP/2 버전이 등장한 지 얼마되지 않아 HTTP/3 버전이 등장하게 되었습니다. 기술의 발전 속도가 매우 빠르다는 게 체감 되시지 않나요?

본 게시글에서는 이러한 버전 업그레이드 시, 어떠한 부분을 개선 하고자 했는지에 대해 설명 드리고자 합니다. HTTP의 역할과 해당 프로토콜이 내부적으로 동작하는 과정, HTTP/0.9 버전부터 HTTP/3 버전까지 각 메이저 버전이 개정될 때마다 진행 된 개선 포인트, 그리고 C/S 간 메시지의 구조에 대해 정리 하겠습니다.

각 주제에 대한 세부적인 상세 내용은 다루지 않으니, 이 점 참고하여 읽어주시면 감사드리겠습니다.

안녕, HTTP!

HTTP는 HyperText Transfer Protocol의 약자로 우리가 인터넷 웹 서핑 등을 이용하게 되면 가장 먼저 접하게 되는 인터넷 상에서 정보를 주고 받기 위한 프로토콜입니다. HTTP는 과거 ‘팀 버너스 리’ 에 의해 제안되었는데요. 이 프로토콜은 WWW(World Wide Web)의 적용을 위해 단순함을 염두해두고 디자인되었습니다.

과거에는 문서간의 링크를 통해 HTML 문서를 전송하기 위해 시작하였는데, 현재는 이미지와 영상, JSON, XML 등 거의 모든 형태의 데이터를 담아 전송합니다. 심지어 서버 간 데이터를 주고 받을 때에도 해당 프로토콜을 활용합니다. 즉, 현재는 과거와 달리 HTML 문서 뿐만 아니라 거의 모든 형태의 데이터를 전송할 수 있는 형태로 변경되어 HTTP의 시대라고 해도 과언이 아닙니다.

이처럼 HTTP는 앞서 소개한 내용과 같이 인터넷에서 데이터를 주고 받기 위한 프로토콜로, 요청과 응답을 보내는 C/S 모델을 따르는데요. OSI 7Layer 계층 기준으로 마지막 계층인 Application 레벨에서 동작하며, HTTP/3 버전을 제외한 하위 메이저 버전에서는 TCP 기반으로 동작하기 때문에 TCP Connection이 맺어지면, 다양한 종류의 데이터를 전송할 수 있도록 설계 되었습니다.

먼저, HTTP에 대해서 살펴 보기에 앞서 URL 컴포넌트 구조에 대해서 정리하자면, URL은 Uniform Resource Locator의 약자로 크게 아래 그림과 같은 구조로 구성됩니다.

HTTP URL 컴포넌트 기본 구조

상기 그림에서 ‘Protocol’은 액세스 프로토콜을 의미하는데요.우리가 자주 이용하는 브라우저에서는 문자열 기반의 어플리케이션 프로토콜인 HTTP, HTTPS, FTP, Mail 등을 지원합니다. 그리고 ‘Host(Domain)’는 액세스할 웹 서버에 대한 도메인 혹은 호스트 아이피 정보에 해당됩니다. ‘Path’는 계층적인 디렉터리 형태로 응답을 받을 리소스에 대한 경로를 의미합니다. ‘Query’는 Key=Value 형태로 구성되어 있으며, 이는 쿼리 파라미터 혹은 쿼리 스트링이라고도 합니다.

HTTP 트랜잭션 과정과 메시지 구조 살펴보기

사용자가 브라우저를 통해 URL을 입력하게 되면, 다음과 같은 일들이 일어나게 됩니다. 가장 먼저, 사용자가 도메인을 입력하면 로컬 호스트의 Hosts 파일을 참조하게 됩니다. 그리고 도메인에 대한 정보가 없다면, 도메인에 대한 리소스 레코드 정보가 기록된 DNS 서버를 경유하여 도메인에 대응하는 주소 정보를 조회합니다.

이 때, 브라우저에서는 사용자가 요청한 프로토콜 규격에 알맞게 서버로 전달할 요청 메시지를 생성하는데 이 요청 메시지에서는 서버가 수행할 동작을 의미하는 메서드 정보와 HTTP 버전 정보, 웹 서버 호스트 정보 등을 포함합니다. 그리고 생성된 요청 메시지는 인터넷망을 통해 서버측으로 정보를 전달하고, 요청을 받은 웹 서버는 해당 메시지 정보를 해석하여 응답 메시지를 만들어 회신합니다. 이렇게 웹 브라우저는 서버에게 받은 메시지를 화면에 렌더링하여 사용자에게 시각화된 정보를 제공합니다.

이처럼 C/S간 리소스를 주고 받을 때에 필요한 HTTP 메시지 구조는 RFC 7230에 정의된 내용에 따라, 하기와 같은 표준화된 규격에 알맞게 생성됩니다.

(RFC 7230) HTTP/1.1 Message Format

HTTP-message = start-line (request line or status line)
*(header-field)
CRLF
message-body

RFC7230에서 명시된 내용에 따르면, HTTP의 메시지 규격은 start-line 으로 시작하여 메시지 헤더와 바디로 구성되어 있다는 가이드를 참고할 수 있습니다.

요청 메시지의 ‘start-line’을 ‘reqeust-line’으로 칭하는데, 이 라인에서는 서버가 수행해야 할 동작을 의미하는 GET, POST, PUT, DELETE, OPTIONS와 같은 메서드에 대한 정보와 요청 대상 리소스의 경로를 표현합니다. 이 리소스의 경로는 절대 경로 혹은 애스터리스크 기호가 포함될 수 있으며, HTTP의 버전 정보가 포함됩니다.

그리고 응답 메시지의 ‘start-line’은 ‘status-line’으로 칭합니다. 이 라인에서는 HTTP 버전 정보와 상태 코드, 사유가 포함됩니다.

HTTP 요청/응답 메시지 구조 및 명칭

상기 그림과 같이 HTTP 메시지 구조는 다음과 같습니다. Request Header에서는 사용자 소프트웨어를 의미하는 User-Agent 정보, 요청 대상 정보인 Host, 클라이언트측에서 콘텐츠 협상을 위한 Accept 등이 포함되며, Response Header에서는 응답에 대한 정보를 포함하는 고유 식별 번호를 포함하는 ETag와 Apache 혹은 Nginx와 같은 서버측의 소프트웨어 정보와 요청 메시지에 대한 응답 시간 등이 포함됩니다.

General Header에서는 요청과 응답 메시지에 공통으로 포함되는 헤더 필드인 TCP Connection 방식 등이 포함됩니다. 마지막으로 Representation Header는 과거 Entity Header라고 하였으나, 현재는 RFC 7230 ~ RFC 7235 로 최신화되면서 표현 헤더로 명칭이 변경되었습니다. 표현 헤더에서는 HTML, JSON 등의 데이터 유형을 의미하는 Content-Type 정보와 데이터에 대한 길이를 의미하는 Content-Length, 압축 정보인 Content-Encoding, 언어에 대한 표현을 위한 Content-Language 와 같은 헤더 필드가 포함되어 해당 정보를 참조하여 페이로드(본문)을 해석합니다.

정리하자면, 위 내용과 같이 헤더 내에서는 ‘field-name’ 과 ‘field-value’ 형태로 구성이 되어 HTTP 전송에 필요한 모든 부가 정보를 포함합니다.

HTTP 끝은 어디까지?

뿐만 아니라, HTTP/1.1 부터는 명시적으로 캐시와 관련된 부분을 제어하기 위한 Cache-Control 헤더 필드 또한 추가가 되었습니다. 먼저, 캐시는 리소스를 오리진 서버를 대신하여 빠르게 응답하기 위해 서버와 클라이언트 사이에 사본을 저장하는 장소를 마련해두고 이 사본을 제공하게 되는데요. HTTP/1.1 에서는 완전한 콘텐츠 응답에 대한 요청 수와 불필요한 전송을 최소화하기 위한 목적으로 Cache-Control 필드가 추가 되었습니다.

이러한 캐시와 관련된 값은 TTL과 관련된 필드와 캐시 범위를 의미하는 필드, 캐싱한 리소스에 대한 다운로드 여부를 결정하는 부분과 TTL이 만료된 콘텐츠 중 변경사항이 있는 콘텐츠를 기준으로 새 응답을 생성하기 위한 시간 기반 조건부 요청 또는 콘텐츠 기반 조건부 요청을 위한 부분 등 다양한 필드가 제공됩니다.

이와 같이 HTTP 메시지는 다양한 구조로 이루어져 있습니다. 또한 사이버 보안 위협이 증가함에 따라 보안헤더를 통해서 웹 취약점 보안을 강화하기 위한 목적으로 암호화된 패킷으로 전송하기 위한 Secure 필드와 XSS 공격 방지를 위한 HttpOnly와 같은 다양한 헤더 필드도 제공합니다. 이 외에도 클라이언트단에 저장될 목적으로 생성하는 OAuth 토큰과 같은 작은 정보를 담을 수 있는 Set-Cookie와 리다이렉트와 관련된 Location, 이전 요청 주소를 의미하는 Referer 등의 다양한 정보를 담아 전송합니다.

이 외에도 더 많다는 흥미로운 사실은 안비밀!

마지막으로 메시지 바디인 표현 데이터에서는 HTML 문서, 이미지, 영상, JSON 등의 Byte 단위로 표현할 수 있는 모든 데이터가 포함됩니다.

HTTP 메서드와 API 의 관계

HTTP 요청 메시지에 포함되는 메서드는 API 설계를 할 때에 리소스에 대한 행위를 구분하는 역할을 하게 됩니다. 메서드의 종류는 다양하지만, 본 게시글에서는 REST API 제약 조건 4가지 대표적인 메서드인 GET, POST, PUT, DELETE 방식에 대하여 정리 해 보겠습니다.

먼저, API URI 를 설계할 때에 URI로 리소스를 식별하고, 리소스에 대한 행위를 메서드로 구분할 수 있습니다. 물론, HTTP 메서드나 상태코드 혹은 REST 와 같은 부분을 지키지 않는다고 해서 프로그램이 동작하지 않는 게 아니며, 프로그램에는 아무런 지장도 없습니다. 그리고 이러한 제약 조건을 온전히 지키며 구현하는 건 어려운 일이라 일반화 할 수는 없습니다.

그러나 RFC 7231에서 권장하고 있는 메서드의 활용 예시에 의하면 다음과 같이 정리할 수 있습니다.

  • GET 방식은 주로 정적 데이터를 조회하거나, 쿼리 파라미터를 기반으로 특정한 게시글 (ex. /posts?title=doa) 등과 같이 동적 데이터 조회를 할 때에 활용합니다.
  • POST 방식은 내부적으로 처리가 필요할 때 활용할 수 있습니다. 예를 들어, HTML 폼에 입력한 데이터를 전달하는 경우, 메시지 바디를 통해 서버로 데이터가 전달됩니다. 이러한 방식은 주로 회원 가입, 상품 주문, 상품 등록, 변경 등에 활용할 수 있습니다.
  • PUT 방식은 클라이언트에서 서버로 데이터를 보내는데 해당하는 리소스가 이미 존재한다면, 대체하고 없으면 새롭게 생성합니다.
  • DELETE 방식은 리소스를 삭제하도록 활용할 수 있습니다.

가령, 하기의 내용과 같이 팀원 관리 API 를 설계했다고 가정해보겠습니다.

  • 팀원 목록 조회 (GET /members)
  • 팀원 조회 (GET /members/{id})
  • 팀원 등록 (POST /members)
  • 팀원 수정 (PUT /members/{id})
  • 팀원 삭제 (DELETE /members/{id})

이처럼 member 컬렉션에 대한 1번 id(pk)가 ‘도아’라는 대상일 경우, id가 1번에 해당되는 /members/{1}데이터를 삭제할 수 있습니다. 물론, 내부적으로는 해당 메서드 방식으로 구현되어 있는 삭제 기능이 구현되어야 한다는 전제 조건이 성립되어야 합니다.

하기의 코드 블럭은 순차적으로 HTML, Javascript, Java 기반의 SpringBoot 프레임워크로 구현된 POST 방식의 게시글 작성 API 예제입니다. 클라이언트단에서 사용자가 데이터를 입력하고 등록 버튼을 클릭하게 되면, 자바스크립트의 createMember() 함수가 호출되어 사용자가 입력한 데이터를 ‘name’, ‘address’으로 선언한 변수에 할당되고 JSON 형태의 포맷으로 변환합니다. 그리고 /members 에 매핑되는 메서드를 호출하여 데이터베이스에 사용자가 전달한 데이터를 저장합니다.

이처럼 우리 눈에는 보이지 않아도, 서버에서는 URI 와 메서드를 활용하여 내부적으로 어떠한 기능의 집합을 처리할 수 있도록 구현됩니다.

멤버 정보 작성 예제 UI
<button class="btn" id="sendMessageButton" type="submit"
onclick="cteateMember()"> 등록
</button>
function createMember() {
let name = $('#name').val();
let address = $('#address).val();

let data = {'name': name, 'address': address}
$.ajax({
type: "POST",
url: "/members",
contentType: "application/json",
data: JSON.stringify(data),
success: function(response) {
alert("OK!");
windows.location.reload();
}
});
}
@PostMapping("/members")
public Member createMember(@ReqeustBody MemberRequestDto requestDto) {
Member member = new Member(requestDto);
return memberRepository.save(member);
}

추가로 하기의 URL은 API를 테스트하기 위한 서비스를 제공하는 사이트인데요, API에 대한 테스트를 할 수 있어, 발표 자료를 시각화하여 작성하기 좋았습니다. 학습용으로도 추천합니다.

그리고 이러한 요청에 대한 반환과 관련된 상태 코드 값은 크게 5가지로 나누어 볼 수 있습니다.

HTTP상태 코드는 1xx 부터 5xx 까지 나누어 볼 수 있습니다. 1xx 는 정보성 상태 코드에 해당되며, 처리가 되면 다음으로 넘어갑니다. 2xx 는 요청에 대한 정상 처리를 의미하며, 3xx 는 리다이렉션과 같은 요청에 해당됩니다. 4xx 은 클라이언트에 대한 오류에 해당되며, 5xx 은 서버에 대한 오류를 의미합니다.

이처럼 상태 코드 값이라는 숫자가 클라이언트 어플리케이션에서 이해할 수 있도록 응답 메시지에 포함되어 전달 됩니다. 상태 코드의 의미는 정의되어 있지만, 다른 의미의 신호 목적으로 클라이언트에 제공될 수 있습니다. 다만, 의미에 알맞는 HTTP status를 리턴하는 부분도 REST를 활용한 API 설계 중 하나라는 점 기억 해 두세요!

HTTP의 진화

HTTP는 HTTP/0.9 버전부터 이르러 HTTP/3까지 많은 발전이 되었습니다. 잠깐 살펴 보자면 HTTP/0.9 버전에서는 GET 메서드만 지원했는데요. 당시에는 클라이언트의 정보를 서버에 전달할 방법이 없었습니다. 또한 전달 받는 데이터 유형 중 텍스트 형태만 받을 수 있었습니다. 그러나, 해당 버전 이후에는 웹을 통해 정보를 전달하는 WWW(World Wide Web)의 근간이 되어 다양한 기능들이 추가가 되기 시작했습니다.

HTTP/1.0 버전에서는 Content-Type 헤더를 통해 HTML외에도 이미지, 동영상 등과 같이 다양한 정보를 주고 받을 수 있게 되었고, POST 방식과 같은 메서드 또한 등장하게 되어 클라이언트의 정보를 웹 서버로 전달할 수 있게 되었습니다. 또한 Content-Encoding 헤더를 통해서 C/S 간 압축 정보를 공유하여 메시지 바디의 크기를 줄일 수 있게 되었습니다.

HTTP/1.1 버전에서는 GET/POST외에도 PUT/DELETE 등과 같은 다양한 메서드가 등장하게 되었고, HTTP 기반이 되는 프로토콜인 TCP의 장점이자 단점이 되는 TCP Connection에 대한 핸드셰이크의 연결 방식을 개선하기 위한 HTTP Keep Alive 또한 추가가 되어 일정 시간동안 연속된 데이터 전송이 가능토록 했습니다.

마지막으로 HTTP/2, HTTP/3는 성능 개선에 초점을 맞추었고, 기존의 HTTP/1 버전의 단점을 보완하고자 노력했습니다.

짧은 시간동안 정말 많은 부분이 개선되었는데요. 놀랍지 않나요! 먼저, HTTP 의 특징에 대해서 살펴보겠습니다.

  1. HTTP는 Stateless 방식의 무상태 프로토콜이다.

HTTP 특징 중 하나로, 해당 프로토콜은 무상태 프로토콜입니다. C/S간 요청과 응답을 주고 받으면, 연결이 끊어지게 됩니다. 따라서 클라이언트가 다시 재요청을 하게 되면 서버는 서로 상태 유지를 하지 않기 때문에 이전 요청을 기억하지 못합니다. 이러한 무상태 방식은 동일한 연결 상에서 연속하여 전달된 두 개의 요청 사이에는 연결고리가 없기 때문에 일관된 방식으로 상호작용하기를 원할 때에 문제가 됩니다.

때문에 상태 유지가 필요한 기능에는 상태 유지를 위한 추가 설계가 필요한데, 브라우저 쿠키, 서버의 세션, 인증 정보를 담는 JWT 토큰 등을 활용하여 보완할 수 있습니다.

2. HTTP의 비연결성

HTTP는 TCP 기반으로 동작하며, 한 문서 내에서 여러개의 객체를 로드하도록 되어 있을 경우, 단일 객체마다 모두 별개의 객체로 판단하여 객체마다 하나하나 지속적인 핸드셰이크 과정이 성립됩니다.

하기의 사이트를 예로 들자면, 한 페이지 내에 총 4마리의 다람쥐 이미지가 있는데요. 하나의 다람쥐 사진을 모두 브라우저에 렌더링하기 위해 이미지 파일들의 TCP 핸드셰이크 과정이 반복 된다는 점 입니다.

이처럼 내부적으로는 보이지 않아도, 웹 브라우저로 사이트를 요청하게 되면 HTML 뿐만 아니라, 해당 사이트에서 로드하도록 되어 있는 자바스크립트, CSS, 추가 이미지 등 모두 별개의 객체이기 때문에 수많은 리소스들을 로드하기 위해서 TCP Connection 과정과 Close 과정이 비효율적으로 반복되어 성능 저하 문제를 야기합니다.

HTTP1.1의 HTTP Keep Alive 지속적 연결의 등장

그래서 HTTP/1에서 처음 일정 시간동안 TCP Connection을 유지할 수 있도록 HTTP에서의 Keep Alive 기능이 등장하게 되었습니다. 이 방식은 HTTP/1.1 부터 기본적으로 활성화된 옵션인데요. 반복적인 연결을 맺는 문제점을 해소하기 위해 일정 시간동안 ESTABLISH 연결이 유지되고, 이후 능동적으로 Close 합니다. HTTP에 대한 Keep Alive는 Apache, Nginx 등의 웹 어플리케이션에서 설정된 기간까지 최대한 연결을 유지하기 위해 설정이 가능합니다. 다만, 장점 뒤에는 항상 단점이 숨어 있는 법인데요.

해당 옵션을 활성화 하는 경우에는 해당 프로세스의 수가 설정한 시간동안 유지되기 때문에 서버에서 제한된 MAXConnection 값을 초과하거나, 메모리 사용률을 초과하는 문제점이 있을 수 있습니다. 또한 지속 커넥션은 Content-Length 가 명확한 경우에만 가능합니다.

참고로 해당 부분은 HTTP/2에서 멀티플렉싱을 지원하기 때문에 별도의 설정은 필요하지 않습니다.

FIFO 방식의 HTTP/1 HOL(Head of Line) Blocking 현상과 파이프라이닝

HTTP/1 버전에서는 HTTP에서의 블로킹으로 인한 문제점도 있습니다. 자료구조에서 FIFO 방식은 처음에 들어온 데이터가 가장 먼저 처리가 되는 순차적인 데이터 처리 방식인데요, 이 데이터 처리 방식과 유사하게 HTTP에서도 한 문서 내에서 여러 객체를 로드해야 하는 경우, 맨 처음 객체가 느리게 다운로드 된다면 그 뒤에 있는 리소스들이 대기 상태가 되어 다운로드가 지연됩니다. 이처럼 HTTP요청은 순차적으로 처리가 되기 때문에 네트워크 지연과 대역폭 제한 등의 이유로 다음 요청을 보내는 데까지 상당한 딜레이가 발생할 수 있습니다.

그래서 이를 개선하고자 등장한 친구가 영속적인 커넥션을 통한 파이프라이닝 기술입니다. 이 방식은 브라우저가 웹 서버에 여러 개의 리소스를 요청했을 때에 이전 요청에 대한 응답을 완전하게 받지 않더라도 지속적 연결로 확보한 TCP 연결 내에서 미리 다음 요청에 대한 처리를 시작하면서 전체적인 전달 시간을 최소화하는 방식으로 동작해 HTTP에서의 HOLB 문제점을 해소하고자 했으나, 이 기능은 여전히 FIFO 방식으로 처리했기에 한계가 있었습니다.

또한 모든 요청이 파이프라인으로 처리가 될 수 없고, GET, HEAD, PUT과 같은 멱등성을 가진 메서드만 가능합니다. 이러한 이유들로 파이프라이닝은 더 나은 알고리즘인 멀티플렉싱으로 대체 되었는데요, 이는 HTTP/2에서 사용됩니다.

HTTP/2로의 진화

HTTP/2 버전으로 진화하게 되면서 해당 메이저 버전에서는 텍스트 방식의 메시지가 아닌, 바이너리 프레임 포맷으로 변화했습니다. 이에따라 왕대가리 헤더도 압축이 가능해졌구요!

이처럼 HTTP/1 버전에서는 텍스트 방식으로 헤더와 페이로드가 구성되었는데요. HTTP/2부터는 바이너리 이진 형태의 프레임으로 추상화되어 헤더 프레임과 데이터 프레임으로 나누어서 이것을 하나의 스트림으로 명명하여 프로토콜을 조금 더 가볍고 유연하게 만들었습니다.

또한 하위 메이저 버전에서는 선입선출 FIFO 방식의 HOLB 현상으로 인해 먼저 요청된 리소스가 완전하게 전달이 될 때까지 다음 요청에 대한 응답은 대기 상태로 있었어야 했는데, HTTP/2 스트림이 가진 유연한 구조로 인해 서버에서 만들어진 응답 프레임들은 요청 순서와 관계 없이 만들어진 순서대로 클라이언트에 전달이 될 수 있게 되었습니다.

정리하면, 하나의 TCP 연결 상에서 다수의 클라이언트 요청과 서버의 응답이 비동기 방식으로 이루어지는 멀티플렉싱으로 인해 HTTP 하위 버전에서 발생했던 HOLB 현상은 자연스럽게 해소가 되었으나, 아쉽게도 HTTP 프로토콜이 동작하는 하위 계층의 TCP에 대한 HOLB 현상은 해소되지 못했습니다.

TCP에 대한 HOLB 현상은 어플리케이션 레벨에서의 HTTP HOLB 현상과 다른 의미이기는 하나, 결국에는 요청에 대한 병목이 생겨서 레이턴시가 지연되는 건 동일한 것 같습니다.

해당 버전을 적용하기 위한 사전 조건은 HTTP/2는 HTTPS만을 지원하기 때문에 SSL/TLS 인증서를 발급 받아야 합니다. Apache에서는 1.4.17 버전, Nginx에서는 1.9.5 버전 이상부터 지원합니다.

그렇다면.. UDP 기반으로 동작하는 QUIC 프로토콜로 변화시키자!

이와 같이 HTTP/1 그리고 HTTP/2 버전에서도 결국에는 TCP를 기반으로 하여 동작하기 때문에 TCP에 대한 HOLB 현상은 개선하지 못했습니다. 그래서 이 현상을 개선하고자 HTTP/3 버전이 개발되었고, 해당 버전에서는 기존과는 다르게 QUIC이라는 UDP 기반의 프로토콜을 사용하여 발표되었습니다.

이 방식은 TCP 기반으로 동작하지 않기 때문에 핸드셰이크 과정이 생략됩니다. 물론 QUIC도 핸드셰이크 과정을 거치지 않는 건 아닙니다. 다만, 기존 방식과는 다르게 첫번째 핸드셰이크 과정을 거칠 때에 연결 설정에 필요한 정보들도 모두 포함하여 데이터도 함께 보낸다는 점입니다.

2023년 기준, HTTP/3 버전 점유율

TCP 프로토콜의 헤더는 UDP 프로토콜에 비해 매우 뚱뚱하게 구성이 되어 있습니다. 반면, UDP 프로토콜은 TCP 헤더와 비교해보면 확실히 가벼운 구조로 구성되어 있구요. 이러한 TCP 프로토콜은 신뢰성을 확보하기 위해서 다양한 기능을 제공해주기 때문에 빠른 데이터 전송 자체에만 초점을 둔 UDP에 비해서 복잡한 구조로 이루어지는 건 어쩌면 당연한 부분이기도 합니다. 그래서 HTTP/3에서는 TCP 특성으로 인한 한계를 극복하고자 UDP 기반의 QUIC 위에 얹어 성능 개선에 초점을 두었습니다.

마치며

우리가 흔하게 접할 수 있는 HTTP 프로토콜은 HTTP/0.9 버전부터 UDP 기반의 HTTP/3에 이르기 까지 정말 빠르게 진화해왔고, 많은 부분들이 개선이 되었습니다. HTTP가 방대하기 때문에 본 글에서는 많은 내용들에 대해서 담지는 못했지만, 추후에 기회가 된다면 각 주제별로 세부적인 내용에 대해서도 정리 해 보고자 합니다!

긴 글 읽어주셔서 감사합니다.

[1]: Doa’s Engineering Blog. [Network] 인터넷에서 정보를 주고 받기 위한 HTTP란?
https://blog.naver.com/pearl097/222991823345

--

--