HTTP 버전과 SPEC

HTTP에 대해 공부해보자.

HTTP 개요

  • HTTP는 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜이다.
  • HTTP는 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜이다.

HTTP 개요

  • HTTP는 애플리케이션 계층의 프로토콜로, 신뢰 가능한 전송 프로토콜이라면 이론상으로 무엇이든 사용할 수 있으나 TCP 혹은 암호화된 TCP 연결인 TLS를 통해 전송된다.

HTTP 특징

  • 클라이언트 서버 구조이다. 클라이언트는 서버에 요청(Request)을 보내고 응답(Response)을 대기한다. 이로인해 클라이언트와 서버의 관심사를 분리할 수 있고 각각을 따로 개발할 수 있게된다.

  • 무상태(Stateless) 프로토콜이다.

    간단한 예시로 특징을 보기위해 고객과 점원의 예시를 살펴보자.

    // Stateful
    고객: 이 노트북이 얼마인가요?
    점원: 100만원 입니다. (노트북 상태 유지)
      
    고객: 2개 구매하겠습니다.
    점원: 결제는 신용카드와 현금중에 어떤 걸로 도와드릴까요? (노트북, 2개 상태 유지)
      
    고객: 신용카드로 구매하겠습니다.
    점원: 200만원 결제되었습니다. 감사합니다. (노트북, 2개, 신용카드 상태 유지)
    

    먼저 Stateful한 프로토콜 예시를 보자.

    점원은 계속해서 고객이 요청했던 문맥(상태)을 보존을 하고 있고 알맞게 행동을 한다.

    // Stateless
    고객: 이 노트북이 얼마인가요?
    점원A: 100만원 입니다.
      
    고객: 2개 구매하겠습니다.
    점원B: 네? 무엇을 2개 구매하시겠어요 ?
      
    고객: 신용카드로 구매하겠습니다.
    점원C: 네? 무슨 제품을 몇개 신용카드로 구매하시겠어요?
    

    Stateless한 프로토콜 예시를 살펴보면 점원이 고객이 요청했던 문맥(상태)을 전혀 기억하지 못한다. 또한, 새 요청마다 오로지 요청한 정보에 대한 응답만 한다. 그렇기 때문에 점원은 네?와 같이 전혀 문맥을 파악하지 못하는 상황을 볼 수 있다.

    Stateless 한 프로토콜이라면 아래와 같이 매 요청마다 필요한 데이터를 넘겨줘야한다.

    // Stateless한 고객과 점원
    고객: 이 노트북이 얼마인가요?
    점원A: 100만원 입니다.
      
    고객: 노트북 2개 구매하겠습니다.
    점원B: 노트북 2개는 200만원 입니다. 신용카드, 현금중 어떤 걸로 도와드릴까요?
      
    고객: 노트북 2개를 신용카드로 구매하겠습니다.
    점원C: 200만원 결제되었습니다. 감사합니다.
    

    이러한 특성 덕분에 중간에 점원이 바뀌어도 상관없이 문맥 전달에 신경을 안써도 된다. 중간에 점원이 바뀌어도 되기 때문에 점원을 늘릴 수 있고 이는 실질적으로 서버를 증설할 수 있다는 것이다. 즉, 스케일 아웃(수평적 확장)에 유리하다.

    HTTP는 이러한 특성을 갖고있다.

    부가 설명으로 Stateless 의 단점을 얘기하면 다음과 같다.

    • 로그인과 같이 로그인 상태를 유지해야 하는 한계의 상황이 생긴다. 이에대한 해결책으로 브라우저 쿠키와 서버 세션등을 이용해서 유지한다.
    • 요청할 때마다 자원의 내용을 다 알려줘야함으로 이 비용이 크다.
  • 비 연결성(connectionless)

    • HTTP는 클라이언트와 서버의 연결을 유지하지 않는 모델이다
    • 그렇기 때문에 1시간 동안 수천명이 서비스를 사용해도 실제 서에서 동시에 처리하는 요청은 수십개 이하로 매우 작다. 즉, 서버의 자원을 매우 효율적을 사용할 수 있다.

    • 하지만 TCP/IP 연결의 경우 새로 연결을 맺어야 하기 때문에 3 way handshake 시간이 추가된다.
    • 따라서 웹 브라우저로 사이트를 요청하면 HTML 뿐만 아니라 자바스크립트, css, 추가 이미지 등 자원을 다운받을때 TCP/IP 계속 새로 연결을 하여 다운을 받아야한다.
    • 지금은 HTTP 지속 연결(Persistent Connections)으로 문제를 해결했다. ( TCP/IP 한번의 연결로 HTML, js, css 등을 다 받아 오는 것) 이후 HTTP/2와 HTTP/3에서는 다른 방식으로 더 문제를 개선했다.

