HTTP 발전

Taesoo Kim·2024년 9월 29일

현재 우리가 쓰는 http로 완성되기까지 여러 단계의 스텝과 버전을 지나면서 발전해왔다!

1. HTTP 0.9

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

진짜 원시적인 프로토콜. 하지만, 기본적인 통신의 기반이 잡힌 버전.

2. HTTP 1.0

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

우리가 알고있는 대부분의 기능과 모습이 이때 정형화 되었다.

문제점 - 단기커넥션

문제는, 모든 통신에 커넥션을 새로한다는 것. -> tcp 핸드셰이크를 매번 하게 된다.

화면에 들어가는게 html, js, css, 및 이미지, 사운드, 비디오,.. 라고 생각하면 엄청난 오버헤드가 발생

3. HTTP 1.1

  • 지속 연결(Persistent connection) : 지정한 timeout 동안 연속적인 요청 사이에 커넥션을 닫지 않음. 기존 연결에 대해서 handshake 생략 가능
  • 파이프 라이닝(pipelining) : 이전 요청에 대한 응답이 완전히 전송되기 전에 다음 전송을 가능하게 하여,  여러 요청을 연속적으로 보내 그 순서에 맞춰 응답을 받는 방식으로 지연 시간을 줄이는 방식 (불안정하여 사장됨, http 2에서 멀티플랙싱으로 대체)
  • HOST 헤더 추가 : 동일 IP 주소에 다른 도메인을 호스트하는 기능 가능
  • Chunk Encoding 전송 : 응답 조각
  • 바이트 범위 요청
  • 캐시 제어 메커니즘 도입

지속 연결

핸드 셰이크를 통해 커넥션을 오픈하는 시기에 Connection, Keep-Alive를 추가해 서버와의 연결을 끊지 않고 유지할 수 있는 방법.

GET / HTTP/1.1
Host: www.example.com
Connection: keep-alive
Keep-Alive: timeout=10, max=100

반대로 Connection: close 를 사용하면 연결을 단발성으로 유지할 수 있다.

파이프라이닝

응답이 제대로 갔다는 것을 확인하지 않고, 일단 보내는 기술 -> 듣기만해도 불안정

새로 생기는 문제들 - HOLB (Head of Line Blocking)

파이프라이닝의 경우, 응답을 순서대로 보내야하는 데에서 문제가 생긴다. 만약, 서버의 작업이 많아, 먼저온 요청이 오래걸리게 된다면, 응답이 결과적으로 계속 밀리게 되는것.

4. HTTP 2.0

  • Binary Framing Layer
  • Multiplexing
  • Server Push
  • Stream Priorization

Binary Framing Layer

HTTP 1.x 는 모든 전송 메세지가 텍스트로 가는데 반해, HTTP 2에서는 binary frame으로 변경되어 헤더 및 바디 모두 압축하여 보낼 수 있다는 장점이 있다.


  • Frame : HTTP/2에서 통신의 최소 단위이며, Header 혹은 Data 가 들어있다. 
  • Message : HTTP/1.1과 마찬가지로 요청 혹은 응답의 단위이며 다수의 Frame으로 이루어진 배열 라인
  • Stream : 연결된 Connection 내에서 양방향으로 Message를 주고 받는 하나의 흐름

특히 Stream 이라는 방식을 통해 멀티플랙싱을 구현하게 된다.

멀티플랙싱

다중 Stream을 통해서 프레임을 병렬적으로 받아 하나의 메세지를 완성하는 방법.

gif가 너무 좋은데 퍼올수가 없음ㅎㅎ;;

https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-HTTP-20-%ED%86%B5%EC%8B%A0-%EA%B8%B0%EC%88%A0-%EC%9D%B4%EC%A0%9C%EB%8A%94-%ED%99%95%EC%8B%A4%ED%9E%88-%EC%9D%B4%ED%95%B4%ED%95%98%EC%9E%90

Server Push

요청이 오기 전에 예상되는 응답을 미리 보내 캐싱하는 방법.

예를 들어, index.html에 대한 요청이 왔으면, 단순히 그 응답만 처리하는게 아닌 index.css, index.js, 및 이미지들을 미리 응답으로 보내는 기술.

Stream Prioritization

특정 메세지를 빠르게 받기 위해 Stream간에 우선순위를 두는 기술.

그래서 html, js, css는 최대한 빠르게 받고, 에셋은 느리게 받아 빠르게 랜더링을 시킬 수 있게 됨

우선순위 트리를 통해서 상위 노드일수록 높은 우선순위를 갖는 구조.

문제점 - 여전한 HOLB

HOLB는 멀티플랭식/스트림 우선순위를 통해 해결한게 아니였나?

TCP만의 문제 - 오류나 유실되는 패킷을 재요청하면, 뒤에 오는 패킷의 처리가 늦어진다.

5. HTTP 3.0

그래서! 3 버전부터는 tcp를 버리고, udp 기반의 QUIC 프로토콜을 사용한다. 좀 더 엄밀히 말하면, 구글에서 TCP의 고유한 문제를 해결한 QUIC을 만들고 이를 새로 적용한 프로토콜이 http 3.0이 되겠다.

http 3.0은 http의 통신 문제보다, low network 프로토콜 개선에 중점을 두게 된다.

QUIC 프로토콜

UDP는 TCP와 다르게 데이터그램 방식을 활용해 도달하는 속도가 빠른반면, 신뢰성이 낮다고 알려져 있다. 하지만, 신뢰성이 없는 것이 아니고 설정이 안되어 있다는게 더 맞는 표현이다.

그래서, QUIC는 UDP를 사용하여 한번의 핸드셰이크를 통해 TLS 및 TCP 핸드셰이크를 모두 끝내어 연결에 필요한 시간을 최대한 단축했다.

독립 스트림

QUIC는 여러개의 독립 스트림을 통해 패킷을 병렬적으로 받을 수 있다. 하나의 패킷이 오류가 나도 해당 스트림만 작업이 중지 되는 상황이 되어 전체적인 작업이 밀리지 않는다.

네트워크 변경에도 연결 유지

보통 클라와 서버가 서로의 연결을 구분하기 위해서는 클라 IP, 포트, 서버 IP, 포트가 필요해서 만약 핸드폰으로 와이파이를 잡고 쓰다가, 데이터로 바꾸는 순간 새로운 연결이 필요해 진다. 하지만, QUIC에서는 Connection ID를 통해 서로를 식별하게 된다. 첫 연결시 서로에게 커넥션 ID가 임의로 설정이 되고, 네트워크가 달라져도 저장되어 있는 아이디를 통해 서로를 식별한다. 또한, 캐싱을 하여 오래 통신을 안해도 바로 연결 할 수 있다.

참고

http ~1.1

http 2.0

http 3.0

profile
뭔 생각을 해. 그냥 하는 거지 뭐

0개의 댓글