10장 HTTP/2.0

  • HTTP/2.0 문서

    2015년 5월 RFC 7540
    2020년 2월 RFC 8740
    위 두 문서는 폐기 되고 현재 표준
    2022년 6월 RFC 9113

  • HTTP/3.0 문서

    2022년 6월 RFC 9114

HTTP/2.0의 등장배경

HTTP/1.1의 메시지 포멧은 구현의 단순성과 접근성에 주안점을 두고 최적화 되었지만, 성능은 어느 정도 희생 시킬 수 밖에 없었다.

그 중에서도 특히 latency가 가장 큰 문제였다. 이 문제를 해결하기 위해 병렬 커넥션이나 파이프라인 커넥션이 도입 되었지만 성능 개선에 대한 근본적인 해결책은 아니었다.

여전히 TCP를 사용하기에 애플리케이션 계층의 Head of Line Blocking 문제는 HTTP/1.1의 가장 큰 문제점 중 하나였다.

Latency vs Bandwidth

Latency(지연시간) : 네트워크에서 하나의 데이터 패킷이 한 지점에서 다른 지점으로 보내지는 데 소요되는 시간
일반적으로 두 네트워크 거리가 멀 때 높아지며 낮은 latency를 가지는 네트워크는 빠른 응답시간을 가진다.

Bandwidth(대역폭) : 컴퓨터 네트워크나 인터넷이 특정 시간 내에 보낼 수 있는 정보량. 초당 비트로 측정됨
넓을 수록 많은 양의 데이터를 빠르게 전송할 수 있다.

  • HTTP 1.0 vs Keep-Alive

http2-1.gif

  • HTTP 1.1의 Connection “Keep Alive(Pipelining)” vs “Keep-Alive(Multiple)”

http2-2.gif

HTTP pipelining은 하나의 커넥션을 통해 여러 request/response를 처리하는 기법이다.
하지만 첫번째 response가 지연되면 두번째, 세번째 response도 지연되는 Head of Line Blocking 문제가 발생한다.

HTTP/2.0은 문제들을 해결하기 위해 SPDY 프로토콜을 기반으로 만들어졌다.

개요

HTTP/2.0은 TCP 커넥션 위에서 동작한다. HTTP/2.0 요청과 응답은 길이가 정의된 한 개 이상의 프레임에 담긴다. 이 때 헤더는 압축되어 담긴다.
프레임에 담긴 요청과 응답은 스트림을 통해 보내진다.
하나의 커넥션 위에 여러 개의 스트림이 동시에 만들어질 수 있다.
스트림에 대한 흐름 제어와 우선순위 부여도 가능하다.
HTTP/2.0은 서버 푸쉬를 도입했다.

HTTP/1.1과의 차이점

기존에는 Plain Text로 통신을 하였으나 HTTP/2.0은 Binary로 인코딩 된 프레임을 사용한다.

http2-3.png

프레임

HTTP/2.0은 frame이라는 단위로 요청과 응답을 전송한다.

frame의 구조

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+--+---------------------------------+-----------------------+----------------------+
|R |              길이(14)            |         종류(8)        |       플래그(8)        |
+-+----------------------------------+-----------------------+----------------------+
|R|                             스트림 식별자(31)                                       |
+-+---------------------------------------------------------------------------------+
|                                   프레임 페이로드(0...)                               |
+-----------------------------------------------------------------------------------+

frame 헤더의 각 필드

  • R : 예약된 2비트 필드, 반드시 0이어야함.
  • 길이 : 페이로드의 길이
  • 종류 : frame의 종류
  • 플래그 : frame의 종류에 따라 의미가 다름
  • R : 예약된 1비트 필드, 반드시 0이어야함.
  • 스트림 식별자 : 31비트 스트림 식별자.

HTTP/2.0은 DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING, GOAWAY, WINDOW_UPDATE, CONTINUATION 이라는 총 10가지의 프레임을 지원하고 있다.