HTTP 메시지

  • HTTP로 클라이언트와 서버가 통신하고자 할 때, 클라이언트가 TCP 연결을 새로 열거나 기존 연결을 재사용하여 서버에 대한 TCP 연결을 열고 HTTP 메세지를 전송하고 응답을 받고 TCP 연결을 끊거나 재사용하는 흐름으로 이루어진다.
  • HTTP 메시지는 두 가지 타입인 요청(requests)과 응답(responses)이라는 형식을 가지고 있다.
  • HTTP/1.1와 초기 HTTP 메시지는 사람이 읽을 수 있다.
  • HTTP/2에서 이 메시지들은 새로운 이진 구조 프레임 안으로 임베디드되어 헤더의 압축과 다중화와 같은 최적화가 가능하게 됐다.

요청(requests)

HTTP 요청의 예시

요청은 다음의 요소들로 구성된다.

  • HTTP 메서드

    보통 클라이언트가 수행하고자 하는 동작을 정의한 GET, POST 같은 동사나 OPTIONSHEAD와 같은 명사이다.

    일반적으로 클라이언트는 리소스를 가져오거나(GET) HTML 폼의 데이터를 전송(POST)하려고 하지만, 다른 경우에는 다른 동작이 요구될 수 있다.

  • 가져오려는 리소스의 경로

    예를 들면 프로토콜(http://), 도메인 (위 사진에서는 developer.mozilla.org), 또는 TCP 포트 (위 사진에서는 default port인 80)인 요소들을 제거한 리소스의 URL

  • HTTP 프로토콜의 버전

  • 서버에 대한 추가 정보를 전달하는 선택적 헤더들

  • POST와 같은 몇 가지 메서드를 위한, 전송된 리소스를 포함하는 응답의 Body와 유사한 본문

응답(responses)

HTTP 응답의 예시

응답은 다음의 요소들로 구성된다.

  • HTTP 프로토콜의 버전
  • 요청의 성공 여부와, 그 이유를 나타내는 상태 코드
  • 상태 코드의 짧은 설명을 나타내는 메시지 (아무런 영향력이 없다.)
  • 요청 헤더와 같은 HTTP 헤더들
  • 선택 사항으로 요청한 리소스가 포함되는 본문

HTTP의 진화와 특징

HTTP/0.9 - The one-line protocol

  • HTTP 초기 버전에는 버전 번호가 없었다. HTTP/0.9에서부터 이후에 차후 버전과 구별하기 위해 0.9로 불리게 됐다.

  • HTTP/0.9는 극히 단순하다. 요청은 단일 라인으로 구성되며 리소스에 대한 경로로 가능한 메서드는 GET이 유일했다.

    GET /mypage.html
    
  • 응답 또한 극히 단순하다. 오로지 파일 내용 자체로 구성된다.

    <HTML>
    A very simple HTML page
    </HTML>
    
  • HTTP 헤더가 없는 것을 볼 수 있는데 이는 HTML 파일만 전송될 수 있으며 다른 유형의 문서는 전송될 수 없음을 의미한다. 상태 혹은 오류 코드도 없었기 때문에 문제가 발생한 경우 특정 HTML 파일이 사람이 처리할 수 있도록 해당 파일 내부에 문제에 대한 설명과 함께 되돌려 보내졌었다.

HTTP/1.0 - Building extensibility (RFC 1945)

매우 제한적이었던 HTTP/0.9를 브라우저와 서버 모두 좀 더 융통성을 가지도록 빠르게 확장됐다.

// 일반적인 요청과 응답 예시

// 요청
GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

// 응답
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>
// 이미지 요청과 응답 예시

// 요청
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/1.0GET이 있는 라인에 들어가게됐다.)
  • 상태 코드 라인 또한 응답의 시작 부분에 붙어 전송되어, 브라우저가 요청에 대한 성공과 실패를 알 수 있고 그 결과에 대한 동작을 할 수 있게 됐다.
  • HTTP 헤더 개념이 요청과 응답 모두에 도입되어 메타데이터 전송을 허용하고 프로토콜을 극도로 유연하고 확장 가능하도록 만들었다.
  • 새로운 HTTP 헤더의 도입으로 HTML 파일들 외에 다른 문서들을 전송하는 기능이 추가됐다. (Content-Type)

