<관련 포스팅>
[네트워크] HTTPS(SSL 핸드쉐이크)

HTTP 프로토콜

HTTP(HyperText Transfer Protocol)

  • 텍스트 기반의 통신 규약으로 인터넷에서 데이터를 주고받을 수 있는 프로토콜
  • TCP/IP 5계층에서 애플리케이션 계층에 속함
  • 연결 상태를 유지하지 않는 비연결성 프로토콜
  • 서버가 클라이언트의 요청에 대한 정보를 유지하지 않음. 즉, stateless
  • 연결을 유지하지 않기 때문에 요청/응답 방식으로 동작함

 

HTTP 버전별 비교

 


RTT

RTT(Round Trip Time)

  • 패킷이 client 에서 server로 이동했다가 다시 돌아오는 왕복 시간을 의미

 

RTT 증가를 해결하기 위한 방법

  • 이미지 스플리팅
    • 많은 이미지를 다운로드받게 되면 과부하가 걸림
    • 여러 이미지가 합쳐있는 하나의 이미지를 다운로드받고, 이를 기반으로 background-image의 position을 이용하여 이미지를 표기하는 방법
  • 코드 압축
    • 코드를 압축하여 개행문자, 빈칸을 없애서 코드의 크기를 최소화하는 방법
  • 이미지 Base64 인코딩
    • 이미지 파일을 64진법으로 이루어진 문자열로 인코딩하는 방법
    • 서버와의 연결을 열고 이미지에 대해 서버에 HTTP 요청을 할 필요가 없다는 장점
    • 하지만 Base64 문자열로 반환할 경우 크기가 약 37% 커지는 단점

 


HTTP/0.9

  • HTTP 초기 버전을 구분하기 위해 부르는 버전
  • 요청은 단일 라인으로 구성되며, 리소스에 대한 메소드는 GET만 존재
  • 응답도 극도로 단순(파일 내용 자체로만 구성)
  • HTTP 헤더도 없고 HTML 파일만 전송 가능했던 것이 특징

 


HTTP/1.0

특징

  • 버전 정보와 요청 메소드가 함께 전송되기 시작
  • 메타데이터 전송을 허용하여 프로토콜을 극도로 유연하고 확장 가능하도록 개선됨
  • 상태 코드 라인도 응답에 함께 전송되면서 요청에 대한 성공과 실패를 알 수 있고 그 결과에 대한 동작을 할 수 있게됨
  • HTTP 헤더 개념이 도입되어 요청과 응답에 추가됨
  • Content-Type 도입으로 HTML 이외의 문서 전송이 가능해짐
  • GET, HEAD, POST 메소드 지원

 

한계점

  • 커넥션 하나당 하나의 요청과 응답을 처리함
  • 모든 요청에 따라 새로운 연결을 열고, 응답이 전송된 후 즉시 닫음
  • 서버로부터 파일을 가져올 때마다 TCP의 3-way handshake를 계속 발생해서 RTT가 증가하는 단점 발생

⇒ 서버에 부담이 가고 사용자 응답 시간이 길어짐

 


HTTP/1.1

특징

  • 1.0은 세션을 유지하지 않고, 1.1은 TCP 세션을 유지한다는 점이 가장 큰 차이점
  • 오늘날 가장 많이 사용되는 HTTP 버전
  • 파이프라인 연결, 압축 및 해제, 가상 호스팅, 캐시 등이 추가되어 응답 속도가 빨라지고 대역폭이 절약되는 등 성능 최적화 및 기능 향상
  • 매번 TCP 연결을 하는 것이 아니라 한 번 TCP 초기화를 한 이후 keep-alive라는 옵션으로 여러 Request-Response에 대해 동일한 연결을 재사용
  • 1.0에도 keep-alive가 있었지만 표준화되어 있지 않았고 1.1부터 기본 옵션으로 설정됨

 

연결 지속성(Persistent Connection)

  • 지정한 timeout 동안 커넥션을 닫지 않는 방법을 통해 커넥션의 사용성이 높아짐
  • 한 번의 TCP 세션에 여러 개의 요청을 보내고 응답을 수신할 수 있음
  • 즉 1.0은 Non-persistent HTTP, 1.1은 Persistent HTTP라고 할 수 있음

 

Pipelining

  • ack 신호를 받을 때까지 기다린 후 다음 데이터를 보내는 stop and wait 방식과 다르게, 송신자가 ack 신호를 받지 않아도 패킷 여러개를 보내는 방식
  • 여러 요청을 연속적으로 보내 그 순서에 맞춰 응답을 받음
  • 서버가 더이상 보낼 데이터가 없다는 메세지를 보내면 연결을 닫음
  • 하나의 커넥션에 여러 요청이 있을 뿐, 동시에 여러 요청을 처리해 응답을 보내는 것은 아님(multiplexing되지는 않음)

 

호스트 헤더(Host Header)

  • 1.0은 하나의 IP 주소에 여러 개의 도메인을 운영할 수 없어 서버의 개수가 늘어났음
  • 호스트 헤더를 통해 하나의 IP 주소에 여러 개의 도메인을 적용하는 가상 호스팅(Virtual Hosting)이 가능해짐

 

향상된 인증 절차

  • proxy-authentication, proxy-authorization 헤더가 추가됨
  • 서버와 클라이언트 사이에 프록시가 위치하는 경우 프록시가 사용자의 인증 요구가 가능해짐

 

한계점

  • HOL Blocking(Head Of Line Blocking) 
    • 네트워크에서 같은 큐에 있는 패킷이 그 첫 번째 패킷에 의해 지연될 때 발생하는 성능 저하
    • 첫 번째 Response가 지연되면 이후의 Response들도 대기하게 됨
    • 패킷이 순서대로 도착해야 하기 때문에, 하나의 TCP 연결에 1개의 스트림만 이용 가능했음
  • Header 구조
    • 연속된 요청들의 헤더 중복이 발생
    • 쿠키 등 많은 메타데이터가 들어 있고 압축이 되지 않아 무거웠음

 


HTTP/2.0

특징

  • 기존의 일반 텍스트 형식이 아니라 Binary Framing 계층을 추가
  • 메세지를 프레임 단위로 분할하여 추가적으로 바이너리로 인코딩함
  • 파싱 속도 및 전송 속도가 빠르고 오류 발생 가능성이 낮아짐
  • 모든 통신은 단일 TCP 연결을 통해 수행되며 전달될 수 있는 양방향 스트림의 수는 제한이 없음

 

데이터 단위

  • stream
    • 구성된 연결 내에서 전달되는 바이트의 양방향 흐름
    • 하나 이상의 메세지 전달 가능
    • 각 스트림에는 고유 식별자와 우선순위가 있음
  • message
    • 논리적 요청 또는 응답 메세지에 매핑되는 프레임의 전체 시퀀스
    • 각 메세지는 하나의 논리적 http 메세지이며, 하나 이상의 프레임으로 구성됨
  • frame
    • http/2.0에서 통신의 최소 단위
    • 헤더를 통해 해당 프레임이 속하는 스트림을 식별함

 

Binary Framing

  • 바이너리 프레이밍 계층은 http 메세지가 캡슐화되어 클라이언트와 서버 사이에 전송되는 방식을 규정함
  • 기존 http는 body가 문자열로 이루어졌지만, 2.0부터는 바이너리 프레이밍 계층에 이진 데이터로 전송됨(헤더는 여전히 문자열)
  • 기존과 달리 줄바꿈으로 구분되는 텍스트를 없애고, 더 작은 프레임으로 전송되게 됨

 

Multiplexed Streams(응답 다중화)

https://m.blog.naver.com/techtrip/221680799006

  • 하나의 TCP 연결에 여러 스트림을 사용하고, 요청과 응답을 병렬로 처리
  • http 메세지를 독립된 프레임으로 조각내어 서로 송수신하고 다시 조립하며 데이터를 주고받음
  • 스트림을 통해 각 요청의 응답 순서가 의미가 없어지므로 다중화(multiplexing)이 가능해짐

HOL Blocking 문제 해결

 

Stream Prioritization

  • 각 요청/스트림에는 고유 식별자와 우선순위가 있음
  • 리소스 간 우선순위를 설정하여 클라이언트가 필요한 리소스부터 먼저 보내줌
  • 예를 들어, image를 먼저 받아도 랜더링할 html 문서가 없으면 의미가 없기 때문에 html 문서의 우선순위를 높여 먼저 응답하도록 함

 

