-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
HTTP/2.0
Overview
- 지금 HTTP/1.1을 대부분 쓰고 있고, 회사 별로 HTTP/2.0을 쓰는 곳도 있는 상황
- 그래서 HTTP/2.0과 관련해서 HTTP/1.1과 주요 차이, 보안 이슈에 대해서 내용을 다룰 예정
Why HTTP/2.0?
HTTP/1.1에서 개선 노력
- HTTP/1.1의 메시지 포맷은 구현의 단순성과 접근성에 주안점을 두고 최적화
- 커넥션 하나를 통해 요청 하나를 보내고 그에 대한 응답 하나만을 받는 방식
- 응답을 받아야만 다음 요청을 보낼 수 있기 때문에 회전 지연 발생(latency)
- 이를 해결하기 위해서 병렬 커넥션, 파이프라인 커넥션이 도입되었지만 성능 개선에 대한 해결책이 되지는 못 함
SPDY
- 결국 성능 개선을 위해 WAKA, S+M 같은 프로토콜 등이 제안되었고, 구글에서 SPDY(스피디) 프로토콜을 개발
- SPDY 는 기존 HTTP t속도를 개선하기 위해 여러 기능이 추가된 것이고, HTTP를 대체하는 프로토콜이 아니라 HTTP가 전송 계층을 통해 전송되는 방식을 재정의하는 프로토콜
- 현재는 HTTP/2.0의 이점이 더 크기 때문에 크롬에서는 2016년에 SPDY 지원 기능을 제거
- HTTP/2.0 은 SPDY를 기반으로 설계
- cf. SPDY - 위키백과, 우리 모두의백과사전
HTTP/2.0
- HTTP/2.0은 TCP 커넥션 위에서 동작
- 요청과 응답은 길이가 정의된(최대 16383바이트) 한 개 이상의 프레임에 담기고, 헤더는 압축되어 담겨짐
- 프레임들에 담긴 요청과 응답은 스트림을 통해 보내지며, 한 개의 스트림이 한 쌍의 요청과 응답을 처리
- 하나의 커넥션 위에 여러 개의 스트림이 동시에 만들어 질 수 있으므로, 여러 개의 요청과 응답을 동시에 처리하는 것이 가능
- 서버 푸시 도입 (후술)
- 하위 호환을 지원하기 위해 요청/응답 메시지의 의미를 HTTP/1.1과 같도록 유지
- ‘Content-Length’ 헤더는 HTTP/2.0에서 ‘:content-length’
HTTP/1.1과 차이점
프레임
- HTTP/2.0에서 모든 메시지는 프레임에 담겨 전송
-
프레임은 8바이트 크기의 헤더로 시작하고, 뒤이어 최대 16383바이트 크기의 페이로드가 옴
- R : 예약된 2비트 필드, 값의 의미가 정의되어 있지 않으며, 반드시 0이어야 함. 받는 쪽에서는 이 값을 무시
- 길이 : 페이로드의 길이를 나타내는 14비트, 길이에는 프레임 헤더는 포함되지 않음
- 종류 : 프레임의 종류를 나타내는 8비트
- 플래그 : 8비트 플래그
- R : 예약된 1비트 필드, 값의 의미가 정의되어 있지 않으며, 반드시 0이어야 함. 받는 쪽에서는 이 값을 무시
- 스트림 식별자 : 31비트 스트림 식별자, 0은 커넥션 전체와 연관된 프레임을 의미
-
HTTP/2.0은 DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS, PISH_PROMISE, PING, GOAWAY, WINDOW_UPDATE, CONTINUATION라는 10가지 프레임을 정의
스트림, 멀티플렉싱
-
스트림은 HTTP/2.0 커넥션을 통해 클라이언트와 서버 사이에서 교환되는 프레임들의 양방향 시퀀스 (하나 이상의 메시지 전달될 수 있음)
- 한 쌍의 HTTP 요청과 응답은 하나의 스트림을 통해 이루어짐
// HTTP/1.1 여러 요청을 보내는 flow 1. 한 TCP 커넥션을 통해 요청 전송 2. 응답이 도착할 때까지 대기 3. 응답 도착 후 다시 요청- 응답이 도착할 때까지 대기하기 때문에 지연 발생
- 이를 해결하기 위해서 여러 개의 TCP 커넥션 생성 -> 병렬
- 무작정 여러 커넥션을 만들 수 없기 때문에 파이프라인 커넥션 사용
- 다만 그다지 널리 구현되어 있지 않음
-
HTTP/2.0에서는 하나의 커넥션에서 여러 개의 스트림을 동시에 열 수 있음
-
스트림에 우선순위를 부여할 수 있기 때문에 대역폭 제한이 있는 경우 중요한 리소스를 요청하는 스트림에 더 높은 우선순위를 부여
- 다만 우선순위를 따르는 것이 의무사항이 아니기 때문에 요청이 우선순위대로 처리된다는 보장은 없음
-
HTTP/2.0 커넥션에서 한번 사용한 스트림 식별자는 다시 사용할 수 없음
- 커넥션을 오래 사용하다보면 스트림에 할당할 수 있는 식별자가 고갈되는 경우가 발생 -> 이 경우에는 다시 커넥션을 맺으면 됨
헤더 압축
- HTTP/1.1에서는 헤더는 아무런 압축 없이 그대로 전송
- 예전에는 헤더의 크기가 작았기 때문에 문제가 되지 않았지만 요즘은 하나의 웹페이지에서 많은 요청이 일어나기 때문에 헤더의 크기가 지연, 대역폭에 영향을 끼침
- 그래서 HTTP/2.0에서는 헤더를 압축하여 전송
- HPACK 명세에 정의된 헤더 압축 방법으로 압축
서버 푸시
- HTTP/2.0은 서버가 하나의 요청에 대해 응답으로 여러 개의 리소스를 보낼 수 있음
- 예를 들어 HTML을 요청 받은 서버는 함께 내려줘야 할 이미지, css, js 등의 리소스를 클라이언트에게 푸시할 수 있음
- 리소스를 푸시하려는 서버는 먼저 클라이언트에게 자원을 푸시할 것임을
PUSH_PROMISE프레임을 보내어 미리 알려주어야 함- 클라이언트가 별도로 요청하여 중복 요청되는 상황을 방지하기 위함
- 클라이언트가
PUSH_PROMISE프레임을 받게 되면 해당 프레임의 스트림은 클라이언트 입장에서예약상태가 되고, 이 상태에서 클라이언트는RST_STREAM프레임을 전송해서 푸시를 거절할 수 있음
cf. https://freecontent.manning.com/animation-http-1-1-vs-http-2-vs-http-2-with-push/
보안 이슈 (Known issue)
중개자 캡슐화 공격
- HTTP/2.0 메시지를 프락시가 HTTP/1.1로 변환할 때 메시지의 의미가 변질될 수 있음
- HTTP/1.1과 달리 HTTP/2.0는 헤더 필드의 이름과 값을 바이너리로 인코딩
- 따라서 HTTP/2.0 헤더 필드는 어떤 문자열이든 사용할 수 있음
- 따라서 위조된 필드를 사용하여 공격할 수 있음
긴 커넥션 유지로 인한 개인정보 누출 우려
- HTTP/2.0은 회전 지연을 줄이기 위해 오랫동안 커넥션을 지속
- 예를 들어 어떤 사용자가 브라우저를 사용할 때, 이전에 그 브라우저를 사용했던 사용자가 어떤 데이터를 주고 받았는지 알아낼 수 있음
- 현재 HTTP 커넥션도 동일한 문제를 가지고 있지만, 커넥션의 지속 기간이 짧기 때문에 상대적으로 위험이 덜함