HTTP/1.1 - The standardized protocol

HTTP/1.1은 HTTP의 첫번째 표준 버전이다. HTTP/1.0이 나온지 몇 달 안되서 1997년 초에 공개되었다.

1997년 RFC2068, 1999년 RFC2616, 2014년 RFC(7230~7235) 순으로 발전됐다.

현재 사용되는 HTTP에 대해서 가장 중요한 버전이다. 이후 나올 2, 3 버전은 성능 개선에 초점이 맞춰져있을 뿐이다.

HTTP/1.1은 모호한 부분을 명확하게하고 많은 개선 사항들을 도입했다.

  • 커넥션이 재사용될 수 있게 하여, 검색된 단일 원본 문서에 포함된 리소스를 표시하기 위해 연결을 여러 번 다시 여는 시간을 절약했다.
  • 파이프라이닝을 추가하여 첫번째 요청에 대한 응답이 완전히 전송되기 이전에 두번째 요청 전송을 가능하게하여 레이턴시를 낮췄다.
  • 청크된(데이터 조각인 청크의 단위로 나눈) 응답이 지원된다.
  • 추가적인 캐시 제어 메커니즘이 도입됐다.
  • 언어, 인코딩 혹은 타입을 포함한 컨텐츠 협상이 도입되어 클라이언트와 서버로 하여금 교환하고자 하는 가장 적합한 컨텐츠에 대한 동의를 가능하게 했다.
  • Host 헤더를 이용하여 동일 IP 주소에 다른 도메인을 호스트하는 기능으로 server colocation을 가능하게 한다.
// 이미지 전송 예시

GET /static/img/header-background.png HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header

200 OK
Age: 9578461
Cache-Control: public, max-age=315360000
Connection: keep-alive
Content-Length: 3077
Content-Type: image/png
Date: Thu, 31 Mar 2016 13:34:46 GMT
Last-Modified: Wed, 21 Oct 2015 18:27:50 GMT
Server: Apache

HTTP/2 - A protocol for greater performance (RFC7540)

몇 년에 걸쳐 웹 페이지는 매우 복잡해지며 웹 페이지 자체가 애플리케이션이 되었다. 보여지는 시각적 미디어 양과 상호작용을 추가하기 위한 스크립트의 양이 더 많이 증가하고 있고 더 많은 데이터들의 더 많은 요청이 이루어지고있다.

HTTP/1.1 연결은 올바른 순서로 전송되는 요청을 필요로 한다. 또한 몇몇 병렬 연결이 이론적으로 사용 가능한 경우 여전히 많은 양의 오버헤드와 복잡도가 남아있다. 2010년 전반기에, Google은 실험적인 SPDY 프로토콜을 구현하여, 클라이언트와 서버 간의 데이터 교환을 대체할 수단을 보여주었다. 응답성 증가를 입증하고 전송된 데이터 중복에 관한 문제를 해결하면서 SPDY는 HTTP/2 프로토콜의 기초로써 기여하게됐다.

