포스트

[Network] HTTP (1-1) - HTTP 버전 별 특징 (0.9 / 1.0 / 1.1)

Computer Science / Network

HTTP의 버전(0.9 / 1.0 / 1.1)에 대한 특징과 차이점에 대한 정리

HTTP(Hyper Text Transfer Protocol)란?

HTTP(Hyper Text Transfer Protocol)는 상당한 범위의 기능 확장이 가능하며 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜이다.

HTTP는 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜이기도 하다.

  • 클라이언트-서버 프로토콜
    (보통 웹 브라우저인) 수신자 측에 의해 요청이 초기화되는 프로토콜을 의미한다.
    하나의 완전한 문서는 텍스트, 레이아웃 설명, 이미지, 비디오, 스크립트 등을 불러온(fetched) 하위 문서들로 재구성된다.

또한 HTTP를 이용한 데이터 전달은 TCP 세션 기반에서 이루어진다. (Application 층에 존재)

이러한 HTTP는 여러 과정을 거쳐 현재의 웹의 표준으로 자리잡게 되었는데, 아래의 내용을 통해 HTTP의 역사와 함께 변천 과정에 대해 알아보고 HTTP에 적용된 기술에 대해 정리할 예정이다.

HTTP 버전의 역사

image_5

HTTP의 역사는 위와 같다.

HTTP의 시작은 1989년 팀 버너 리(Tim Berners-LEE)에 의해 제안된 인터넷의 하이퍼 텍스트 시스템이다.

HTTP/0.9 (1991, One-Line Protocol)

1
GET /mypage.html
1
2
3
<html>
  A very simple HTML page
</html>

HTTP/0.9는 One-Line Protocol로, 요청은 단일 라인으로 구성되며 리소스에 대한 Method는 GET만 존재한다.

응답 역시도 파일 내용 자체로만 구성되어 있어 극도로 단순한 것이 특징이다.

HTTP의 헤더가 없고, 오로지 HTML 파일만 전송이 가능했으며 상태 혹은 오류 코드가 없었으며, 문제가 발생한 경우에는 특정 HTML 파일을 오류에 대한 설명과 함께 보내졌다.

  • HTTP/0.9 스펙 정리
    TCP/IP 링크 위에서 동작하는 ASCII 프로토콜
    GET 메서드만 지원
    HTTP 헤더 X, 상태 코드 X
    응답도 HTML 파일 자체만 보내줌
    서버와 클라이언트 간의 연결은 모든 요청 후에 당힘

HTTP/1.0 (1996)

인터넷이 빠르게 성장하면서 1994년 W3C1가 만들어지면서 HTML의 발전을 도모하게 되었고 이와 비슷하게 HTTP 프로토콜 개선에도 초점을 맞추기 위해 HTTP-WG(HTTP Working Group)가 설립되었다.

웹 브라우저, 인터넷 인프라가 빠르게 진화하며 이제는 단순히 하이퍼 텍스트 문서 뿐만이 아닌, 멀티 미디어 데이터나 메타 데이터 등 다양하고 상세한 컨텐츠가 필요해짐으로써, 기존의 HTTP/0.9로는 다양한 요구사항들을 채울 수 없는 한계에 봉착하게 되었다.

그러던 중에 1996년 HTTP-WG는 HTTP/1.0 구현의 일반적인 사용을 문서화한 RFC 1945를 발표한다.

HTTP/1.0의 특징

RFC 1945는 어려울 것 없이 HTTP/1.0 프로토콜 통신 스펙에 관한 기술 문서 정도로 이해하면 된다.

컨텐츠 인코딩, 다양한 글자 지원, 멀티파트 타입, 인가, 캐싱, 프록시, 날짜 형식 등을 문서화했다.

이는 아래와 같은 굉장히 익숙한 형태의 요청과 응답 포맷으로 구성되었다.

1
2
GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
1
2
3
4
5
6
7
8
9
200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html

<HTML>
A page with an image
  <IMG SRC="/myimage.gif">
</HTML>

Request 메시지에는 GET 요청이 시작되는 줄에 PATH와 HTTP 버전, 그리고 다음 줄로 이어지는 헤더값을 가지며, Response 메시지에는 200 OK 이후 응답 상태로 이어지는 응답 헤더값을 가지는 것을 볼 수 있다.

이와 같이 HTTP/1.0은 이른바 HTTP 포맷 형태의 시초라고 보면 된다.

  • HTTP/1.0 스펙 정리
    기본적인 HTTP 메서드와 요청/응답 헤더 추가
    HTTP 버전 정보가 각 요청 사이 내로 전송되기 시작 (HTTP/1.0이 GET 라인에 붙는 형태)
    상태 코드(Status Code)가 응답의 시작 부분에 붙어서 전송되며, 브라우저가 요청에 대한 성공과 실패를 알 수 있고 그 결과에 대한 동작을 할 수 있게 되었다. (특정 방법으로 로컬 캐시를 갱신하거나 하는 등…)
    응답 헤더의 Content-Type 덕분에 HTML 파일 형식 외에 다른 문서들을 전송하는 기능이 추가되었다.
    단기 커넥션
    • Connection 하나 당, 1 Request & 1 Response 처리 가능

HTTP/1.0의 문제점

Short-lived Connection

image_6

HTTP/1.0의 문제점은 비연결성(Connectionless)로 인한 단기 커넥션(Short-lived Connection) 특징이다.

즉, 커넥션 하나 당, 하나의 요과 하나의 응답 처리가 가능한 것을 말하는데, 서버에 자원을 요청할 때마다 매번 새로운 연결을 해줘야 했다.

  • 1 Request & 1 Response
  • 매번 새로운 연결로 인한 성능 저하
  • 매번 새로운 연결로 서버 부하 비용 증가

예를 들어, 웹 페이지를 요청하면 HTML과 그에 딸린 CSSJavaScript 및 이미지 등의 수많은 자원들이 다운로드되고 화면에 띄워지는데 각 자원들을 매번 따로 TCP 연결하고 다운받고 연결 끊고 하는 과정을 자원만큼 반복하는 것이다.

그래서 HTTP 초기에는 모든 자료에 대해서 비연결성으로 각각의 자원에 대해 연결 → 응답 → 종료를 반복하다보니, 느렸다.

HTTP/1.1 (표준 프로토콜의 등장, 1997)

HTTP/1.0의 몇 가지 단점을 보완하기 위해 HTTP/1.0이 출시된지 얼마 안된 6개월 만인 1997년 1월에 공식적으로 HTTP/1.1이 발표된다.

현재 가장 많이 쓰이는 프로토콜 버전으로, 우리가 HTTP를 학습할 때 배우는 가장 기본이 되는 지식이다.

HTTP/1.1 표준은 이전 버전에서 발견된 많은 프로토콜의 모호성을 해결하고 몇 가지 중요한 성능 개선을 도입했다.

  • HTTP/1.1에서 보완된 특징
    지속 연결 (Persistent Connection)
    • 지정한 timeout 동안 연속적인 요청 사이에 커넥션을 닫지 않으며, 기존 연결에 대해서 Handshake 생략이 가능
  • 파이프라이닝 (Pipelining) → 현재 불안정하여 사장됨
    이전 요청에 대한 응답이 완전히 전송되기 전에 다음 전송을 가능하게 하여 여러 요청을 연속적으로 보내 그 순서에 맞춰 응답을 받는 방식으로 지연 시간을 줄인 방식
  • Host 헤더 추가
    동일한 IP 주소에 다른 도메인을 호스트 가능
  • Chunk Encoding 전송
    응답 조각
  • 기타 보완된 점
    바이트 범위 요청
    캐시 제어 메커니즘 도입

Persistent Connetion (keep-alive)

HTTP는 TCP 연결 기반 위에서 동작하는 프로토콜로 신뢰성 확보를 위해 연결을 맺고 끊는 데 있어서 #TCP VS UDP - 3-Way Handshake가 이뤄진다.

그런데 HTTP는 기본적으로 비연결성(Connectionless) 프로토콜이기 때문에 한번의 요청과 응답을 하고 응답이 끝나면 연결을 끊어버리는데, 자원을 요청할 때마다 연결을 맺고 끊어버려서 오버헤드2가 생기게 된다.

이러한 현상을 보완하기 위해 HTTP/1.1에서 Persistent Connection 기능이 추가됨으로써, 한 번 맺어졌던 연결을 끊지 않고 지속적으로 유지해 불필요한 Handshake를 줄여 성능을 개선하였다.

image_7

  • 연결을 유지함으로써 Handshake 과정을 생략해 빠르게 자원을 받아올 수 있다.
  • 불필요한 연결의 맺고 끊음을 최소화시켜 네트워크 부하를 줄일 수 있다.
  • 클라이언트 측에서 요청에 keep-alive 헤더를 담아 보내야 한다.
  • 정확한 Content-length 헤더를 사용해야 한다.
  • 하나의 Connection을 계속해서 재사용해야 하는데, 특정 요청의 종료를 판단할 수 없기 때문이다.
  • Connection 헤더를 지원하지 않은 Proxy에는 사용할 수 없다.

