컴퓨터 웹브라우저, 모바일 등 우리가 흔히 말하는 인터넷에서 http가 쓰이지 않는 곳이 없다. 지금 이 글을 써서 완료버튼을 누르게 되면 http프로토콜을 활용해서 tstory 서버에 request가 날아갈 것이다. 오늘은 이렇게 대중적으로 많이 쓰이는 http의 탄생과 역사 그리고 지금 http는 어디까지 발전해 왔는지 살펴보겠다.
사실 필자는 기술적인 것도 재밌어하지만 어떻게 탄생하게 됐는지 인문학적인 스토리도 좋아한다. http는 영국의 컴퓨터 과학자 티머시 존 버너스리 에 의해서 만들어 졌다. 놀랍게도 자신이 고안해낸 이 기술을 인터넷의 자유로운 발전을 위하여 무료로 풀게 된다.(사랑해요 버너스리) 그리고 훗날 이 공로를 인정받아 2004년 기사작위도 받게 된다. 맨유의 전감독 Sir. 알렉스 퍼거슨 마냥 Sir 버너스리 인것이다.
HTTP/0.9
Http는(HyperText Transfer Protocal)의 약자로 Hyper Text 즉 문서를 뛰어 넘는 텍스트 즉 비선형구조로 연결된 text 전송 프로토콜을 의미한다. 그래서 1991년 HTTP 첫 번째 버전인 0.9 버전일 때는 헤더라는것도 없었고 GET 메소드로 HTML 문서만 전송할 수 있는 단순한 프로토콜이었다.
<!-- HTTP request -->
GET /index.html
<!-- HTTP response -->
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to my website</h1>
<p>This is a simple web page.</p>
</body>
</html>
HTTP/1.0
1996년에 공식적으로 표준화된 프로토콜이다.
특징
GET 외에 POST, HEAD 메서드가 추가
상태코드 추가 : 응답에 상태코드를 포함하여 서버의 상태 표시
HTTP 헤더 : 요청과 응답에 다양한 헤더를 포함하여 더 많은 정보 교환이 가능 ex) 요청 및 응답 시 HTTP 버전 정보 추가, Content-Type을 통한 html 외 다른 파일 전송가능
단일연결 : 요청-응답 쌍마다 새로운 TCP 연결 사용
<!-- HTTP request -->
GET /index.html HTTP/1.0
User-Agent: ExampleBrowser/1.0
Accept: text/html
<!-- HTTP response -->
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 137
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to my website</h1>
<p>This is a simple web page.</p>
</body>
</html>
HTTP/1.0 요청-응답이 끝나면 TCP 연결이 종료 됐지만, HTTP/1.1은 Keep-Alive Header를 통해 연결이 종료 될 때가지 데이터를 주고 받을 수 있다.
PUT, DELETE, OPTIONS, TRACE 등 메서드 추가
캐시제어 메커니즘 Cache-Control 헤더를 통해 서버가 클라이언트로 하여금 서버가 보낸 데이터를 캐싱하게 하여 불필요한 데이터 전송을 줄인다
HTTP/1.1 200 OK
Cache-Control: max-age=3600
이 응답은 클라이언트에게 너 3600초간 내가 보내는 데이터 캐시하라는 응답이다. 이러한 응답은 고정된 리소스에 대해 하면 좋을 것 같다.
Host Header host 헤더 필드를 통해 가상 호스팅을 지원한다. 예를들어 나의 Nginx 서버의 설정이 아래와 같고 클라이언트가 아래와 같이 요청을 날린다면 서버는 Host header를 보고 각각 다르게 응답을 보낼 수 있다.
# Nginx Server 설정
server {
listen 80;
server_name www.example.com;
root /var/www/example.com;
index index.html;
}
server {
listen 80;
server_name www.anotherexample.com;
root /var/www/anotherexample.com;
index index.html;
}
<!-- request -->
GET /en-US/docs/Glossary/Simple_header HTTP/1.1
Host: www.example.com
GET /en-US/docs/Glossary/Simple_header HTTP/1.1
Host: www.anotherexample.com
파이프라이닝(Pipelining) 클라이언트가 서버의 응답을 기다리지 않고 데이터를 보낸다.
https://donggov.tistory.com/187
HOL(Head Of Line) Blocking 문제 클라이언트가 요청을 순서대로 던지더라도 그것을 처리하는 서버입장에서는 TCP 프로토콜상 순차적으로 차례차례 처리를 해야된다. 이렇게 되면 처음 들어온 요청에 대한 처리가 길어 질 수록 그 다음 이어지는 응답도 길어질 수 밖에 없다. 이러한 현상을 HOL Blocking 문제라고 한다.
HTTP/2
HTTP/2는 HTTP/1.1의 HOL blocking 같은 지연들과 같은 한계를 극복하기 위해 나온 프로토콜로 2015년 RFC 7540 표준화 되었다. HTTP/2의 많은 기능은 구글의 SPDY 프로토콜에 영감을 받았고 많은 부분을 차용했다.
특징
이진(binary)프로토콜 HTTP/1.1에서는 텍스트 기반으로 요청을 보냈지만 HTTP/2에서는 데이터를 바이너리로 변환하여 전송한다. 파싱이 더 빠르고 오류 발생 가능성이 낮다.
SSL/TLS 사용 https://d2.naver.com/helloworld/140351
SPDY는 TLS위에서 작동하기 때문에 HTTPS에서만 지원을 한다.
서버푸시(Server Push) 서버가 클라이언트의 요청을 예상해서 클라이언트가 필요할 데이터를 '이럴 줄 알고 준비했어' 느낌으로 보낸다. 이렇게 하면 페이지 로딩속도가 빨라지게 되지만 불필요한 트래픽을 발생 시킬 수 있으므로 리소스 선택을 잘해야한다.
헤더압축 HPAKC이라는 압축 방식을 활용하여 header에 반복되는 헤더필드를 압축한다. 출처: https://web.dev/performance-http2
다음과 같이 연속된 요청에서 헤더가 중복되면 내용을 확 줄여서 보내게 된다.
응답 다중화(Multiplexing) HTTP/2의 핵심 기술 중 하나이다. 각 요청별로 스트림을 만들어 그곳에서 frame을 주고 받는다. 각 요청마다 스트림이 생기게 되므로 각각 요청이 독립적으로 응답이 오게 되어 HOL Blocking문제를 해결 할 수 있다.
https://web.dev/articles/performance-http2?hl=ko
https://web.dev/articles/performance-http2?hl=ko
이론상 여러개의 stream을 만들 수 있지만 서버의 과부하가 있을 수 있어서 Stream의 갯수를 통제한다.
HTTP/3
최신 웹 전송 프로토콜이다. google, facebook, insta, amazon과 같은 미국 유명 잘나가는 거대 IT 기업들은 HTTP/3를 사용하고 있다. (우리의 naver는 아직 HTTP/2 이다.) HTTP/3가 나오게 된 이유는 TCP의 고질적인 문제를 해결하기 위해서다.
HTTP/2의 한계
HOLB문제
TCP 연결에서는 하나의 패킷이 손실이 되면 기 이후의 모든 패킷이 대기해야하는 문제가 발생한다. 특히 multiplexing 환경에서는 단일 TCP 연결을 공유하므로 하나의 패킷 손실이 다른 stream에도 영향을 미치게 된다.
만일 HTTP/2의 Multiplexing 환경에서 다음과 같은 요청을 클라이언트가 보낸다라고 가정해보자. 이때 네트워크 상의 이유로 DATA2의 패킷이 손실 됐다라고하면 TCP 프로토콜은 순차적인 프로토콜이므로 DATA2 패킷이 재전송 될 때까지 TCP 연결은 먹통이 된다. 즉 Multiplexing을 통해 Application 단에서는 HOLB 문제를 해결했지만 네트워크 단에서 발생하는 HOLB는 HTTP/2가 해결 하지 못한것이다.
HTTP/3는 TCP를 버리고 UDP를 기반으로 한 QUIC 프로토콜 선택
특징
UDP + 패킷 재전송 + 혼잡제어 + 흐름제어 등 직접 구현 = QUIC
QUIC는 다중 독립 Stream을 지원하며 손실된 패킷의 빠른 복구가 가능하다.
빠른 연결 설정 QUIC는 0-RTT 연결 설정을 지원하며, 첫번째 데이터 패킷이 연결 설정과 동시에 전송된다. 3-way handshake을 대체하여 초기 지연시간을 크게 단축한다.
HOLB 완전 해결 HTTP/2에서 패킷 손실 시 대기해야하는 HOLB문제를 완전 해결한다. https://www.debugbear.com/blog/http3-quic-protocol-guide
후기
사실 위와 같은 HTTP의 특징을 인지 하지 못한채 채팅서비스 프로그램을 만들었던 기억이 있다. 그 때 NGINX의 http버전 설정이 1.0으로 되어 있어서 채팅 소켓과 SSE가 계속 끊였었는데 만일 사전에 위 같은 HTTP에 대한 지식을 미리 공부 했으면 어땠을까 싶다.
개발자가 되기 위해서 공부를 하다보면 어떠한 기술 구현이 중요한게 아니라 HTTP, Network, OS와 같은 지식이 훨씬 더 중요하구나를 새삼 느끼게 된다.