[Network] HTTP (1-1) - HTTP 버전 별 특징 (0.9 / 1.0 / 1.1)
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 버전의 역사
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 버전 정보가 각 요청 사이 내로 전송되기 시작 (HTTP/1.0이
HTTP/1.0의 문제점
Short-lived Connection
HTTP/1.0의 문제점은 비연결성(Connectionless)로 인한 단기 커넥션(Short-lived Connection) 특징이다.
즉, 커넥션 하나 당, 하나의 요과 하나의 응답 처리가 가능한 것을 말하는데, 서버에 자원을 요청할 때마다 매번 새로운 연결을 해줘야 했다.
- 1 Request & 1 Response
- 매번 새로운 연결로 인한 성능 저하
- 매번 새로운 연결로 서버 부하 비용 증가
예를 들어, 웹 페이지를 요청하면 HTML
과 그에 딸린 CSS
나 JavaScript
및 이미지 등의 수많은 자원들이 다운로드되고 화면에 띄워지는데 각 자원들을 매번 따로 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를 줄여 성능을 개선하였다.
- 연결을 유지함으로써 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
파이프라이닝은 여러 개의 요청을 보낼 때, 처음 요청이 응답될 때까지 기다리지 않고 바로 요청을 한 번에 보내는 것을 의미한다.
즉, 여러 개의 요청을 한 번에 보내서 응답을 받음으로서 대기 시간을 줄이는 기술이다.
이론 상으로는 좋아보이는 기술이지만, 단점이 너무나도 명확해서 현재는 사장된 기술이다.
keep-alive
를 전제로 하며, 서버 간 요청의 응답 속도를 개선시키기 위해 적용- 서버는 요청이 들어온 순서대로(#FIFO) 응답을 반환한다.
하지만 응답 순서를 지키기 위해 응답 처리를 미루기 떄문에 HOL(Head of Line) Blocking 문제가 발생한다.
그래서 모던 브라우저들은 대부분 파이프라이닝을 사용하지 못하도록 막아 놓았다.
- HTTP/2.0에서는 멀티플렉싱 알고리즘으로 대체되었다.
Domain Sharding
파이프라이닝을 대체하기 위한 차선책으로 나온 기술이며, 브라우저들은 하나의 도메인에 대해 여러 개의 Connection을 생성해서 병렬로 요청을 보내고 받는 방식으로 성능을 개선했다.
한 도메인 당, 6~13개의 TCP 연결들을 동시에 생성해 여러 리소스를 한 번에 다운로드하는 방식이다.
브라우저 종류 | 최대 동시 연결 개수 |
---|---|
IE 11.0 | 13 |
파이어폭스 | 6 |
크롬 | 6 |
사파리 | 6 |
오페라 | 6 |
iOS | 6 |
Android | 6 |
하지만 도메인의 주소를 찾기 위해 DNS Lookup
과정에서 시간을 잡아먹을 수도 있으며, 위와 같이 브라우저 별로 Domain 당 Connection 개수의 제한이 존재하여 근본적인 해결책은 아니었다.
HTTP/1.1의 문제점
HOL(Head of Line) Blocking
위에서 소개한 파이프라이닝은 어찌보면 정말 혁신적인 기술이다.
하지만, 보낸 요청의 순서에 맞게 응답을 받아야하는 규칙 부분에서 문제가 생기게 된다.
마치 #FIFO(선입선출)처럼 생각하면 되는데, 문제는 요청하는 데이터의 크기는 각각 다르기 때문에, 첫 번째로 요청한 데이터가 용량이 큰 데이터라면 두 번째, 세 번째 데이터가 아무리 빨리 처리되어도 우선 순위 원칙에 따라 첫 번째 데이터의 응답 속도가 늦어지면 후순위에 있는 데이터 응답 속도도 늦어지게 되는 현상이 발생한다.
위와 같이 첫 번째 http request
에서는 요청 하나 당 응답을 받아야 다음 요청을 보내는 오래된 방법으로 time
길이가 길며, 총 시간이 오래걸린다.
그래서 pipelining
을 통해 동시에 요청을 보내서 time
의 길이를 줄였지만, 문제는 첫 번째 요청에 대한 응답이 오래 걸릴 경우에 그 뒤의 응답도 같이 늦어져서 결과적으로는 총 time
이 길어지게 되는 비효율적인 상황이 발생하게 되는 것이다.
따라서, 위의 문제점과 더불어 구현 복잡성에 의해 파이프라이닝은 활용이 매우 제한적이었으며, 대부분의 브라우저에서는 여러 개의 TCP 연결을 만들어 병렬적으로 이용하는 방식을 많이 사용했지만, 이 역시 추가 메모리와 리소스를 낭비한다는 단점이 있었다.
RTT (Round Trip Time)
RTT
(Round Trip Time)란, 요청(SYN
)을 보낼 때붜 요청에 대한 응답(SYN-ACK
)을 받을 때까지의 왕복 시간을 의미한다.
즉, 아무리 keep-alive
라고 하지만 결국 TCP 상에서 동작하는 HTTP의 특성항 Handshake가 반복적으로 일어나게 되어, 불필요한 RTT
증가로 인한 네트워크 지연을 초래하여 성능이 저하되게 된다.
예전에는 컨텐츠가 지금처럼 많지 않았기에 큰 부담은 아니었지만, 점점 컨텐츠가 증가하면서 이러한 Latency도 부담스러워졌다.
무거운 헤더 구조와 불필요한 반복
HTTP/1.1의 헤더에는 많은 메타 정보들이 저장되어 있다.
또한, 해당 도메인에 설정된 Cookie 정보도 매 요청 마다 헤더에 포함되어 전송되기 때문에, 오히려 전송하려는 값보다 헤더값이 더 큰 경우가 비일비재 하였다.
그리고 지속 커넥션 속에서 주고 받는 연속된 요청 데이터가 중복된 헤더값을 가지고 있는 경우가 많아서 쓸데없는 메모리 자원도 낭비하게 되는 꼴이 되었다.
HTTP/1.1을 개선한 HTTP/2.0
HTTP/2.0은 기존 HTTP/1.1 버전의 성능 향상에 초점을 맞춘 프로토콜이다.
기존의 HTTP/1.1의 내부적인 통신 구조를 다른 개념으로 바꿔버렸는데, 웹 응답 속도가 HTTP/1.1에 비해 15~50% 정도 향상되었다.
해당 이미지를 통해 응답 속도를 한 눈에 비교할 수 있다.
추가적인 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)