HTTP/2와 HTTP/1.1의 근본적인 차이

  • 텍스트 프로토콜이 아닌 이진 프로토콜이다. 더 이상 읽을 수도 없고 수 작업으로 만들어낼 수 없다. 이러한 결점에 대한 보상으로 새로운 최적화 기술 구현이 가능하게 됐다.
  • 병렬 요청이 동일한 연결에서 다루어질 수 있는 다중화 프로토콜이다. 순서가 제거됐고 HTTP/1.x 프로토콜의 제약사양(Head Of Line과 같은 문제)을 막아준다.
  • 전송된 데이터의 중복과 이것으로부터 유발된 불필요한 오버헤드를 제거하면서 연속된 요청 사이의 매우 유사한 내용으로 존재하는 헤더들을 압축시키는 방법을 사용한다. (HPACK)
  • 서버가 사전에 클라이언트 캐시를 필요하게 될 데이터로 채워 넣도록하는 서버 푸쉬라고 불리는 메커니즘이 가능하다.

HTTP/3

HTTP/3는 기존의 HTTP/1, HTTP/2와는 다르게 UDP 기반의 프로토콜인 QUIC을 사용하여 통신하는 프로토콜이다.

QUIC의 특징

  • 한 구글 팀에서 2013년에 공식 발표한 TCP로 인해 생긴 병목을 해결하기 위해 만든 UDP 기반의 프로토콜이다.

  • HOL(Head Of Line)의 문제를 HTTP/2 에서는 Multiplexing을 이용하여 해결을 했다. 하지만 TCP 레벨에서의 HOL은 해결하지 못한다.

    TCP Head Of Line Blocking

    예를 들어 상위 레벨(애플리케이션 레벨)에서 프레임을 수신한 후 TCP는 프레임을 세그먼트로 나눈다.

    모든 것이 잘되면 모든 세그먼트는 전송한 다른 쪽 끝에 도착하게된다.

    그러나 인터넷 불안정 같은 문제로 프로세스 중에 일부 세그먼트가 손실 될 수 있게되는데, 이 때 TCP에는 전달을 보장하는 기능이 있어서 수신된 세그먼트를 버퍼에 넣고 손실 된 세그먼트의 재전송을 기다림으로써 HOLB 문제로 이어진다.

    QUIC은 이러한 문제를 UDP 프로토콜을 통해 해결한다.

프로토콜 스택의 변화

  • TLS가 QUIC 내부에서 구현되고 모든 보안 기능이 동시에 포함된다.

  • QPACK으로 HPACK을 대체하여 헤더 압축 알고리즘의 성능을 더욱 향상시켰다.

  • 패킷 헤더에서 QUIC은 연결 ID를 사용하여 대상과 소스를 표시한다.

    따라서 브라우저와 서버는 자신의 ID를 갖고 이를 통해서 IP와 포트로부터 연결을 분리하여 원활한 연결 마이그레이션을 할 수 있다.

    예를 들어 TCP 상황을 보면, 집을 떠나면 모바일이 WiFi에서 4G로 전환이 된다. IP가 변경되었으므로 TCP가 다시 연결된다. 인터넷에 다시 연결하기 전에 잠시 연결이 끊어지게된다.

    QUIC을 사용하면 연결 ID가 동일하게 유지되므로 연결이 개념적으로 유지되게된다. IP가 변경되더라도 연결은 재사용되며 재 연결 비용이 없다.

    아래와 같이 QUIC 패킷에 Destination Connection ID와 Source Connection ID이 들어가게된다.

    QUIC 패킷

Reference

https://developer.mozilla.org/en-US/docs/Web/

https://cabulous.medium.com/http-3-quic-and-how-it-works-c5ffdb6735b4

https://cottonblue.tistory.com/29

https://http3-explained.haxx.se/ko/h3/h3-h2

⤧  Next post 진정한 REST API ⤧  Previous post 토큰기반 인증방식과 세션기반 인증방식