가끔 HTTP 지속 연결을 Persistent Connection 혹은 keep-alive Connection으로 용어를 혼용하는 경우가 있는데, 정확히는 Persistent Connection이 맞다.

keep-alive는 HTTP/1.0+ 버전이 Persistent Connection을 연결하기 위해 헤더에 명시해 사용하는 단어라고 보면 된다.

keep-alive 동작 과정

Keep-Alive의 원리는 단순하다.

지정한 timeout 동안 연결을 끊지 않게 지정해서 HTTP 요청과 응답 시, 다수의 TCP 연결 Handshake를 줄이는 것에 초점을 둔다.

HTTP/1.1부터는 keep-alive가 기본으로 세팅되어 있어서 자동으로 Persistent Connection 연결이 되지만, HTTP/1.0 Connection은 하나의 request에 응답할 때마다 Connection을 close하도록 설정되어있다.

1
2
3
GET /index.html HTTP/1.1
Host: website.org
Connection: keep-alive
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 200 OK
Date: Sat, 10 Aug 2024 07:48:28 GMT
Server: Apache/2.4.48 (Ubuntu)
Cache-Control: no-cache, private
Set-Cookie: ...
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 44498
Keep-Alive: timeout=5, max=100 # → timeout : 얼마동안 유지 / max : response 최대 개수
Connection: Keep-Alive # → keep-alive를 명시하지 않는다면 close
Content-Type: text/html; charset=UTF-8
  • max
    keep-alive를 통해서 주고받을 수 있는 request의 최대 개수이다.
    이 수보다 더 많은 요청을 주고 받을 경우에는 Connection: close 처리된다.
  • timeout
    keep-alive가 얼마동안 유지될 것인가를 의미한다.
    이 시간이 지날 동안 request가 더 이상 없을 경우, Connection: close 처리된다.

keep-alive를 이용한 통신은 위의 설정에 따라 클라이언트나 서버 중 한 쪽이 다음 헤더를 부여해 접속을 끊거나 타임아웃이 될 때까지 연결이 유지된다.

그래서 만일 필요한 자원을 모두 할당받고 더 이상 keep-alive 연결을 유지할 필요가 없을 경우, 요청 헤더에서 Connection 속성을 close로 설정해 서버로 보내게 되고, TCP 지속 연결은 끊기게 된다.

1
2
3
GET /index.html HTTP/1.1
Host: website.org
Connection: close
1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK
Date: Sun, 11 Aug 2024 02:55:39 GMT
Server: Apache/2.4.48 (Ubuntu)
Cache-Control: no-cache, private
Set-Cookie: ...
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 44496
Connection: close # → close 처리
Content-Type: text/html; charset=UTF-8

Pipelining

파이프라이닝은 여러 개의 요청을 보낼 때, 처음 요청이 응답될 때까지 기다리지 않고 바로 요청을 한 번에 보내는 것을 의미한다.

즉, 여러 개의 요청을 한 번에 보내서 응답을 받음으로서 대기 시간을 줄이는 기술이다.

이론 상으로는 좋아보이는 기술이지만, 단점이 너무나도 명확해서 현재는 사장된 기술이다.