Server Push

  • 1.1에서는 클라이언트가 요청을 해야 파일을 받을 수 있었다면, 2.0는 클라이언트 요청 없이 서버가 바로 리소스를 푸시할 수 있음
  • 단일 클라이언트 요청에 여러 응답을 보낼 수 있는 특징을 통해 클라이언트가 요청하기 전에 필요하다고 예상되는 리소스를 서버에서 먼저 보내줌
  • html에는 css나 js 파일이 포함되기 마련이므로 함께 푸시하여 클라이언트에 먼저 줄 수 있음

 

Header Compression

  • 기존에는 연속된 요청의 경우 많은 중복된 헤더의 전송으로 오버헤드가 발생했음
  • 이전 헤더의 내용과 중복되는 필드값을 재전송하지 않아 데이터를 절약함
  • 클라이언트와 서버는 각각 Header Table을 관리하고, 이전 요청과 동일한 필드는 table의 index만 보냄
  • 변경되는 값은 허프만 인코딩 후 전송하여 헤더의 크기를 경량화
    • 문자열을 문자 단위로 쪼개 빈도수를 셈
    • 빈도가 높은 정보는 적은 비트 수를 사용하여 표현하고, 빈도가 낮은 정보는 비트 수를 많이 사용하여 표현

 

한계

  • 패킷에 오류가 있어 재전송할 경우, 그동안 전체 TCP 연결이 중단되게 됨
  • 즉 애플리케이션 계층에서의 HTTP HOLB는 해결했지만, 전송 계층에서의 HOLB를 해결한 것은 아님
  • 애초에 TCP로 인터넷 통신을 하는 것이 발목을 잡은 것

⇒ TCP의 태생적인 HOL Blocking을 해결하기 위해 QUIC 프로토콜과 HTTP 3.0이 등장

 


HTTP/3.0

특징

  • 구글이 SPDY 프로토콜에 이어 새로운 UDP 기반의 QUIC 프로토콜을 고안
  • QUIC 프로토콜을 TCP/IP 4계층에 동작시키기 위해 설계된 것이 HTTP/3.0
  • 초기 연결 설정 시 지연 시간 감소라는 장점이 있음
  • 패킷 손실에 대한 빠른 대응이 가능하며, 사용자 IP가 바뀌어도 연결이 유지

 

QUIC 프로토콜

https://www.nearform.com/blog/a-quic-update-for-node-js/

  • QUIC은 TCP의 3-way handshake 과정을 최적화하는 것에 초점을 두고 개발됨
  • TCP를 사용하지 않기 때문에 통신을 시작할 때 번거로운 핸드쉐이크 과정을 거치지 않아도 됨
  • 클라이언트가 서버에 신호를 보내고 서버가 응답하기만 하면 바로 본 통신을 시작할 수 있음
  • TCP는 연결을 생성하기 위해 1 RTT가 필요하고, TLS를 사용한 암호화까지 한다면 TLS의 핸드쉐이크까지 더해져 총 3 RTT가 필요
  • 반면 QUIC은 첫 연결 설정에만 1 RTT 소요

 

QUIC 연결 원리

  • 1-RTT 가 가능한 이유는 데이터를 연결 설정에 필요한 정보와 함께 보내기 때문
  • 서로의 세션 키를 교환하기도 전에 데이터를 교환할 수 있기 때문에 연결 설정이 더 빠름
  • 클라이언트가 첫 요청을 보낼 때는 서버의 세션 키를 모르는 상태이기 때문에 초기화 키(Initial Key)를 사용하여 통신을 암호화함
    • 초기화 키란 서버의 Connection ID를 사용하여 생성한 특별한 키
  • 한번 연결에 성공했다면 서버는 그 설정을 캐싱해 놓았다가, 다음 연결 때 해당 정보를 사용하여 바로 연결을 성립시켜 0 RTT가 가능
  • Connection ID는 랜덤한 값일 뿐, 클라이언트의 IP와는 전혀 무관한 데이터이기 때문에 클라이언트의 IP가 변경되더라도 기존의 연결을 계속 유지할 수 있음

 

QUIC의 신뢰성 확보 방법

  • 순방향 오류 수정 메커니즘(FEC, Forword Error Correction)이 적용됨
  • 전송한 패킷이 손실되었다면 수신 측에서 에러를 검출하고 수정하는 방식
  • 열악한 네트워크 환경에서도 낮은 패킷 손실률을 자랑함

 


References

+ Recent posts