티스토리 뷰
HTTP/1.x
문제점
- Head-Of-Line Blocking
- 모든 요청이 FIFO로 처리되기 때문에 요청이 blocking 되는 문제
- RTT(Round Trip Time) 증가
- 매번 connection 별로 3-way-handshake로 인한 네티워크 지연 초래
- 무거운 Header
- 매요청 마다 중복되는 헤더 정보 전송로 인한 header 크기 증가
- 메타데이터는 항상 일반 텍스트로 전송되고, 전송당 500~800바이트의 오버헤드가 추가
- HTTP 쿠키를 사용할 경우 수 KB가 추가되기도 함
해결 시도
- Image Spriting
- 여러 이미지를 하나의 이미지로 만들어 사용하는 방법
- 네트워크 통신은 줄지만 이미지 크기가 커지는 문제
- Domain Sharding
- 도메인 별로 connection을 생성해서 병렬로 요청
- 브라우저 별로 도메인당 connection 개수 제한 존재
- Minified
- CSS, JS등 코드 공백 등을 없애 데이터 용량을 줄이는 방법
- Load Faster
- HTML 변경으로 해결해보려는 방법
- 스크립트 위치 변경 등
- async 및 defer 사용
- Data URI Scheme
- 문서 내 이미지를 Base64 인코딩 된 데이터로 직접 사용하는 방법
- 구글의 SPDY
- HTTP/2의 참고 규격
HTTP/2
- 어플리케이션 내에서 처리하던 HTTP/1.1 문제를 전송계층 내에서 해결할 수 있도록 한다.
- 애플리케이션을 더 빠르고, 단순하며 강력하게 만들어준다.
- 애플리케이션을 최적화하고 성능 개선할 수 있는 새로운 기회를 다양하게 제공한다.
- 이전의 HTTP 표준을 대체하는 것이 아니라 확장
- 클라이언트 서버간 데이터 서식(프레임)이 지정되는 방식과 데이터 전송 방식을 수정
- HTTP 핵심 개념 유지
목표
- 지연 시간을 줄이기
- 응답 다중화 지원
- TTP 헤더 필드의 효율적 압축을 통해 프로토콜 오버헤드를 최소화
- 요청 우선순위 지정
- 서버 푸시를 지원
방법
- 헤더 필드 압축
- 동일한 연결에서 다중 동시 교환 허용(동일한 연결에서 요청 및 응답 메시지의 인터리빙을 허용)
- 요청의 우선순위 지정을 허용함으로써 더 중요한 요청이 더 빨리 완료되도록 개선
- 바이너리 메시지 프레이밍을 사용하여 보다 효율적인 메시지 처리
바이너리 프레이밍 계층
HTTP 메시지가 캡슐화되어 클라이언트와 서버 사이에 전송되는 방식을 규정한다.
더 작은 메시지와 프레임으로 분할
바이너리 형식으로 인코딩
장점
- HOL(Head-of-Line) Block 해결
- 하나의 연결로 병렬 request, response 가능
스트림, 메시지 1 및 프레임 2 3
HTTP/2 통신은 바이너리로 인코딩 된 프레임의 세분화된 교환이다.
프레임은 특정 스트림에 속한 메시지에 매핑
모든 프레임은 단일 TCP 연결 내에서 다중화
- 모든 통신은 단일 TCP 연결을 통해 수행
- 스트림의 수는 제한이 없다
- 각 스트림에는 메시지 전달에 사용되는 고유 식별자와 우선순위 정보(optional)가 있다.
- 각 메시지는 하나의 논리적 HTTP 메시지(예: 요청 또는 응답), 하나 이상의 프레임으로 구성
- 프레임은 통신의 최소 단위
- 특정 유형의 데이터(예: HTTP 헤더, 메시지 페이로드 등)를 전달
요청 및 응답 다중화(Request and Response multiflexing)
HTTP 메시지를 독립된 프레임으로 세분화하고, 이 프레임을 인터리빙
다른 쪽에서 인터리빙 된 프레임의 헤더에 삽입된 스트림 식별자를 통해 이 프레임을 다시 조립
스트림 우선순위 지정
각 스트림이 가중치와 종속성을 갖도록 허용
- 각 스트림에는 1~256 사이의 정수 가중치
- 각 스트림에는 다른 스트림에 대한 명시적 종속성이 부여 가능
하지만
- 특정한 처리나 전송 순서를 보장하지 않는다
- 스트림의 종속성과 가중치는 전송 기본 설정을 표현하는 것이지 요구사항을 표현하는 것이 아니기 때문
- 클라이언트는 스트림 우선순위 지정을 사용하여 특정 순서로 스트림을 처리하도록 강제할 수 없다
- A와 B는 12:4 즉 3:1의 비율로 리소스를 갖는다
- 가중치보다 종속성이 우선되기 때문에 D가 C보다 리소스를 먼저 받는다
- D다음으로 C 및 E가 리소스를 받고 A와 B는 C가 받는 리소스를 3:1로 갖는다
One connection per origin
하나의 origin에 단일 연결을 사용한다.
- 동일한 연결을 재사용하여 각 TCP 연결을 더 효율적으로 사용
- 전반적인 프로토콜 오버헤드를 대폭 감소
- 클라이언트, 중개 장치 및 원본 서버 등에서 메모리와 처리량 감소
연결 수가 적다는 것은 HTTPS 배포 성능을 개선한다는 점에서 의미가 크다.
- 값 비싼 TLS Handshake 감소
- 세션 재사용 향상
- 필요한 클라이언트 및 서버 리소스 감소
흐름 제어
- TCP의 흐름 제어와 거의 동일한 문제
- HTTP/2는 TCP 내에서 다중화되기 때문에 TCP의 흐름 제어가 정교하지 않아 개별 스트림 전달을 제어하는데 필요한 애플리케이션 수준의 API를 제공 어려움
- HTTP/2는 단순한 빌딩 블록 세트를 제공하며, 이를 통해 클라이언트와 서버가 스트림 수준과 연결 수준에서 흐름 제어를 구현
- 흐름 제어는 종단 간(End-to-End) 방식이 아니라 홉(Hop-by-Hop) 방식
서버 푸시
원래 요청에 응답할 뿐만 아니라 클라이언트가 명시적으로 요청하지 않아도 서버가 추가적인 리소스를 클라이언트에 푸시 가능
HTTP/2는 엄격한 request-response 의미 체계를 탈피하여 일대다의 서버 푸시 워크플로를 지원
- 서버는 브라우저가 필요한 리소스를 알기 때문에 브라우저가 리소스를 요청하지 않아도 리소스를 전달해서 지연 시간을 더 줄일 수 있다.
- 아래와 같은 리소스 인라인처럼 client의 요청을 기다리지 않고 수동으로 문서에 인라인 처리 해당 리소스를 클라이언트에 푸시
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAA AAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==" alt="1x1 transparent (GIF) pixel" />
- 리소스 인라인과 차별되는 이점은 아래와 같다.
- 클라이언트에 의해 캐시 됨
- 다른 페이지에서 재사용
- 다른 리소스와 함께 다중화
- 서버에서 우선순위 지정
- 클라이언트에 의한 거부
- HTTP/2에서는 클라이언트가 서버 푸시의 사용 방식을 완벽하게 제어(연결 시작 시에 SETTINGS 프레임을 통해 전달되며 언제든지 업데이트 가능)
- 동시에 푸시되는 스트림의 수를 제한
- 스트림이 최초로 열릴 때 푸시되는 데이터의 크기를 제어하는 초기 흐름 제어 창을 조정
- 서버 푸시를 완전히 비활성화
- 푸시된 각 리소스는 인라인 처리된 리소스와는 다른 스트림
- 클라이언트에 의해 개별적으로 다중화, 우선순위 지정 및 처리가 가능
- 라우저에 의해 시행되는 유일한 보안 제한은 푸시된 리소스가 동일 출처 정책을 준수해야 한다는 것
PUSH_PROMISE
- 모든 서버 푸시 스트림은 PUSH_PROMISE 프레임을 통해 시작
- 푸시된 리소스를 요청하는 응답 데이터보다 먼저 전달되어야 한다
- 리소스에 대해 중복 요청이 생성되는 것을 막기 위해 클라이언트는 서버가 어떤 리소스를 푸시할지를 알아야 한다
- HTTP 헤더만 포함된 모든 PUSH_PROMISE 프레임을 상위 요소의 응답(즉, DATA 프레임)보다 먼저 전송
- 클라이언트가 PUSH_PROMISE 프레임을 수신한 후에 (RST_STREAM 프레임을 통해) 해당 스트림을 거부 가능
- 예를 들어 이미 해당 리소스가 캐시에 있을 경우
- HTTP/1.x에서 쓰는 인라인 리소스는 강제 푸시와 동일
- 클라이언트는 인라인 처리된 리소스를 개별적으로 옵트 아웃하거나 취소하거나 처리 불가능
헤더 압축
HTTP/2는 오버헤드를 줄이고 성능을 개선하기 위해 헤더 정보를 압축하기 위해 Header Table과 Huffman Encoding 기법을 사용하여 처리하는데 이를 HPACK 압축방식이라 부르며 별도의 명세서(RFC 7541)로 관리
- 헤더 필드를 Huffman 코드로 인코딩 -> 필드의 개별 전송 크기 감소
- 이전에 표시된 헤더 필드의 색인 목록을 클라이언트와 서버가 유지하고 업데이트(establishes a shared compression context)
- 이 목록을 참조로 사용하여 이전에 전송된 값을 효율적으로 인코딩
HPACK 압축 콘텍스트는 정적 및 동적 테이블로 구성
- 정적 테이블: 모든 연결에 사용될 가능성이 있는 공용 HTTP 헤더 필드를 제공(e.g., valid header names)
- 동적 테이블: 처음에는 비어있으며, 특정 연결에서 교환되는 값에 따라 업데이트
아직까지 나타나지 않은 값에 대해 정적 Huffman 코딩을 사용하고 또한 정적 테이블이나 동적 테이블에 이미 있는 값을 인덱스로 대체
HTTP/2의 request 및 response header가 HTTP/1.x 과 다른 점이 있다.(나머지는 다 같다)
- 모든 헤더 필드가 소문자
- request가 :method, :scheme, :authority, :path의 pesudo 필드로 나뉜다.
Reference
'CS' 카테고리의 다른 글
헷갈리는 network 개념 요약 (0) | 2022.02.28 |
---|---|
[Network] HTTP/3 and QUIC (0) | 2022.01.18 |
[Network] HTTP/0.9 ~ 1.1 (0) | 2022.01.03 |
[Network/OS] Network Socket(IP Socket, WebSocket) (0) | 2021.12.27 |
Interpreter VS Compiler (0) | 2021.11.26 |
- Total
- Today
- Yesterday
- Complier
- no-op
- QUIC
- thetextbook
- k8s
- HTTP/3
- Network
- 위코드
- database
- user-agent
- gitignore
- http
- Python
- go
- Git
- docker-compose
- Isolate level
- pytest
- MSA
- inflearn
- 원티드
- GitHub
- 프리온보딩
- HTTP/2
- direnv
- web_server
- 덕타이핑
- cka
- buildkit
- 창업
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |