HTTP1.1 의 문제점
- Http는 처음에 text, html만 실어나를 것 생각하고 만들어졌다. 하지만 방향 바뀌면서 오리지널 설계가 담지 못하는 부분 생겼다.
- 3.5세대 이동통신과 스마트폰이 전세계 인터넷의 폭발적 성장을 이끌었다.
- HoL(Head of Line)
- 줄의 머리가 통과하지 못하면 뒤에서도 통과하지 못한다. 첫번째에 대한 응답 만들지 못하면 뒤의 응답들이 다 만들어져도 못나가고 기다리고 있어야 한다.
- Fat Message Header
- http 1.1은 사람이 읽을 수 있게 되어있어서 헤더에 많은 메타 정보를 저장햇는데 앞에 있는 정보와 뒤에 있는 정보가 독립적이라 앞에 많은 것 보냈으면 뒤에도 많은 것 보내야 한다. ⇒ 중복된 Header 값 전송 (domain sharding이란 여러 개의 서브도메인을 생성하여 정적파일을 병렬로 가져옴)
- 쿠키 : 웹브라우저에 흔적 남기면 안되어 이 사람이 이전에 접속했던 흔적, 식별할 수 있는 정보를 소량으로 저장한다 -> 얘가 매 요청시마다 헤더에 포함되어 전송된다.
- 전송하려는 값보다 헤더 값이 더 큰 경우도 자주 발생한다.
- Limited priorities
- 사용자가 우선순위로 보는 내용이 있다. http1.1 은 우선순위의 개념이 없어서 화면 채우고 있는 모든 정보는 동일한 우선순위를 가진다. 상업적 목적에서 고객님이 원하는 정보를 먼저 보여줘야 한다.
- Client-driven Transmission
- 클라이언트가 서버로 정보 요청을 해야만 통신이 가능한 구조
- 클라이너트가 요청하지 않은 것을 서버가 보내는 것이 불가능하다.
HTTP/2
Google SPDY(Properietary Solution)
- 웹 컨텐츠 전송을 비표준으로 네트워크 프로토콜 오픈소스 풀었다.
- 웹 페이지 전송 지연을 줄이고 웹 보안을 개선하는 목표로 압축(데이터 용량 개선), 다중화(서비스 질 다양화), 우선순위 설정(요구하는 정보 빠르게 리턴) 등을 통한 전송 지연 감소
- SSL/TLS 암호화 되지 않은 연결 지원하지 않음.
HTTP/2의 주요 목표
- 줄어든 지연 시간
- 응답 다중화 지원
- HTTP 헤더 필드 압축 통한 프로토콜 오버헤드 최소화
- 요청별 우선순위 지정 추가 : 중요한 것 먼저 보내서 고객님이 떠나지 않도록
- 서버 푸시(지금와서는 사라짐)
- 기존 어플리케이션 수정 없는 지원(HTTP 메서드, 상태코드, URI 및 헤더 필드 등 지원)
가장 큰 변화
- text기반 전송이 아닌 binary framing 계층 도입
- TCP위에 TLS(Optional, Session Layer) 그 위에 HTTP2(안에 binary Framing layer 존재)동작
- http2안에 binary framing layer있어서 0과 1로 동작하게 해준다.
- 프레임 : 사람이 읽지 못하는 비트 레벨의 형태로 만들어진다.
Binary Framing Layer
- http1.1의 명령, 헤더 , 데이터 다 쓸 수 있다.
- 메소드 동일하게 하는데 네트워크 레벨에서 주고 받을 때 http2가 0과 1의 형태로 바꿀 뿐
- 메시지가 프레임들로 나눠서 송수신이 된다.
- 헤더 -> 헤더 프레임
- 데이터 -> 데이터 프레임
Stream, Message & Frame
스트림 : 구성된 연결 내에서 전달되는 바이트의 양방향 흐름. 하나 이상의 메시지가 전달될 수 있다.
메시지 : 논리적 요청 또는 응답 메시지에 매핑되는 프레임의 전체 시퀀스
프레임 : http/2에서 통신의 최소 단위. 각 최소 단위에는 하나의 프레임 헤더가 포함.
- 메시지가 크면 여러개의 프레임으로 쪼개진다.
- 본인이 현재 무엇을 실어나르고 있는지 정보 가지고 있다.
- 프레임 헤더는 최소한으로 프레임이 속하는 스트림을 식별
리소스 하나에 대해 스트림 만들어서 여러 개의 프레임으로 갈 수 있다.
하위 레벨에서 프레임으로 쪼개고 상위 레벨에서 스트림으로 묶는다.
req -> payload없는 리퀘스트의 경우 데이터 프레임 없고 헤더 프레임만 있다.
결국 통신상에서 주고 받는 것은 프레임들이다. 내가 어느 스트림에 속하는 프레임인지 알아야 한다. 동시다발적으로 서버와 클라이언트가 메시지 주고받는데 하나의 메시지가 크다고 해서 독점하는 것 아닌 주고받는데 있어 다른 얘가 전송 되는 것에 대한 불이익을 받지 않는다.
req, res 상위 개념이 stream 하위 개념이 frame.
동시에 송수신이 가능해 1,2,3이 갈 때 1에 대한 리스폰스가 준비되지 않아도 2,3에게 불이익이 가지 않는다.
헤더 - 보고 무엇을 해야겟구나 알고 그 정보 가지고 더 최적화 할 수 있다.
모든 통신은 클라이언트와 서버 사이에 하나의 tcp 연결만을 사용하며 전달될 수 있는 양방향 스트림의 수는 제한이 없음. tcp를 복수로 뚫지 않는다.
각 스트림에는 양방향 메시지 전달에 사용되는 고유 식별자와 우선순위 정보(선택적)가 존재.
각 메시지는 하나의 논리적인 HTTP 메시지이며 하나 이상의 프레임으로 구성됨.
frame은 송수신이 되는 통신 입장에서 최소의 단위. 큰 정보를 작게 쪼개서 동시다발적으로 가는 스트림 속에서 아이디(각 프레임의 헤더에 삽입된 스트림 식별자)가지고 재조합한다.
http1.1 에서 성능 개선 -> 클라이언트가 여러 병렬 요청 수행 : 여러 tcp 연결이 사용된다 => tcp연결의 비효율적인 사용을 초래하고 서버에 과부하 초래
HTTP/2
요청 및 응답 다중화
- 바이너리 프레이밍 계층의 다중화 기능
- 여러개에 대한 리퀘스트 주고받는데 바이너리 레벨로 해서 0101010로 데이터 양 줄인다
- 다중화해서 주고 받는데 순서 섞여서 나간다
- 클라이언트와 서버가 HTTP 메시지를 독립된 프레임으로 세분화하고 이 프레임을 인터리빙한 다음 다른 쪽에서 다시 조립.
아래에서는 3개의 병렬 스트림 존재.
클라이언트는 스트림5 전송, 서버는 스트림 1, 3 전송.
- 이 덕분에 서버가 리퀘스트를 받은 순서대로 응답을 보내지 않아도 된다.
- 단일 TCP연결을 사용하여 여러 요청/응답을 하나도 차단하지 않고 병렬로 인터리빙 할 수 있다.
- 지연 시간 줄이고 서버와 프로세스에서 네트워크 전송량을 줄인다 → 페이지 로드 시간을 줄임
- 사람이 보낸 페이지 로드 타임을 줄여서 고객이 떠나지 않도록 하는 것이 목적
- 서버 쪽 부하 & 배포 비용 절감 -> tcp 세션 줄인다
스트림 우선 순위
고객님이 궁금해 할 것을 가장 먼저 전달하고 정보 지속적으로 볼 수 있도록 함 - > 프레임이 클라이언트와 서버에 의해 인터리빙되고 전달되는 순서가 중요한 성능 고려사항이 됨.
이를 용이하게 하기 위해 HTTP/2 표준에서는 각 스트림이 연관된 가중치와 종속성을 갖도록 허용!
- 가중치 : 각 스트림은 1~256 사이의 정수 가중치가 할당될 수 있음.
- 종속성 : super, sub 상하관계 -> super 먼저 보낸다.
스트림의 종속성 및 가중치 조합을 이용하여 클라이언트가 우선 순위 지정 트리 구성하고 통신 → 서버는 이 정보 사용해서 cpu, 메모리 및 기타 리소스 할당 제어해 스트림 처리의 우선순위 지정
만약 응답 데이터가 있는 경우 서버는 우선순위가 높은 응답이 클라이언트에 최적으로 전달되도록 대역폭을 할당.
💡 점점 서버의 부하를 줄이는 방향으로 가고 있고 클라이언트는 점점 똑똑해짐.
스트림 우선 순위 지원은 다양한 종속성 및 가중치와 여러가지 리소스 유형이 존재하는 브라우저에서 그 성능을 개선하는데 중요하다.
http2프로토콜은 클라이언트가 기본 설정을 언제든지 업데이트 할 수 있도록 허용 → 브라우저 성능 최적화. 즉, 사용자 상호작용과 기타 신호에 응답하여 종속성을 변경하고 가중치를 재할당할 수 있음.
이 스트림 우선 순위는 표준에도 있는거고, 요구할 수도 있지만 서버가 반드시 보장하는 것은 아님!! 즉, 클라이언트는 스트림 우선순위 지정을 사용하여 서버에게 특정 순서대로 스트림을 처리하라고 강요할 수 없음.
One TCP connection per origin
TCP하나만 열어놓고 한다(암호화를 한개만 함). 클라이언트와 서버 사이에 오직 하나의 tcp 커넥션 유지한다. 주고받는 것 끝났다고 해도 연결 유지→ HTTP/2에서 동일한 연결을 재사용
→ 연결 수가 적으면 값비싼 TLS 핸드세이크가 줄어듬. 세션 재사용이 더 향상되며 필요한 클라이언트 및 서버 리소스가 감소.
→ 서버에서 더 적은 연결을 사용하므로 전체 연결 경로에서(서버-중개자-클라이언트) 메모리 부하나 처리량이 줄어든다.
→ 따라서 HTTP2로 전환하면 네트워크 지연 시간이 줄어들 뿐만 아니라 처리량이 개선되고 운영 비용이 줄어들게 됨.
보안 -> TLS : 암호화, 복호화 과정과 연결설정하고 해제하는 과정에서 키 생성,전달,번역 과정에서 생기는 시간의 부하가 줄어든다.
흐름 제어
흐름제어를 통해 수신단에서, 송신단의 데이터가 불필요하거나 처리가 불가능한 경우 수신단에 부담을 주는 것을 막을 수 있음.
- 동영상 스트림 도중 사용자가 이 동영상을 일시 중지하는 경우 전송을 중단할 수 있음..
- 프록시 서버의 다운스트림 속도와 업스트림의 속도가 다를 경우 데이터 전달 속도를 조절하여 제어 가능.
tcp에서의 흐름제어는 흐름제어 위한 알고리즘이 지정되어 있다.
HTTP/2 흐름 제어
- 스트림들을 다시 관리 할 수 있는 흐름 제어 제공한다.
- http2 흐름제어 특징
- 구현하기 위한 특정 알고리즘을 지정하지 않는다.
- 빌딩블록만 제공하고 이걸 어떻게 사용할지는 클라이언트,서버 개발자에게 달려있음 → 빌딩 블록을 사용하여 사용자 설정 전략을 구현하여 리소스 사용과 할당을 제어
- 흐름제어는 양방향
- 주고 받는 것에 대해 동시다발적으로 이루어진다.
- 각 수신단은 각 스트림과 전체 연결에 원하는 창 크기를 설정하도록 선택할 수 있음.
- 흐름 제어는 크레딧 기반이라서 각 수신단은 자체의 초기 연결과 스트림 흐름 제어 window(바이트 단위, 버퍼 크기)를 알림 → 이 window는 송신단인 DATA 프레임을 방출할 때마다 감소하고 수신단이 WINDOW_UPDATE 프레임을 보낼 때마다 증가.
- 흐름제어는 비활성화 될 수 없음.
- SETTINGS 프레임을 클라이언트와 서버가 http/2를 연결할 때 주고받아서 흐름제어와 관련된 창 크기를 설정한다.
- 흐름 제어 창의 기본값은 65,535 바이트로 설정되지만 데이터가 수신될 때마다 수신기가 WINDOW_UPDATE 프레임을 전송하여 최대 창 크기를 설정하고 유지할 수 있음.
- 어플리케이션 레벨에서 flexibility 가져갈 수 있다.
- tcp의 플로우 컨트롤 값은 64kb ==> 2GB까지 설정할 수 있다.
- 어플리케이션 레벨에서 상대방의 동의 없이 보낼 수 있는 양이 늘어나서 속도 높이고 기능 개선한다.
- tcp 흐름제어는 종단간 방식인 End to end, http/2의 흐름제어는 hop by hop →
- 프록시 있으면(중개자 역할)
- 클라이언트 - 프록시, 프록시 - 서버 흐름제어가 독립적으로 이루어진다.
- 이전에는 프록시가 가려져있었지만, http2부터는 프록시가 전면에 등장한다.
- 중개자가 자체적인 기준과 추론에 따라 리소스 사용을 제어하고 리소스 할당 메커니즘을 구현할 수 있음.
- 홉바이홉 - 데이터 센터 안의 서버들 간에 흐름제어로도 사용한다.
서버 푸시
- http1.1에서 서버는 요청하지 않은 데이터를 보낼 수 없었다.
- http 2부터는 클라이언트가 명시적으로 요청하지 않아도 서버가 추가적인 리소스를 클라이언트에 푸시할 수 있다.
- 서버는 사용자에게 필요할것 같은 정보의 헤더를 미리 보냄 -> promise // 클라이언트는 요청하지 않은 promise 헤더를 받을 수도 있고 거절할 수도 있음.
- 프로그래밍 하는 개발자에 의해서 다양한 시나리오로 개발할 수 있다.
- 광고와 같이 클라이언트가 요청하지 않아도 서버가 클라이언트한테 리소스 내 줄 수 있다.
- 미리 보내놔서 클라이언트가 필요로 할 때 서버에 요청하고 받으며 생기는 지연을 줄여준다.
- 사용자가 느끼는 지연 줄여야 한다. http로 작동하는 경우 하나의 웹 리소스에 많은 것이 오고간다. 하나의 페이지에서 다음 페이지로 갈 때 서버가 미리 다음 단계에서 필요할 컨텐츠 내려 놓으면 사용자 입장에서의 반응 속도가 줄어든다.
- but, 미리 내려놓은게 쓰이지 않으면 버려진다 -> 네트워크 낭비 할 수도 있지만 사용자가 빠르다고 느끼는 것이 중요하다.
동작 과정
- 서버가 이 컨텐츠를 내려야겠다고 판단 → 미리 내릴 놈은 특정 스트림으로 규정. 클라이언트는 어떤 resources를 서버가 push할려고 하는지 알아야함.(중복된 resource에 대한 요청을 피하기 위함과 delivery order 때문에). 그다음 서버에서 PUSH_PROMISE 프레임(promised resource의 HTTP 헤더들을 포함한)을 보냄. 간단한 방법은 response로 보낼 data frame앞에 frame을 달아서 보내는 것!
- 클라이언트는 PUSH_PROMISE 프레임을 받고 받을지, 거절할지 결정한다. 클라이언트는 이미 cachce에 있으면 거부 할 수 있다. via RST_STREAM : 프로미스 거절하는 프레임.
- 클라이언트가 푸시 스트림의 개수 조절하고 + 초기 플로우 컨트롤 윈도우를 조절할 수 있음(아예 disable도 가능). 이게 HTTP2 커넥션 시작전에 SETTINGS 프레임으로 통신되고 언제든지 업데이트 가능
- push되는 resource는 다 stream이고 마찬가지로 독립적으로 멀티플렉싱되고 우선순위 존재.
- 클라이언트가 정해진 조건에 의해 서버가 푸시(push resource는 stream)한다. multiplexing, 우선순위도 정해서 전해진다.
- 서비스 세션들 있지만 실질적으로 하나의 tcp 링크 안에 다 때려넣는다. 보안은 tcp 레벨에서 함
결론적으로 server push 기능은 잘 안써서 구글에서도 이 기능을 삭제한다는 걸로 알고 있음.
헤더 압축
HTTP는 header도 같이 실어나르는데 여기에는 전송할 resource 정보가 들어있음.
1.1에서는 500~800바이트 정도의 plain text가 보내줌. 가끔씩 킬로바이트까지(쿠키도 사용될 경우) 감.
- 헤더 : http1에서 평균 1kb -> 데이터 아님에도 너무 양이 크다.
- 헤더 데이터가 가져올 데이터보다 더 큰 경우도 있다.
-
- 허프만 코드를 통해 압축한다.(적게 등장하는 애들은 많은 비트, 많이 등장하는 애들은 적은 비트)
- 원본 하나 보내고 다음에는 원본 대비 달라진 부분만 추출해서 보낸다.
- http 1.1은 모든 req, res가 독립적이라 다 따로 보내지만 http2는 스트림이라는 논리적인 모델로 묶어 리퀘스트들이 독립적이지 않아 앞쪽 헤더와 뒤의 헤더를 비교하고, 동일 tcp연결의 리퀘스트 안에 있었던 헤더의 정보는 보내지 않는다.
- HTTP/1.1의 경우 헤더 중복 값을 그냥 보냈지만 HTTP/2는 Header Table 개념을 사용하여 중복 헤더를 검출하고 중복된 헤더는 index값만 전송. 중복되지 않은 Header 정보의 값은 static Huffman 인코딩 기법을 사용하여 전송.HTTP/2에서는 HPACK 알고리즘 통해서 헤더를 압축
- HPACK Header Table
- static table : 현재 보내지는 메시지와 상관없이 미리 만들어져있어서 어떠한 정보도 주고받지 않아도 만들어놓을 수 있다. 상시적으로 많이 쓰는 HTTP header 필드를 static으로 만들어놓는다.
- 고정된 거는 인덱스만 보내고 바뀐 값은 인덱스 + 바뀐 값 보낸다.
- dynamic table : empty로 초기화 되고 통신하면서 업데이트 되는 정보 들어간다.
- 단) 프로세싱 과정 늘어났다.
- static table : 현재 보내지는 메시지와 상관없이 미리 만들어져있어서 어떠한 정보도 주고받지 않아도 만들어놓을 수 있다. 상시적으로 많이 쓰는 HTTP header 필드를 static으로 만들어놓는다.
DES
- 대칭형(하나의 키만 이용) 암호방식
- 평문을 64bit로 나눠 56bit키를 이용해 64bit 암호문을 만들어내는 알고리즘
RSA
- 공개키 암호방식 (Public key encryption system)- 키를 두개 가짐 public key, private key
- 전자서명 가능한 알고리즘
'기타' 카테고리의 다른 글
CI / CD 에 대해서.. (0) | 2023.06.04 |
---|---|
QUIC HTTP/3 내용 정리 (0) | 2022.12.08 |
WebRTC 내용 정리 (0) | 2022.12.08 |
gRPC 공부 내용 정리 (0) | 2022.12.08 |
HTTP2 특징 정리 및 springboot로 테스트하기 (0) | 2022.10.08 |