안녕하세요. Mozilla에서 소개된 HTTP의 역사 관련 글을 재구성해 보았습니다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP
HTTP란?
OSI 7계층에서 애플리케이션 계층의 프로토콜입니다. 일반적으로는 TCP 및 TLS(HTTPS) 계층 위에서 동작합니다.
UDP 위에서 동작 가능하게 된 것은 아래 기술할 것이나, HTTP/3.0 이후의 변화입니다.
특징
- 간단합니다.
HTTP/2.0 이전까지는 인코딩이 없어 사람이 읽을 수 있습니다. 크롬 개발자 도구에서 header나 payload 등으로 디버깅을 할 수 있는 것이 이 때문입니다. 또한, 2.0까지도 프레임별로 캡슐화되어 있습니다.
- 확장 가능합니다.
HTTP 헤더들 덕에 새로운 인터페이스를 쉽게 추가할 수 있었고, HTTP/0.9에서 1.0으로의 진화는 이 헤더의 공이 아주 컸습니다.
- 상태는 없지만 세션은 있습니다.
모든 요청은 항상 독립적입니다. 심지어, 동일한 연결(TCP 혹은 UDP connection)* 내에서도 그렇습니다. 그러나, 때로는 이것이 단점으로 작용하기도 하는데, 이것을 대체하고자 하는 기술이 쿠키 혹은 세션입니다. 경우에 따라, 필요한 기술을 적용하여 사용할 수 있습니다.
HTTP 요청/응답 이전에는 항상 TCP/UDP connection이 맺어져야 합니다. 이 connection이 열려있어야 요청과 응답이 오갈수 있으며, connection이 열려있는 한, 오갈 수 있는 요청/응답의 제한은 없습니다.
HTTP에 기반한 API
- XHR
XMLHttpRequest의 약칭입니다. XML은 HTML과 같은 데이터 교환을 위해 등장한 마크업 언어입니다. XHR을 본래 XML을 위해 탄생하였으나, XML 외의 데이터들도 다룰 수 있습니다.
- Fetch API
일반적으로 XHR보다 유연한 상위호환이라고 봐도 무방합니다. 두 api의 차이점은 링크를 참고하세요
- SSE(Server-sent events)
클라이언트 쪽에서 연결을 맺고(EventSource), 이벤트 핸들러를 설정해두면, 서버에서 일방적으로 이벤트를 수신받아 처리할 수 있는 방법입니다. 웹소켓과 유사하나 차이점에 대해서는 링크 를 참고하세요.
- Websocket
일반적으로 SSE보다 유연한 형태의 API인 것으로 보입니다. 서버와 클라이언트간 connection이 맺어져 있으면, 서버, 클라이언트 할 것없이 양방향으로 요청이 가능합니다.
HTTP의 진화
HTTP/0.9
극초기의 HTTP의 형태이며, 0.9라는 이름도 1.0 등장 후에 편의상 붙인 버저닝입니다.
- GET 밖에 없음
- 1 TCP connection에 1개의 request만 날릴 수 있음
- 응답은 HTML 파일 자체로만 가능함
- request
GET /mypage.html
- response
<HTML>
A very simple HTML page
</HTML>
HTTP/1.0
- 헤더가 탄생합니다. 이로써 오늘날의 다양한 HTTP의 부가기능들이 추가 가능하게 되었습니다. 특히, Content-type 헤더를 통해 HTML 외의 파일들이 전송 가능해졌습니다.
- HTTP 버전 정보가 요청/응답에 담기게 되었습니다.
- 200 과 같은 상태 코드가 추가되었습니다.
GET /myimage.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
200 OK
Date: Tue, 15 Nov 1994 08:12:32 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/gif
(image content)
오늘날 우리가 알고 있던 HTTP와 거의 흡사해졌습니다.
HTTP/1.1
1.0과의 가장 두드러지는 차이는, 하나의 TCP connection안에서 수차례의 요청/응답이 오갈 수 있게 되었다는 것입니다. 이와 관련한 두가지 모델이 있습니다. Persistent Connection 모델과 HTTP pipelining입니다.
Persistent Connection
단일 TCP connection 내에서, 수차례의 요청/응답을 처리하는 가장 기본적인 모델입니다.
위 그림에서 open과 close는 각각 TCP connection의 열림과 닫힘을 의미합니다. Persistent Connection 모델에서는 한 번 open한 connection 위에서 여러번의 client-server간 통신이 일어납니다.
사실 이 모델은 HTTP/1.0부터 헤더를 통해서 슬슬 쓰이기 시작하던 모델입니다. Client와 server가 Connection: keep-alive
헤더를 주고 받음으로써 TCP connection의 close는 일어나지 않고 connection이 유지됩니다. 그러다, client와 server 중 하나가 Connection: close
헤더를 담아 보내면 connection은 close 됩니다.
HTTP/1.1에서는 헤더를 통해 connection을 조절하지 않아도, 기본적으로 client, server 모두에서 Persistent Connection을 지원하는 것으로 변경되었습니다. Connection은 브라우저에 따라 5~15초 간 유지됩니다. 불필요한 서버의 리소스를 낭비할 필요는 없기에 이 시간이 지나면 close를 하긴 해야합니다. client의 요청이 날아가는 새에 server와의 connection이 끊겼을 때는 408 상태 코드를 받아 볼 수 있습니다.
이로써, Persistent Connection 모델은 기본적인 HTTP 통신 규약이 되어, 후에, HTTP/2.0에서는 Connection 헤더 자체를 금지하게 됩니다. 링크
HTTP pipelining
HTTP pipelining에서는 Persistent Connection 모델에서 한단계 더 나아가, client가 server의 응답을 기다리지 않고 다음 요청을 날릴 수 있습니다. 이 모델은 HTTP/1.1에서 처음 제시되었습니다. 응답을 기다릴 필요가 없으니, client은 더 많은 요청을 더 빠른 시간내에 응답받을 수 있습니다. HTTP/1.1은 지금까지도 가장 일반적으로 통용되는 HTTP 버전입니다.
그러나 충분히 강력해보이는 HTTP pipelining에도 결점이 있었습니다. 서버의 응답이 FIFO(first-in-first-out, 선입선출) 방식으로 동작한다는 것이였습니다. 모든 응답은 서버에 들어온 요청 순서대로, 먼저 들어온 요청이 먼저 응답되는 것입니다. 그렇기에 먼저 들어온 요청 중 아주 처리가 오래 걸리는 요청이 있으면, 그 다음 요청들은 무한정 기다려야하는 문제가 있었습니다. 이 문제를 HOL blocking(Head Of Line blocking) 문제라 부릅니다. 이 문제를 해결하고자 HTTP/2.0이 등장합니다.
HTTP/2.0
앞서 얘기한 HOL blocking 문제를 해결하며, 더 빠르면서도, 보안까지 챙긴 HTTP/2.0이 등장합니다. google에서 만들어진 SPDY(스피디 라고 읽습니다!) 프로토콜을 기반으로, 프레임들을 각각 바이너리화해서 더 빠르고 가벼운 형태의 프로토콜입니다. 아래의 특징들이 있으며 링크의 내용과 이미지를 재구성했습니다.
1. Binary Framing
Header 파트와 Data 파트를 각각 바이너리화 합니다. 이로써 더 가볍고 빠르게, 통신이 가능합니다. 심지어 이 두 파트를 따로따로 server에 송신하더라도 서버에서 이 두 파트를 알아서 조립하여 응답합니다.
2. Multiplex Streaming
하나의 TCP connection 내에서, 여러개의 stream이 생겨, 병렬적인 요청/응답이 가능합니다. 위 그림에서 client는 stream1과 3을 통해 요청을 하고, stream 5를 통해 응답받았습니다.
3. 요청들의 우선순위 설정 가능
HOL blocking을 해결합니다.
4. 헤더 압축
여러 요청들 간에 헤더들은 중복되기 마련인데, 이 중복된 헤더들을 압축해서 재사용합니다.
5. server push
본래, 완성된 페이지를 받아오기 위해 client가 server에 HTML, CSS, Javascript 파일들을 각각 요청했다면, HTTP/2.0에서는 client가 HTML을 요청한 시점에 눈치껏 CSS와 Javascript 파일도 묶어서 함께 응답합니다.
(6). TLS
HTTP/2.0의 공식적인 규약은 아니나, 대부분의 메이져한 브라우저들은 HTTP/2.0은 TLS(HTTPS)위에서만 동작하도록 강제합니다. 이 또한 보안의 이점이 있습니다.
HTTP/2.0을 통해 더 원활한 서버-클라이언트 통신이 가능해졌으나, 여전히 단일 스트림 내에서는 HOL blocking 문제가 동일하게 발생할 수 있습니다. 이것 조차 해결하고자 QUIC가 등장합니다.
HTTP/3.0과 QUIC
QUIC(Quick UDP Internet Connection)는 UDP 위에서 동작하는 프로토콜로, 이 프로토콜을 통해 동작하는 HTTP를 HTTP/3.0이라 부릅니다. TCP에 비해 UDP의 장점인, 빠른 핸드쉐이크(Connection 맺음)가 장점이며, HTTP/2.0의 multiplex streaming 기능 또한 개선하여, HOL blocking 문제로부터 좀 더 쾌적합니다.
'개발이야기' 카테고리의 다른 글
Node.js에서 csv 파일 다루기 및 ios-윈도우 간 한글 깨짐 문제 해결 (1) | 2024.01.06 |
---|---|
타입스크립트: ts2322 error 해결을 위한 서브타입 관련 개념 총정리 (1) | 2023.11.26 |
한글의 유니코드 인코딩과, javascript에서 한글 문자열을 다루는 방식 (1) | 2023.10.19 |
데코레이터(Decorator) (0) | 2023.09.05 |
Artillery와 함께, 웹 부하테스트 빠르게 익히기 (0) | 2023.08.12 |