image_8

  • keep-alive를 전제로 하며, 서버 간 요청의 응답 속도를 개선시키기 위해 적용
  • 서버는 요청이 들어온 순서대로(#FIFO) 응답을 반환한다.
  • 하지만 응답 순서를 지키기 위해 응답 처리를 미루기 떄문에 HOL(Head of Line) Blocking 문제가 발생한다.

    그래서 모던 브라우저들은 대부분 파이프라이닝을 사용하지 못하도록 막아 놓았다.

  • HTTP/2.0에서는 멀티플렉싱 알고리즘으로 대체되었다.

Domain Sharding

파이프라이닝을 대체하기 위한 차선책으로 나온 기술이며, 브라우저들은 하나의 도메인에 대해 여러 개의 Connection을 생성해서 병렬로 요청을 보내고 받는 방식으로 성능을 개선했다.

image_9

한 도메인 당, 6~13개의 TCP 연결들을 동시에 생성해 여러 리소스를 한 번에 다운로드하는 방식이다.

브라우저 종류최대 동시 연결 개수
IE 11.013
파이어폭스6
크롬6
사파리6
오페라6
iOS6
Android6

하지만 도메인의 주소를 찾기 위해 DNS Lookup 과정에서 시간을 잡아먹을 수도 있으며, 위와 같이 브라우저 별로 Domain 당 Connection 개수의 제한이 존재하여 근본적인 해결책은 아니었다.

HTTP/1.1의 문제점

HOL(Head of Line) Blocking

image_10

위에서 소개한 파이프라이닝은 어찌보면 정말 혁신적인 기술이다.

하지만, 보낸 요청의 순서에 맞게 응답을 받아야하는 규칙 부분에서 문제가 생기게 된다.

마치 #FIFO(선입선출)처럼 생각하면 되는데, 문제는 요청하는 데이터의 크기는 각각 다르기 때문에, 첫 번째로 요청한 데이터가 용량이 큰 데이터라면 두 번째, 세 번째 데이터가 아무리 빨리 처리되어도 우선 순위 원칙에 따라 첫 번째 데이터의 응답 속도가 늦어지면 후순위에 있는 데이터 응답 속도도 늦어지게 되는 현상이 발생한다.

image_11

위와 같이 첫 번째 http request에서는 요청 하나 당 응답을 받아야 다음 요청을 보내는 오래된 방법으로 time 길이가 길며, 총 시간이 오래걸린다.

그래서 pipelining을 통해 동시에 요청을 보내서 time의 길이를 줄였지만, 문제는 첫 번째 요청에 대한 응답이 오래 걸릴 경우에 그 뒤의 응답도 같이 늦어져서 결과적으로는 총 time이 길어지게 되는 비효율적인 상황이 발생하게 되는 것이다.

따라서, 위의 문제점과 더불어 구현 복잡성에 의해 파이프라이닝은 활용이 매우 제한적이었으며, 대부분의 브라우저에서는 여러 개의 TCP 연결을 만들어 병렬적으로 이용하는 방식을 많이 사용했지만, 이 역시 추가 메모리와 리소스를 낭비한다는 단점이 있었다.

RTT (Round Trip Time)

image_12

RTT(Round Trip Time)란, 요청(SYN)을 보낼 때붜 요청에 대한 응답(SYN-ACK)을 받을 때까지의 왕복 시간을 의미한다.

즉, 아무리 keep-alive라고 하지만 결국 TCP 상에서 동작하는 HTTP의 특성항 Handshake가 반복적으로 일어나게 되어, 불필요한 RTT 증가로 인한 네트워크 지연을 초래하여 성능이 저하되게 된다.

예전에는 컨텐츠가 지금처럼 많지 않았기에 큰 부담은 아니었지만, 점점 컨텐츠가 증가하면서 이러한 Latency도 부담스러워졌다.

무거운 헤더 구조와 불필요한 반복

image_13

HTTP/1.1의 헤더에는 많은 메타 정보들이 저장되어 있다.

또한, 해당 도메인에 설정된 Cookie 정보도 매 요청 마다 헤더에 포함되어 전송되기 때문에, 오히려 전송하려는 값보다 헤더값이 더 큰 경우가 비일비재 하였다.

그리고 지속 커넥션 속에서 주고 받는 연속된 요청 데이터가 중복된 헤더값을 가지고 있는 경우가 많아서 쓸데없는 메모리 자원도 낭비하게 되는 꼴이 되었다.

HTTP/1.1을 개선한 HTTP/2.0

HTTP/2.0은 기존 HTTP/1.1 버전의 성능 향상에 초점을 맞춘 프로토콜이다.

기존의 HTTP/1.1의 내부적인 통신 구조를 다른 개념으로 바꿔버렸는데, 웹 응답 속도가 HTTP/1.1에 비해 15~50% 정도 향상되었다.

image_14 해당 이미지를 통해 응답 속도를 한 눈에 비교할 수 있다.

추가적인 HTTP/2.0에 대한 내용은 다음 게시글인 #HTTP (1-2) - HTTP/2.0은 무엇이 바뀌었는가? 게시글을 참고

참고 사이트

드프 DrawingProcess - [Network] HTTP 버전 별 특징: HTTP v0.9 v1.0 v1.1 v2 v3

Semantics - HTTP (1) - version 별 특징 (0.9 / 1.0 / 2.0 / 3.0)

minu.log - HTTP/1.0, HTTP/1.1, HTTP/2.0, HTTP/3.0, and QUIC

Inpa Dev - 🌐 HTTP 0.9 ~ HTTP 1.1 까지 알아보는 통신 기술


  1. 월드 와이드 웹을 위한 표준을 개발하고 장려하는 조직으로 팀 버너스리를 중심으로 1994년 10월에 설립되었으며, W3C는 회원기구, 정직원, 공공기관이 협력하여 웹 표준을 개발하는 국제 컨소시엄이다. ↩︎

  2. 오버헤드(Overhead)는 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다. ↩︎

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.