HTTP/2의 신택스: 프로토콜 재정의
7.1 HTTP/2
달라진 점
•
stream을 사용해 바이너리 데이터를 다중으로 송수신 할 수 있는 구조로 변경
•
stream내 우선 순위 설정과 서버 사이드에서 데이터 통신을 하는 서버 사이드 푸시를 구현
•
헤더가 압축
HTTP/2에서는 헤더부 압축, 활용되지 못하던 파이프라이닝 대체 구현등이 추가되었습니다.
7.1.1 스트림을 이용한 통신 고속화
HTTP/2의 가장 큰 변화는 텍스트 기반 프로토콜에서 바이너리 기반 프로토콜로 변화했다는 점입니다. 기존엔 여러 요청들을 병렬적으로 TCP 접속을 했지만, HTTP/2에서는 Stream이라는 가상 TCP 소켓을 통해 핸드세이크 과정없이 여러 병렬화를 진행해 속도를 높일 수 있습니다.
이러한 TCP 요청들에는 공통 헤더가 있는데, Stream Identifier를 통해 각 stream을 분리해주고 있어, 같은 스트림 식별자일 시 같은 스트림에서 나온 데이터로 인식합니다.
Stream Identifier를 사용할 때 0은 에러가 나오고, 홀수는 클라이언트에서, 짝수는 서버에서 클라이언트로 통신에 사용됩니다.
가작 작은 Headers 프레임엔 다음과 같이 데이터들이 들어가게 되됩니다.
종류 : 비트가 지정 시 헤더 블록앞에 데이터가 있는것으로 판단해 바이너리 데이터를 해석
플래그
•
PADDED(0x08): 패드 길이인 8비트와 그 패드 길이로 지정된 패딩 추가
•
PRIORITY(0x20): 더미 1비트, 스트림의존관계 31비트, 중요도 8비트 데이터 추가
위에서 설명한 모든 플래그들이 설정되었을 때 헤더입니다.
HEADER 프레임, CONTINUATION 프레임은 헤더 종료 플래그를, HEADERS 프레임과 DATA 프레임은 스트림 종료 플래그를 가질 수 있습니다. 이때 헤더와 스트림이 종료되고 데이터가 계속되지 않음을 명시합니다.
7.1.2 HTTP/2의 애플리케이션 계층
프레임단위로 바꾸므로 데이터를 쉽게 프레임 단위별로 분리할 수 있어, 버퍼를 비우거나, 데이터 고속 요청등이 편리해졌습니다. 또한 Content-Length의 크기도 일정한 경우가 많아 요청에 대한 처리 비용이 많이 줄어듭니다.
7.1.3 플로 컨트롤
HTTP/2는 애플리케이션 계층이지만, 트랜스포트 층에 가까운 것을 내부에 가지고 있습니다. 이는 플로 컨트롤로 TCP 소켓과 같은 기능을 구현했습니다. 이는 통신량 제어처리에 사용되는데, 느린쪽에 대량의 패킷전송으로 인해 블록되는 현상을 방지하기 위해 사용됩니다. 이는 SETTINGS의 프레임을 사용해 초기 위도우의 크기, 최대 병렬 스트림 수, 최대 프레임 크기, 최대 헤더 리스트 크기등 매개 변수를 조정할 수 있습니다.
TCP의 Flow Control
•
Stop and wait
◦
모든 송수신 패킷에 응답이 있어야만 다음 요청이 가는 방식
•
Sliding window
◦
수신측에서 설정한 만큼 송신데이터를 조정하는 방법
TCP의 Congestion Control
송신 측의 데이터 전달과 네트워크 처리속도를 해결하기 위한 방법
•
Slow Start
◦
윈도우 크기를 2배로 늘리다 overflow 발생 시 1로 떨어뜨림
•
Fast Recovery
◦
1이 아닌 반으로 줄여 선형식으로 줄여나감
7.1.4 서버 푸시
이를 이용해 우선순위가 높은 콘텐츠를 클라이언트가 요구하기전에 전송할 수 있게되었습니다. 이는 웹페이지를 구성하는 파일을 다운로드하는 용도로 사용됩니다.
7.1.5 HPACK을 이용한 헤더 압축
헤더가 압축되는 방식으로, HTTP/2에선 정적 테이블이라는 이름으로 자주 나타나는 헤더 이름과 값을 테[이블로 가지고있어 작은 크키로도 송수신 가능합니다.
7.1.6 SPDY와 QUIC
SPDY는 HTTP/2의 전신으로 HTTP와 같은 층인 TCP 소켓상에 구현된 방식입니다. 추가적으로 UDP 소켓상에 QUIC이라는 프로토콜을 통해 핸드세이크등의 한계점을 넘어설 수 있도록 했습니다.
7.2 Fetch API
Fetch는 XMLHttpRequest처럼 서버 액세스를 하는 함수로, 다음과 같은 특징이 있습니다.
•
XMLHttpRequest보다 오리진 서버 밖으로의 액세스 등 CORS 제어가 쉬워짐
•
Promise
•
캐시 제어 가능
•
Redirect 제어 가능
•
Referrer 정책 설정 가능
•
Service Worker 내에서 이요 ㅇ가능
7.2.1 Fetch API의 기본
웹은 속도와 보안 향상 두가지 방향으로 발전해왔는데 Fetch는 보안에 속합니다.
7.2.2 Fetch API만 할 수 있는 것
캐시 제어
리다이렉트 제어
Service Worker
Service Worker 내에서 외부 서비스로 접속할 때에는 Fetch API만 사용할 수 있는 사양입니다.
7.3 server-sent events
HTML 5의 기능 중 하나로 서버에서 주기적으로 클라이언트에 응답을 보내는 방식입니다. 이때 정보를 돌려보내는 방식으로 코멧이 있어, 롱폴링을 통해 전달합니다.
7.4 웹소켓
서버와 클라이언트간 오버헤드가 적은 양방향 통신입니다.
7.4.1 웹소켓은 스테이트풀
서버의 부하를 분산시키는 방법은 여러가지가 있으나, 채팅방등의 방법은 분산을 할 수 없습니다. 따라서 HTTP 기반 로드 밸런서를 사용할 수 없어 TCP 수준의 웹소켓 대응 로드밸런스를 사용해야합니다.
7.4.2 JS의 클라이언트 API
웹소켓은 HTTP의 하위 레이어인 TCP 소켓에 가까운 기능을 제공하는 API입니다.
1.
서버가 특정 IP 주소, 포트 번호로 시작(Listen)
2.
클라이언트(브라우저)가 서버에 통신을 시작한다고 선언(Connect)
3.
클라이언트가 보낸 접속 요청을 서버가 받아들인다(Accept)
4.
서버에 소켓 클래스의 인스턴스가 넘어옴
5.
서버가 받아서 처리시 클라이언트의 소켓 인스턴스는 송신 기능, 수신 기능이 활성화
7.4.3 접속
웹소켓 통신은 프로토콜 업그레이드를 사용하는데, HTTP로 시작하고, 그안에서 프로토콜을 업그레이드해 웹소켓으로 전환합니다.
•
Sec-WebSocket-Key: 랜덤하게 선택된 16바이트 값을 BASE64로 인코딩한 문자열
•
Sec-WebSocket-Versions: 13으로 고정
•
Sec-WebSocket-Protocol: 단순 통신기능만을 제공할 때 어떤 형식을 사용할지 결정
Sec-WebSocket-Accept: Sec-Web-Socket-Key를 정해진 규칙으로 변환한 문자열로 클라이언트는 서버와의 통신 확립을 검증
Sec-WebSocket-Protocol: 클라이언트로부터 서브 프로토콜 목록을 받았을 때. ㅓ버는 그중하나를 선택
7.4.4 Socket.IO
사용 시 장점
•
웹소켓을 사용할 수 없을 때 XMLHttpReqeust에 의한 롱 폴링으로 에뮬레이션해 서버에서의 송신을 실현하는 기능
•
웹소켓 단절 시 자동으로 재접속
•
서버에서 사용할 수 있는 구현도 있어, XMLHttpRequest 통신 핸들링 가능
•
로비 기능
7.5 WebRTC
기존엔 브라우저와 서버간 통신이였다면 이는 P2P 통신입니다. 이는 TCP가아닌 UDP를 메인으로 사용하고, 사설 주소만으로 통신할 수 있는 기술도 사용됩니다.
…사용 사례 중략
7.5.4 RTCPeerConnection
•
RTCPeerConnection: 통신 경로 확보와 미디어 채널의 오픈
•
mediaDevices.getUserMedia: 카메라, 마이크와 동영상 음성 핸들링
•
RTCDataChannel: 데이터 채널 통신
7.6 HTTP 웹 푸시
웹사이트에 알림 기능을 제공합니다. 이는 RFC 8030에 규격화되어있습니다. 이는 오프라인이더라도 사용자에게 알림을 보낼 수 있어야하는데, 이는 Service Worker를 통해 구현됩니다. Service Worker는 addEventListner에 등록되어 필요시에만 실행됩니다.
사용자가 사용을 허가한다면, 푸시 서비스에 등록하고, 이때 ServiceWorker로 등록한 push 알림 이벤트를 받을 수 있습니다.