Frame 종류 Type 설명
DATA 0x00 Stream contents data전송
HEADERS 0x01 Stream open을 위한 header info 전송
PRIORITY 0x02 Stream 우선순위 정보 전송
RST_STREAM 0x03 Stream 종료를 알리는 프레임
SETTINGS 0x04 Connection 및 stream의 parameter 설정 전송
PUSH_PROMISE 0x05 Server push를 위한 header info 전송
PING 0x06 Connection 유지를 위한 Ping 전송
GOAWAY 0x07 Connection 종료
WINDOW_UPDATE 0x08 Flow control을 위한 frame
CONTINUATION 0x09 Header info 정보가 길어서 분할 전송을 위한 프레임

자세한 설명은 RFC 9113 6.Frame Definitions 참고

스트림과 멀티플렉싱

  • Stream은 HTTP/2.0 커넥션을 통해 클라이언트와 서버 사이에서 교환되는 frame들의 독립된 양방향 시퀀스이다.
  • HTTP/2.0에서는 하나의 TCP 커넥션에 여러 개의 Stream이 동시에 열릴 수 있다. 이를 통해 여러 TCP 커넥션을 열어서 TCP 커넥션을 무한정으로 만드는 것을 방지할 수 있다.
  • Stream은 우선순위를 가질 수도 있다. 하지만 의무 사항은 아니다.
  • 서버와 클라이언트는 Stream을 상대방과 협상 없이 일방적으로 만들기 때문에 시간 낭비를 줄일 수 있다.
  • HTTP/2.0 커넥션에서 한번 사용한 Stream 식별자는 다시 사용할 수 없다. 오래 사용하는 경우 식별자가 고갈될 수 있으나 이 경우에는 커넥션을 새로 맺으면 된다.
  • 동시에 여러개의 Stream을 사용하면 Stream이 블록되는 문제가 있을 수 있으나, WINDOW_UPDATE frame을 통해서 흐름 제어를 하여 Stream들이 서로 간섭해서 망가지는 것을 막아준다.

Stream Identifier(31 bit unsinged integer)

  • 한 커넥션 내에서 Stream을 구분하기 위한 식별자
  • Stream Id는 HEADERS, PUSH_PROMISE를 통해 새로운 Stream을 만들 때 할당된다.
  • 클라이언트가 초기화한 Stream은 홀수, 서버가 초기화한 Stream은 짝수로 식별자를 할당한다.
  • 새로운 Stream Id 생성이 불가능할 경우 커넥션을 새로 맺어야 한다. 새로운 커넥션을 맺을 때는 기존 커넥션에 대해 GOAWAY frame을 보내고 새로운 커넥션을 맺는다.

Stream Message frame 정리

http2-4.png

위 그림과 같이 frame 단위로 이루어진 요청과 응답 message는 하나의 Stream을 통해 전송된다.
하나의 커넥션 내에서 병렬적으로 처리된다.
하나의 커넥션에서 여러 개의 Stream이 동시에 열릴 수 있기 때문에 Stream들은 서로 간섭하지 않는다.

Multiplexing

http2-5.png

하나의 커넥션으로 동시에 여러개의 Stream을 응답 순서에 상관없이 주고 받는 것

Multiplexed stream 간 간섭을 제한하기 위해 stream들의 flow controlprioritization을 지원한다.

Flow control
  • Multiplexingstream을 사용하면 TCP 연결 사용에 대한 경합이 발생하여 Stream이 차단된다.
  • 이를 방지하기 위해 HTTP/2.0은 WINDOW_UPDATE frame을 통해 flow control을 지원한다.
Stream Priority
  • HTTP/2.0은 stream에 우선순위를 부여할 수 있다.
  • 우선 순위 체계가 좋지 않다면 HTTP/2의 성능이 저하될 수 있다.
  • 기존 RFC 7540 문서에서는 stream에 우선순위를 부여하는 방법을 정의하고 있었으나, RFC 9113 문서에서는 우선순위를 부여하는 방법을 제거하였다.
  • 그러나 여전히 상호 운용 가능하도록 HTTP/2.0은 stream에 우선순위를 부여하는 방법을 정의하고 있다.

우선 순위가 폐기된 배경

헤더 압축

http2-7.png

  • HTTP1.1에서 헤더는 압축없이 전송이 되었으나 이는 현대의 웹에 와서는 성능적 문제가 됨.
  • 이를 개선하기 위해서 HTTP/2.0에서는 HTTP 메시지의 헤더를 압축하여 전송
  • Huffman Coding을 사용하는 HPACK 헤더 압축 알고리즘을 사용
  • 헤더를 받은 수신 측은 어떤 경우에도 반드시 압축 해제를 수행해야하며, 안된다면 반드시 COMPRESSION_ERROR와 함께 커넥션을 끊어야한다.

헤더 중복 문제

http2-6.png

서버 푸시

  • HTTP/2.0은 서버가 하나의 요청에 대해 응답으로 여러개의 리소스를 보낼 수 있도록 해준다.
  • 리소스를 푸시하려는 서버는 먼저 클라이언트에게 자원을 푸시할 것임을 PUSH_PROMISE 프레임을 보내어 미리 알려주어야한다.
  • 이러한 PUSH_PROMISE를 먼저 보내는 이유는 서버가 푸시하려고 하는 자원을 클라이언트가 별도로 또 요청하는 상황을 피하기 위함이다.

서버 푸시를 사용할 때 주의점

  • 서버 푸시를 사용하기로 했더라도 중간 프락시가 전달을 안할 수도 있고 클라이언트에게 추가 리소스를 전달 할 수도 있다.
  • 서버는 오직 안전하고, 캐시가 가능하고, 본문을 포함하지 않은 요청에 대해서만 푸시할 수 있다.
  • 푸시할 리소스는 클라이언트가 명시적으로 보낸 요청과 연관된 것이어야한다.
  • 클라이언트는 반드시 서버가 푸시한 리소스를 동일 출처 정책(Same-origin policy, RFC 6454 참고) 에 따라 검사해야한다.
  • 마지막으로 서버 푸시를 끄고 싶으면 SETTINGS_ENABLE_PUSH을 0으로 설정하면 된다.

http2-8.png

서버 푸시 예시

  • Server는 stream 1로 수신된 request에 대한 응답으로 page.html 응답을 전송
  • page.html 을 수신한 client는 script.js, style.css 파일을 추가 요청할 것으로 예상하고 PUSH_PROMISE frame을 전송하여 2, 4 stream을 예약
  • Stream 1, 2, 4를 통해 page.html, script.js, style.css DATA frame을 전송

HTTP 비교 애니메이션

HTTP/1.1 통신 과정

http1.1

HTTP/2.0 통신 과정

http2.0

HTTP/2.0 + push 통신 과정

http2.0+push

알려진 보안이슈

중개자 캡슐화 공격(lntermediary Encapsulation Attacks)

  • HTTP/2.0 메시지를 중간 프락시가 HTTP/1.1 메시지로 변환할 때 메시지의 의미가 변질될 가능성이 있다.
  • HTTP/1.1 을 HTTP/2.0으로 변경할 때는 이러한 문제는 발생하지 않는다.

    긴 커넥션 유지로 인한 개인정보 누출 우려

  • HTTP/2.0은 사용자가 요청을 보낼 때의 latency를 줄이기 위해서 클라이언트와 서버 사이의 커넥션을 오래 유지하는 것을 염두에 두고 있다. 이는 개인 정보의 유출에 악용될 가능성이 높다.

참고 문서
https://datatracker.ietf.org/doc/html/rfc7540
https://datatracker.ietf.org/doc/html/rfc8740
https://datatracker.ietf.org/doc/html/rfc9113#name-prioritization
https://velog.io/@kyy806/e0c5bjic
https://velog.io/@taesunny/HTTP2HTTP-2.0-%EC%A0%95%EB%A6%AC#:~:text=HTTP%2F2%EC%97%90%EC%84%9C%EB%8A%94%20%EC%97%AC%EB%9F%AC%20%ED%8C%8C%EC%9D%BC,%EC%9D%B4%EB%9F%AC%ED%95%9C%20%EB%AC%B8%EC%A0%9C%EB%A5%BC%20%ED%95%B4%EA%B2%B0%ED%95%98%EC%98%80%EB%8B%A4.&text=TCP%20%EC%97%B0%EA%B2%B0%20%ED%95%98%EB%82%98%EB%A1%9C%20%EC%97%AC%EB%9F%AC%20%EC%9A%94%EC%B2%AD,%EC%9D%B4%20%EC%A1%B4%EC%9E%AC%20%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8B%A4
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

results matching ""

    No results matching ""