...
HTTP / 3.0
HTTP 2.0 의 등장과 함께 기존의 프로토콜 데이터 체계를 프레임과 스트림 개념으로 재구축한 결과 기존 보다 혁신적으로 성능이 향상되게 되었다. 하지만 여전히 HTTP는 TCP 기반 위에서 동작되기 때문에, TCP 자체의 핸드쉐이크 과정에서 발생하는 지연 시간과, 기본적으로 TCP는 패킷이 유실되거나 오류가 있을때 재전송을하는데 이 재전송하는 패킷에 지연이 발생하면 결국 HOLB(Head Of Line Blocking) 문제가 발생되었다.
즉, HTTP 2.0은 TCP/IP 4 계층의 애플리케이션 계층(L4)에서 HTTP의 HOLB를 해결하였지만, 전송 계층(L3)에서의 TCP HOLB 를 해결한건 아니기 때문이다.
애초에 TCP로 인터넷 통신을 하는 것이 발목을 잡은 것이다.
점점 기술이 발전하고 다채로운 휴대 통신 기기가 널리 보급되면서 기업들은 다양한 컨텐츠를 여러 기기에 신속하게 전달하기 위해 TCP의 한계를 극복하고 최적화하는 것이 급선무의 과제였다.
그러자 IT 기업의 선두주자인 구글은 SPDY 프로토콜에 이어 새로운 UDP 기반인 QUIC 프로토콜을 고안하게 된다. 그리고 이 새로운 QUIC 프로토콜이 TCP/IP 4계층에도 동작시키기 위해 설계된 것이 바로 HTTP 3.0 이다.
즉, HTTP/1.1과 HTTP/2는 TCP를 전송에 사용하지만, HTTP/3은 UDP(QUIC)를 사용한다고 보면 된다.
HTTP 3.0은 HTTP 2.0가 가지는 장점들을 모두 가지면서 TCP가 가지는 원초적인 단점을 보완하는데 중점으로 개발되었다. 그래서 지금까지 거론되었던 HTTP/2 의 문제를 거의 해결하였다고 보면 된다. RTT(Round Trip Time)를 제로 수준으로 줄였고, 패킷 손실에 대한 빠른 대응, 사용자 IP가 바뀌어도 연결이 유지되는 것이 특징이다.
통신 인프라가 빈약한 나라에서는 큰 차이가 느껴질지도 모르겠지만, 사실 한국에서 HTTP/2를 사용하든 HTTP/3를 사용하든 워낙에 땅이 좁은데다 통신 인프라는 세계에서 끝내주게 잘되어 있기 때문에 소비자들은 체감을 못 할 것이다.
그렇지만 2022년 11월 15일 한국 최초로 네이버가 HTTP/3을 도입하였다고 한다. (당연히 구글은 이미 도입했다)
개발자 도구의 네트워크 탭에서 표 항목에 Protocol을 활성화하면 각 요청에 대한 프로토콜을 볼 수 가 있다.
사진상에서 h3이라고 쓰여져 있는 것이 http 3.0 이며 http 2.0 과 간혹 http 1.1 도 보인다.
QUIC 프로토콜
HTTP/3의 가장 큰 특징은 기존의 HTTP/1, HTTP/2와는 다르게 UDP 기반의 프로토콜인 QUIC(Quick UDP Internet Connections)을 사용하여 통신하는 프로토콜이라는 점이다. 'Quick UDP Internet Connections' 라는 이름에서 알수 있듯이 말 그대로 UDP를 사용하여 빠르게 인터넷 연결을 하는 새로운 프로토콜이다. (참고로 '퀵' 이라고 읽는다)
HTTP/2의 기반이 되는 SPDY는 사장되었지만, HTTP/3의 기반이 되는 QUIC는 RFC 9000으로 표준화되어 있다는 점도 다르다.
QUIC의 계층 위치
위의 TCP/IP 4 Layer에서 볼 수 있듯이 HTTP/3은 계층 형태는 약간 특이하다.
왜냐하면 QUIC은 TCP + TSL + HTTP의 기능을 모두 구현한 프로토콜이기 때문이다. TCP의 프로토콜의 무결성 보장 알고리즘과 SSL이 이식됨으로써 높은 성능과 동시에 신뢰성을 충족시켰다고 보면 된다. 그래서 계층 위치도 약간 비스듬하게 걸쳐 있게 표현된 것이다.
쉽게 말하자면, Application 계층의 HTTP/3은 QUIC를 동작시키기 위해 있는 것이라고 보면 되고, 위에서 배웠다시피 QUIC는 UDP 기반으로 만들어졌기에 Transport 계층의 UDP 위에서 동작한다고 보면된다.
어째서 TCP가 아닌 UDP인가 ❓
💬 TCP는 구조상 한계로 개선해도 여전히 느리다
사실 TCP는 인류가 지금과 같이 엄청난 속도로 발전할 것이라곤 상상 할 수 없는 시기에 만들어졌다. TCP가 만들어지던 시절에 클라이언트와 서버가 동시 다발적으로 여러 개 파일의 데이터 패킷을 교환할 것이라고 상상하지 못했기 때문이다.
그래서 모바일 기기와 같이 네트워크 환경을 바꾸어가면서 서버와 클라이언트가 소통할 수 있을 것이라고 생각하지 못했다. 그 때문에 와이파이를 바꾸면 다시 새로운 커넥션을 맺어야 되서 끊김 현상이 일어나는 것이다.
또한 TCP를 사용한 통신에선 패킷은 신뢰성을 위해 무조건 순서대로 처리되어야 한다. 또한 패킷이 처리되는 순서 또한 정해져있으므로 이전에 받은 패킷을 파싱하기 전까지는 다음 패킷을 처리할 수도 없다. 만일 중간에 패킷이 손실되어 수신 측이 패킷을 제대로 받지 못했으면 다시 보내야 한다.
이렇게 패킷이 중간에 유실되거나 수신 측의 패킷 파싱 속도가 느리다면 통신에 병목이 발생하게 되는데, 이러한 현상을HOLB(Head of line Blocking)라고 부른다.
이 HOLB는 TCP 설계도상 어쩔수 없이 발생하는 문제이기 때문에 HTTP/1.1 뿐만 아니라 HTTP/2도 가지고 있는 아주 고질적인 문제였다.
따라서 이런 고질적인 문제들을 해결하기 위해 HTTP/3는 TCP를 버리고 UDP를 선택하였다.
💬 UDP는 신뢰성이 없는게 아니라 탑재를 안했을 뿐이다
처음 TCP와 UDP에 대해서 배웠을때, UDP는 하얀 도화지 같이 기능이 거의 없어서 빠르지만 대신에 신뢰성이 낮기 때문에, 인터넷 통신에선 조금 느리더라도 신뢰성이 높은 TCP를 사용한다라고 배웠을 것이다.
TCP | UDP | |
연결 방식 | 연결 지향형 프로토콜 | 비 연결 지향형 프로토콜 |
전송 순서 | 보장 | 보장하지 않음 |
신뢰성 | 높음 | 낮음 |
전송속도(상대적) | 느림 | 빠름 |
혼잡제어 | O | X |
헤더 크기 | 20바이트 | 8 바이트 |
UDP는 User Datagram Protocol이라는 이름에서도 알 수 있듯이 데이터그램 방식을 사용하는 프로토콜이기 때문에 패킷의 목적지만 정해져있다면 중간 경로는 신경쓰지 않기 때문에 핸드쉐이크 과정이 필요없다.
결론으로는 UDP는 TCP가 신뢰성을 얻기 위해 내제된 과정을 거치지 않기 때문에 속도가 더 빠를 수 밖에 없다는 것인데, 그렇다면 UDP를 사용하게되면 빠르지만 신뢰성과 패킷의 무결성을 보증할 없다는 뜻인데 이것을 인터넷 통신에 사용해도 문제가 없는 걸까?
이부분은 오해인것이, UDP는 신뢰성이 없는게 아니라 탑재를 안했을 뿐이다.
UDP의 진짜 장점은 커스터마이징이 가능하다는 점이다.
즉, 아래 사진과 같이 UDP 자체는 헤더에 들은게 없어 신뢰성이 낮고 제어 기능도 없지만, 이후 개발자가 애플리케이션에서 구현을 어떻게 하냐에 따라서 TCP와 비슷한 수준의 기능을 가질 수도 있다는 말이다.
💬 아예 새로운 프로토콜은 안되는가?
TCP가 문제이고 UDP도 애매하면 아예 다른 프로토콜을 만들거나 채용한다는 선택지도 있을 것이다. 이론적으로도 네트워크 스택에서 UDP와 TCP 옆에 새로운 전송 프로토콜을 만들 수 있다. 아니면 이미 있는 전송 프로토콜인 SCTP를 사용할 수도 있다.
그러나 새 프로토콜 배포는 그렇게 녹록치만은 않은데, 사용자와 서버 사이에 있는 TCP와 UDP만 허용하는 방화벽, NAT, 라우터 등의 설정에 따라 차단 될 수 있기 때문이다. 이를 프로토콜 고착화(ossification)라고 부른다.
게다가 네트워크 스택의 전송 프로토콜 계층에서 뭔가를 바꾼다는 것은 새로운 운영체제 커널을 갱신하고 프로토콜을 구현해 배포하는 것은 상당한 노력이 필요한 과정이다. 그래서 이미 표준화된 수많은 TCP 개선사항도 광범위하게 지원되지 않아서 널리 배포되거나 사용되지 않고 있는 것이다.
HTTP 3.0 개선점
연결 시 레이턴시 감소
기존 TLS+TCP에서는 TLS 연결을 위한 핸드쉐이크와 TCP를 위한 핸드쉐이크가 각각 발생했다.
그래서 TCP는 연결을 생성하기 위해 기본적으로 1 RTT 가 필요하고, 여기에 TLS를 이용한 암호화 통신까지 한다면 총 3 RTT가 필요하게 된다.
RTT (Round Trip Time)
RTT(Round Trip Time)란, 요청(SYN)을 보낼 때부터 요청에 대한 응답(SYN+ACK)을 받을 때까지의 왕복 시간을 의미한다.
QUIC에서는 이를 한단계로 줄였다.
UDP 위에서 동작하는 QUIC는 통신을 시작할 때 3 Way Handshake 과정을 거치지 않아도 되기 때문에 첫 연결 설정에 1 RTT만 소요된다. 그 이유는 연결 설정에 필요한 정보와 함께 데이터도 보내버리기 때문이다.
QUIC 내에 아예 TLS 인증서를 내포하고 있기 때문에, 최초의 연결 설정에서 필요한 인증 정보와 데이터를 함께 전송한다. 그래서 클라이언트가 서버에 어떤 신호를 한번 주고, 서버도 거기에 응답하기만 하면 바로 본 통신을 시작할 수 있다는 것이다
위의 그림에서 볼 수 있듯이 TCP+TLS는 서로 자신의 세션 키를 주고 받아 암호화된 연결을 성립하는 과정을 거치고 나서야 세션 키와 함께 데이터를 교환하기 때문에 핸드쉐이크 과정이 여러번 발생하게 된다.
하지만 QUIC은 서로의 세션 키를 교환하기도 전에 데이터를 교환할 수 있기 때문에 연결 설정이 더 빠르다. 다만, 최초의 요청을 보낼 때는 클라이언트는 서버의 세션 키를 모르는 상태이기 때문에, 목적지인 서버의 Connection ID를 사용하여 생성한 특별한 키인 초기화 키(Initial Key)를 사용하여 통신을 암호화 한다.
그리고 한번 연결에 성공했다면 서버는 그 설정을 캐싱해놓고 있다가, 다음 연결 때 캐시를 불러와 바로 연결을 하기 때문에 추가적인 핸드 쉐이크 없이 0 RTT만으로 바로 통신을 시작할 수도 있다는 장점도 있다.
잔존하던 HOLB 현상을 해결
HTTP의 HOLB (Head Of Line Blocking)
기존 HTTP/1.1 같은 경우 파이프라인(pipeline) 기술을 통해 병렬적으로 리소스를 빠르게 얻도록 하려고 하였지만, 만일 첫번째 요청에 딜레이가 생기면 나머지 요청이 빨리 처리됬음에도 불구하고 딜레이가 되는 심각한 현상이 있었다.
예를들어 3개의 이미지 a.png, b.png, c.png 를 받는다고 가정한다면 다음과 같이 첫번째 a.png 를 받는 과정에서 오래걸리게 된다면 b와 c 이미지가 아무리 빨리 처리되더라도 결과적으로 늦게 받게 되게 된다.
그래서 이를 극복하기 위해 HTTP/2 에서는 리소스들을 하나의 커넥션에서 병렬적으로 보내도록 개선하였다. 따라서 a.png 가 시간이 걸리더라도 b 와 c 이미지는 먼저 받아서 보여줄 수 있었다.
TCP의 HOLB (Head Of Line Blocking)
이처럼 HTTP 레이어의 HOL Blocking 은 해결됬지만, 문제는 TCP 레이어의 HOL Blocking 문제가 여전히 잔존해 있었던 것이다.
HTTP/2를 사용하는 일반적인 브라우저는 TCP 연결 한개로 수십, 수백 개의 스트림 데이터를 병렬 전송을 한다. 그런데 만일 두 엔드포인트 사이 네트워크 어딘가에서 하나의 패킷이 빠지거나 없어진다면, 없어진 패킷을 다시 전송하고 목적지를 찾는 동안 전체 TCP 연결이 중단되게 된다.
즉, HTTP/2에서 스트림에서 여러가지 프레임들이 뒤 섞여 이동되게 되는데, 만일 어느 하나의 프레임에 문제가 생기면 상관없는 그 뒤의 프레임까지 영향이 가게 된다. 따라서 결국은 HTTP의 HOLB처럼 스트림 내 패킷들은 전체가 지연이 되게 된다.
거기다가 HTTP/2는 1개의 TCP 커넥션으로 전부를 처리하고 있기 때문에 패킷 손실률이 증가하면 여러 개의 TCP를 사용하는 HTTP/1.1보다 성능 저하가 커질 수 있다.
독립 스트림으로 HOLB 단축
그래서 TCP를 버려버리고 새로 QUIC 프로토콜로 구축해서 아예 스트림 자체를 독립적으로 여러개로 나누어서 처리하도록 하였다. 이를 독립 스트림이라고 한다.
QUIC 연결을 통해 두 가지 다른 스트림을 설정했을 때, 이들을 독립적으로 다루므로 만약 특정 스트림에서 HOLB가 발생하더라도, 다른 스트림에는 영향을 미치지 않는다.
패킷 손실 감지에 걸리는 시간 단축
HOLB 해결에 이어 QUIC는 흐름 제어하는 시간까지 단축하였다.
QUIC도 TCP와 마찬가지로 전송하는 패킷에 대한 흐름 제어를 해야한다. QUIC는 기본적으로 TCP와 유사한 방법으로 패킷 손실을 탐지하지만 여기에 몇 가지 알고리즘 개선 사항을 추가하였다.
예를들어 HTTP 2.0에서는 아래 그림과 같이 하나의 스트림에 A, B, C 패킷 프레임들이 비순서대로 전달될때, 만일 세번째 프레임에서 패킷 손실이 일어나면, 패킷 B만 중지되어야 하지만 위에서 배운바와 같이 전혀 연관없는 패킷 A와 C도 모두 막혀 대기를 해야된다.
이러한 문제를 해결하기 위해 QUIC는 헤더에 패킷의 전송 순서를 나타내는 별도의 패킷 번호 공간을 부여했다.
이를 이용해 QUIC는 패킷 번호를 파악해 개별 파일을 구분하여 중간에 패킷 로스가 발생해도 해당 파일의 스트림만 정지가 되도록 할 수 있다.
하나의 스트림에서 문제가 발생한다고 해도 다른 스트림은 지킬 수 있게 되어 이런 문제에서 자유로워 졌다.
더욱 향상된 멀티플렉싱
HTTP/3도 당연히 HTTP/2와 같은 멀티플렉싱을 지원한다.
그리고 독립 스트림 방식으로 기존의 멀티플렉싱을 더욱 강화시켰다고 보면 된다.
보안을 더욱 강화
HTTP/3와 그 기반 기술인 QUIC은 TLS 암호화를 기본적으로 사용한다.
물론 UDP와 TLS가 결합된 기술로는 DTLS라는 기술도 있지만 'TCP의 재구현'이 목표 중 하나인 QUIC와는 지향하는 바가 다르다.
이처럼 기본적으로 QUIC 내에 TLS 이 포함되어있기 때문에 TCP와 달리 헤더 영역도 같이 암호화된다.
네트워크가 변경 되도 연결이 유지
TCP의 경우 클라이언트와 서버가 서로를 구분하기 위해서는 클라이언트 IP, 클라이언트 PORT, 서버 IP, 서버 PORT, 이렇게 네 가지가 필요하다. 그래서 클라이언트의 IP가 바뀌는 상황이 발생하면 연결이 끊어져 버린다.
우리가 핸드폰을 들고 와이파이존에서 LTE 데이터를 사용하게 됐을 때, 동영상 끊김과 같이 일시적 지연이 일어나는 이유는 클라이언트 IP가 이때 바뀌기 때문이다. 그래서 다시 연결을 생성하기 위해 결국 핸드쉐이크 과정을 다시 거쳐야한다는 것이고, 이 과정에서 다시 지연시간이 발생하게 되는 것이다.
Connection ID
반면 QUIC은 Connection ID를 사용하여 서버와 연결을 생성한다.
Connction ID는 각 연결은 연결 식별자나 연결 ID를 가지므로 이를 통해 연결을 식별한다.
Connection ID는 랜덤한 값일 뿐, 클라이언트의 IP와는 전혀 무관한 데이터이기 때문에 클라이언트의 IP가 변경되더라도 기존의 연결을 계속 유지할 수 있다. 그래서 새로 연결을 생성할 때 거쳐야하는 핸드쉐이크 과정을 생략할 수 있다. 따라서 휴대폰으로 인터넷을 할 때, 중간에 와이파이에서 LTE로 변경해도 스트림이 계속 유지가 된다.
하지만 똑같은 Connection ID만 사용한다면 해커가 네트워크를 통해 사용자를 추적하여 보안 문제가 일어날 수도 있을 것이다. 그래서 QUIC는 새 네트워크가 사용될 때마다 Connection ID를 변경한다.
위의 말과 행동이 다르겠다고 생각하겠지만, 내부적으로 클라이언트와 서버가 모두 연결을 위해 무작위로 생성한 Connection ID에 대해 인지하고 있고, 네트워크가 바뀔때 Connection ID를 바꾸더라도 이게 이전 Connectin ID와 동일하다고 인지하여 연결을 유지하는 것이다.
HTTP 3.0 우려점
HTTP 3.0 과 QUIC 프로토콜이 이렇게 좋은 많은 것들을 제공해 주고 있지만, 아직 전세계의 기업들이 이를 막상 도입하지 않는 현실적인 이유가 존재한다.
기존 체계 호환성 문제
HTTP/1.1 이나 HTTP/2 기반의 프론트엔드단 최적화를 이미 적용한 기업의 경우 QUIC 도입에 부담스러울 수 있다.
예를들어 브라우저의 병렬 다운로드를 통해 리소스를 빠르게 받아오는 도메인 분할(domain sharding) 기법을 이미 적용하여 최적화를 시킨 기업은 오히려 멀티플렉싱 기반의 HTTP/2 혹은 HTTP/3에서 성능이 반감될 수 있다.
또한 브라우저의 콘텐츠 Prefetch 기능을 적용한 경우, 이를 Server Push 기능으로 변경해야 할지에 대한 기술적인 판단과 충분한 성능 비교 테스트가 필요하게 된다.
암호화로 네트워크 제어가 힘듬
QUIC는 기존에는 암호화하지 않던 헤더 필드도 암호화한다.
그래서 이런 헤더의 정보를 사용하는 ISP나 네트워크 중계회사들은 기존에 암호화하지 않던 헤더 필드 영역들을 읽을 수 없어 네트워크 혼잡을 관리하기 위한 네트워크를 최적화하기 힘들다. 예를 들어 패킷이 ACK인지 재전송인지 알 수 없다. RTT 추정 은 더 어렵다.
이러한 이유로 기업들이 HTTP 3 도입을 주저하고 있다.
암호화로 리소스가 많이 듬
QUIC은 패킷별로 암호화를 한다.
이는 기존의 TLS-TCP에서 패킷을 묶어서 암호화하는 것보다 더 큰 리소스 소모를 불러올 수 있다는 단점이 있다.
QUIC는 CPU를 너무 사용함
QUIC은 너무 많은 CPU 시간을 차지한다.
따라서 보급형 스마트폰과 IoT 장치같은 마이크로 애플리케이션들은 이용에 어려움을 겪을 수도 있다.
물론 시간이 지나면 개선될수도 있다. 다만 문제는 추가적인 CPU 사용이 배포자에게 얼마나 영향을 끼치는가 이다.
UDP의 보안적인 문제
DNS에서 TCP나 UDP를 53포트를 이용해 통신하게 되는데, 53 포트가 아닌 UDP 트래픽이 최근에는 도스 공격에 주로 사용되기 때문에 많은 서비스들에서 차단하거나 속도를 제한하고 있다.
그래서 QUIC에서는 초기 패킷이 최소 1200바이트여야 한다는 조건과 서버가 클라이언트로부터 응답 패킷을 받지 않으면 요청 크기의 3배 이상은 절대 보내면 안 된다는 프로토콜의 제약사항으로 이를 해결하려고 노력중이다.
기존에도 HTTP/2의 여러 보안 취약점이 발견되어 모든 업체가 이에 대한 보안 패치를 적용한 사례가 있듯이, 이처럼 새로운 기술이 나오면 보안 문제는 항상 대두되길 마련이다.
물론 이러한 우려점들은 QUIC도 버전이 업데이트 됨에 따라 극복될 가능성이 있다.
HTTP/3도 점점 발전해 나갈것이고, QUIC가 사장되고 또다른 프로토콜이 나온다고 할지라도, 이제는 더이상 HTTP는 TCP라는 이야기도 바뀌지 않을꺼라 생각된다.
# 참고자료
HTTP 완벽 가이드 - Programming Insight
https://http3-explained.haxx.se/en
https://evan-moon.github.io/2019/10/08/what-is-http3/
https://www.hamadevelop.me/http3/
https://devopedia.org/quic
https://youtu.be/xcrjamphIp4
https://blog.workinghardinit.work/2021/06/30/microsoft-and-quic/
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.