Ver4.0 웹을 더 빠르게 만든 HTTP/3와 QUIC: 전송 계층의 재설계가 바꾼 인터넷 속도의 문법

웹을 더 빠르게 만든 HTTP/3와 QUIC: 전송 계층의 재설계가 바꾼 인터넷 속도의 문법
TCP의 30년 관성을 UDP 위에서 다시 쓴 사건, 그리고 그 결과 우리가 체감하는 '빠름'의 정체
0. 들어가며: "인터넷이 느린 게 아니라, 규칙이 낡았던 것"
우리는 흔히 웹이 느리면 "회선이 느려서"라고 말한다.
하지만 2010년대 중반 구글 엔지니어들이 내린 결론은 정반대에 가까웠다.
이 관찰은 구글의 Mike Belshe가 2010년에 발표한 유명한 실험에서 나왔다.
대역폭(Bandwidth)은 한 번에 얼마나 많이 보내느냐이고, 지연시간(Latency)은 한 번 다녀오는 데 얼마나 걸리느냐다.
웹 페이지 하나를 여는 일은 사실 수십~수백 개의 작은 요청이 서로를 기다리는 대화(Conversation)다.
대화가 많으면 많을수록, 중요한 것은 '입의 크기'가 아니라 '말이 오가는 왕복 횟수'다.
HTTP/3와 QUIC은 바로 그 왕복 횟수, 그리고 왕복 도중 발생하는 불필요한 대기를 제거하기 위해 태어났다.
이 글은 공학적으로 그 구조를 해부하되, 가능한 한 재미있게 따라갈 수 있도록 구성했다.
이 글에서 다루는 것
① TCP가 만든 세 가지 근본 병목 (핸드셰이크 / HOL 블로킹 / 경로 고정)
② QUIC이 UDP 위에서 전송 계층을 재구현한 방식
③ HTTP/3의 프레이밍과 QPACK 헤더 압축
④ 혼잡 제어, 손실 복구, 0-RTT의 보안적 트레이드오프
⑤ 실제 성능 데이터와 배포 현황, 그리고 한계
1. 시간 여행: HTTP는 어떻게 여기까지 왔나
1.1 HTTP/0.9부터 HTTP/2까지의 계보
| 버전 | 표준화 | 핵심 변화 | 남은 문제 |
|---|---|---|---|
| HTTP/0.9 | 1991 | GET 한 줄. 헤더도 상태코드도 없음 | 기능 부재 |
| HTTP/1.0 | 1996 (RFC 1945) | 헤더, 상태코드, 콘텐츠 타입 | 요청마다 TCP 연결 새로 생성 |
| HTTP/1.1 | 1997/1999 (RFC 2068→2616), 2014 재정비(RFC 7230~) | Keep-Alive, 청크 전송, Host 헤더, 캐시 제어 | 요청 직렬화 → HOL 블로킹 |
| HTTP/2 | 2015 (RFC 7540) | 바이너리 프레이밍, 멀티플렉싱, HPACK, 서버 푸시 | TCP 레벨 HOL 블로킹 잔존 |
| HTTP/3 | 2022 (RFC 9114) | QUIC 위에서 동작, 스트림 단위 독립성 | UDP 차단·CPU 비용 |
HTTP/1.1 시절 개발자들은 눈물겨운 우회를 했다.
도메인 샤딩(static1.example.com, static2.example.com …)으로 브라우저의 도메인당 6커넥션 제한을 억지로 늘리고,
스프라이트 이미지로 아이콘 수십 개를 한 장에 우겨넣고,
CSS/JS 번들링으로 파일 수를 줄였다.
이 모든 기법의 공통 목적은 단 하나였다. "요청 개수를 줄여라."
왜? 요청 하나가 곧 왕복 하나였기 때문이다.
1.2 HTTP/2의 약속과 배신
HTTP/2는 이 문제를 멀티플렉싱으로 해결했다.
하나의 TCP 연결 안에 여러 개의 논리적 '스트림'을 만들어, 요청들이 서로 기다리지 않고 섞여서 오갈 수 있게 한 것이다.
애플리케이션 레벨에서 보면 완벽했다. 그런데 TCP는 그 사실을 몰랐다.
TCP의 세계관: "나는 바이트 스트림 하나를 순서대로 배달하는 택배기사다. 그 안에 뭐가 들었는지는 관심 없다."
그래서 10번 패킷이 유실되면, 11·12·13번이 이미 도착해 있어도 커널은 애플리케이션에게 넘겨주지 않는다. 순서를 지켜야 하니까.
결과적으로 이미지 스트림의 패킷 하나가 사라지면, 아무 상관없는 CSS 스트림까지 멈춰 선다.
이것이 그 악명 높은 TCP 레벨 Head-of-Line(HOL) 블로킹이다.
손실률이 낮은 유선 환경에선 티가 안 난다.
그러나 지하철, 엘리베이터, 혼잡한 셀룰러 네트워크에서는? HTTP/2가 HTTP/1.1보다 느려지는 역전 현상까지 보고됐다.
2. 문제의 지도: TCP가 만든 세 가지 병목
2.1 병목 ①: 연결 수립의 왕복 비용
HTTPS 연결 하나를 만들려면 두 번의 협상이 필요했다.
먼저 TCP 3-way 핸드셰이크(SYN → SYN-ACK → ACK)로 1 RTT,
그다음 TLS 핸드셰이크로 1~2 RTT.
지구 반대편 서버라면 RTT가 200ms를 넘는다.
그럼 데이터 1바이트 받기도 전에 0.4~0.6초가 증발한다.
이게 왜 낭비인가? 두 협상이 하는 일이 겹치기 때문이다.
TCP는 "너 거기 있니?"를 확인하고, TLS는 "너 진짜 그 사람 맞니?"를 확인한다.
논리적으로는 한 번에 묶을 수 있는 일을, 레이어가 분리되어 있다는 이유만으로 따로 했던 것이다.
2.2 병목 ②: 커널에 갇힌 HOL 블로킹
앞서 말한 그 문제다. 더 아픈 지점은 애플리케이션이 이를 고칠 수 없다는 것.
TCP는 OS 커널에 구현되어 있고, 커널 업데이트는 수년 단위로 느리게 퍼진다.
프로토콜 경화(Protocol Ossification)
TCP를 개선하려는 시도는 많았다. 하지만 중간 장비(NAT, 방화벽, 로드밸런서)들이 "내가 아는 TCP가 아니면 버린다"는 태도를 취했다.
실제로 TCP Fast Open(TFO)은 2014년 표준화됐지만, 상당수 네트워크에서 미들박스가 예상치 못한 SYN 페이로드를 떨어뜨려 폴백이 빈번했다. 프로토콜이 화석처럼 굳어버린 것이다.
2.3 병목 ③: 4-튜플에 묶인 연결
TCP 연결의 신원은 (출발지 IP, 출발지 포트, 목적지 IP, 목적지 포트) 4-튜플이다.
스마트폰이 Wi-Fi에서 LTE로 넘어가면 출발지 IP가 바뀐다 → 연결 사망 → 처음부터 다시.
영상 보다가 엘리베이터 타면 버퍼링 도는 그 순간, 바로 이 일이 벌어지고 있다.
3. QUIC의 등장: "그럼 UDP 위에 다시 짓자"
3.1 왜 하필 UDP인가
2012년경 구글의 Jim Roskind가 이끄는 팀은 대담한 결정을 내린다.
"TCP를 고칠 수 없다면, TCP가 하던 일을 유저 스페이스에서 새로 구현하자."
그 토대로 UDP를 택한 이유는 낭만이 아니라 현실적 계산이었다.
UDP를 선택한 4가지 이유
1) 이미 전 세계 네트워크 장비가 UDP를 통과시킨다 (DNS, VoIP, 게임 덕분)
2) UDP는 "그냥 보내는" 최소 기능만 있어서, 위에 무엇이든 얹을 수 있다
3) 새 IP 프로토콜 번호를 쓰면 방화벽이 100% 차단한다 (SCTP의 비극)
4) 유저 스페이스 구현 → 브라우저·서버 업데이트만으로 배포 가능. 커널 대기 불필요
즉 QUIC은 "UDP라는 빈 캔버스 위에 TCP의 신뢰성 + TLS의 보안 + HTTP/2의 멀티플렉싱을 하나로 통합해 다시 그린 것"이다.
3.2 gQUIC에서 IETF QUIC으로
초기 버전은 구글 내부 규격인 gQUIC이었다.
2015년 구글이 IETF에 제안했고, 표준화 과정에서 구조가 대폭 재설계된다.
가장 큰 변화는 암호 계층의 분리였다.
gQUIC은 자체 암호 프로토콜(QUIC Crypto)을 썼지만, IETF는 검증된 TLS 1.3을 그대로 가져다 쓰되 레코드 계층만 QUIC이 대체하는 방식을 택했다.
그리고 2021년 5월, 마침내 표준 문서들이 쏟아진다.
| RFC | 제목 | 내용 |
|---|---|---|
| RFC 8999 | Version-Independent Properties of QUIC | 버전 무관 불변 요소 |
| RFC 9000 | QUIC: A UDP-Based Multiplexed and Secure Transport | 전송 계층 본체 |
| RFC 9001 | Using TLS to Secure QUIC | TLS 1.3 통합 방식 |
| RFC 9002 | QUIC Loss Detection and Congestion Control | 손실 탐지·혼잡 제어 |
| RFC 9114 | HTTP/3 | HTTP 매핑 (2022.6) |
| RFC 9204 | QPACK | HTTP/3용 헤더 압축 |
| RFC 9369 | QUIC Version 2 | 버전 협상 경화 방지용 |
실제로 RFC 9110(HTTP Semantics)은 버전과 무관한 의미론을 따로 분리해 정의했다.
GET, POST, 상태코드 200, 헤더 Content-Type — 이 모든 개념은 1/1.1/2/3에서 동일하다.
달라진 것은 직렬화 방식과 전송 방식뿐이다.
4. QUIC 내부 해부: 계층을 접어 넣은 설계
4.1 커넥션 ID: 연결의 새로운 신원
QUIC은 4-튜플 대신 Connection ID(CID)라는 별도 식별자를 쓴다.
이 값은 패킷 헤더에 담기며, IP나 포트가 바뀌어도 그대로 유지된다.
그래서 Wi-Fi → 셀룰러 전환 시에도 연결이 끊기지 않는다. 이를 커넥션 마이그레이션이라 한다.
프라이버시까지 챙긴 설계
CID를 고정해두면 오히려 추적 도구가 된다. 그래서 QUIC은 NEW_CONNECTION_ID 프레임으로 여분의 CID를 미리 발급하고, 경로가 바뀔 때마다 다른 CID로 교체한다.
또한 마이그레이션 시 PATH_CHALLENGE/PATH_RESPONSE로 새 경로의 도달성을 검증한다. 공격자가 위조 IP로 트래픽을 유도하는 것을 막기 위함이다.
4.2 스트림: 독립적인 차선들
QUIC 연결 안에는 여러 개의 스트림이 존재한다.
각 스트림은 자체적인 순서 보장과 흐름 제어를 가진다.
여기가 결정적이다. 스트림 A의 패킷이 유실돼도, 스트림 B·C·D는 지체 없이 애플리케이션에 전달된다.
TCP의 HOL 블로킹이 구조적으로 사라지는 순간이다.
스트림 ID는 62비트 정수이며, 하위 2비트가 종류를 나타낸다.
스트림 ID 하위 2비트 의미
0x00 → 클라이언트 개시, 양방향
0x01 → 서버 개시, 양방향
0x02 → 클라이언트 개시, 단방향
0x03 → 서버 개시, 단방향
예) 스트림 0 = 클라이언트가 연 첫 양방향 스트림 (HTTP/3 첫 요청)
스트림 2 = 클라이언트 단방향 → HTTP/3 제어 스트림으로 사용
스트림 6, 10 = QPACK 인코더/디코더 스트림
4.3 프레임: 패킷 안의 레고 블록
QUIC 패킷 하나에는 여러 종류의 프레임이 담긴다.
TCP가 헤더 플래그로 제어했던 것들을, QUIC은 프레임이라는 구조화된 단위로 표현한다.
| 프레임 | 역할 |
|---|---|
STREAM | 실제 애플리케이션 데이터 전송 |
ACK | 수신 확인. TCP와 달리 최대 256개 ACK 범위 표현 가능 |
CRYPTO | TLS 핸드셰이크 메시지 운반 |
MAX_DATA / MAX_STREAM_DATA | 흐름 제어 윈도우 갱신 |
NEW_CONNECTION_ID | 추가 CID 발급 |
PATH_CHALLENGE | 경로 검증 |
RESET_STREAM | 특정 스트림만 중단 |
CONNECTION_CLOSE | 연결 종료 |
PING / PADDING | 생존 확인 / 증폭 공격 방지용 패딩 |
주목할 점은 ACK 프레임이다.
TCP의 SACK은 옵션 필드 크기 제약으로 보통 3~4개 블록만 담을 수 있다.
QUIC ACK은 훨씬 많은 불연속 수신 범위를 표현할 수 있어, 손실이 흩뿌려진 환경에서 복구 판단이 정확해진다.
4.4 패킷 번호의 재발명: 모호성 제거
TCP의 고질병 중 하나는 재전송 모호성(Retransmission Ambiguity)이었다.
재전송한 세그먼트가 원본과 같은 시퀀스 번호를 쓰기 때문에, ACK이 왔을 때 "원본에 대한 응답인가, 재전송에 대한 응답인가?"를 알 수 없다.
이 때문에 RTT 측정이 왜곡되고, Karn's algorithm 같은 우회책이 필요했다.
QUIC은 이를 깔끔하게 해결했다.
패킷 번호는 항상 단조 증가하며, 재전송 시에도 새 번호를 부여한다.
데이터의 '순서'는 STREAM 프레임의 오프셋이 따로 관리한다.
역할 분리의 미학
TCP: 시퀀스 번호 하나가 "전송 순서"와 "데이터 위치"를 동시에 담당 → 충돌
QUIC: 패킷 번호 = 전송 순서 / 스트림 오프셋 = 데이터 위치 → 완전 분리
덕분에 RTT 샘플이 정확해지고, 손실 탐지 알고리즘이 훨씬 공격적으로 동작할 수 있다.
4.5 암호화 범위: 헤더까지 감춘다
TCP+TLS에서는 TCP 헤더가 평문이다. 시퀀스 번호, 포트, 플래그가 모두 노출된다.
그래서 미들박스들이 "내가 개입해도 되겠군" 하며 끼어들었고, 그게 경화의 원인이 됐다.
QUIC은 다르다.
| 부분 | 보호 수준 |
|---|---|
| 페이로드(프레임) | AEAD 완전 암호화 |
| 패킷 번호 | 헤더 보호로 암호화 |
| 일부 헤더 플래그 | 헤더 보호 적용 |
| Connection ID | 평문 (라우팅 필요) |
| 버전 필드(Long Header) | 평문 |
초기 핸드셰이크 패킷조차 버전별 고정 솔트에서 유도한 키로 암호화된다.
기밀성 목적이 아니라 미들박스가 내용을 파싱해 굳어버리는 것을 막기 위한 "grease" 성격이 강하다.
5. 핸드셰이크와 0-RTT: 속도의 가장 극적인 구간
5.1 1-RTT 핸드셰이크
QUIC은 첫 패킷(Initial)에 TLS ClientHello를 CRYPTO 프레임으로 담아 보낸다.
서버는 ServerHello + 인증서 + Finished를 함께 회신한다.
그리고 클라이언트의 두 번째 패킷부터 암호화된 애플리케이션 데이터가 흐른다.
즉 연결 수립과 키 교환이 동일한 1 RTT 안에서 끝난다.
TCP+TLS1.3의 2 RTT 대비 정확히 절반이다.
5.2 0-RTT: 첫 패킷에 데이터를 실어 보내기
이전에 접속한 적 있는 서버라면, 클라이언트는 세션 티켓(PSK)을 갖고 있다.
이때는 첫 패킷에 ClientHello와 실제 HTTP 요청을 함께 실어 보낼 수 있다.
대기 시간 0. 극적이다. 하지만 공짜는 아니다.
0-RTT의 두 가지 위험
① 재전송 공격(Replay Attack)
0-RTT 데이터는 순방향 비밀성이 완전하지 않고, 공격자가 패킷을 캡처해 재전송할 수 있다.
→ 그래서 멱등(idempotent)한 요청, 즉 GET 정도만 0-RTT로 보내는 것이 원칙이다. POST로 결제를 0-RTT로 보내면 중복 결제가 발생할 수 있다.
② 증폭 공격(Amplification)
UDP는 출발지 IP 위조가 쉽다. 공격자가 피해자 IP로 위장해 작은 요청을 보내면 서버가 큰 응답을 피해자에게 퍼붓는다.
→ QUIC은 주소 검증 전 서버는 수신 바이트의 3배까지만 전송이라는 규칙(anti-amplification limit)을 못 박았다. 또한 Initial 패킷은 최소 1200바이트로 패딩해야 한다.
실제로 Cloudflare, Google 등은 0-RTT를 안전한 메서드에 한해 선택적으로 활성화한다.
HTTP/3 스펙(RFC 9114)도 서버가 0-RTT 요청을 거부하고 425 Too Early로 재시도를 요구할 수 있게 규정한다.
6. HTTP/3 계층: QUIC 위에 얹힌 HTTP
6.1 요청 하나 = 양방향 스트림 하나
HTTP/3에서 각 요청-응답 쌍은 클라이언트 개시 양방향 스트림 하나를 차지한다.
HTTP/2에서는 스트림이 HTTP/2 프레이밍 레이어의 개념이었지만, HTTP/3에서는 QUIC이 제공하는 네이티브 스트림을 그대로 쓴다.
그래서 HTTP/3 프레임은 훨씬 단순하다.
| HTTP/3 프레임 | 용도 |
|---|---|
HEADERS | QPACK 압축된 헤더 필드 |
DATA | 본문 |
SETTINGS | 제어 스트림 상 파라미터 교환 |
GOAWAY | 정상 종료 예고 |
MAX_PUSH_ID | 서버 푸시 제한 |
HTTP/2에 있던 WINDOW_UPDATE, RST_STREAM, PING 프레임은 사라졌다.
QUIC 계층이 이미 흐름 제어·스트림 리셋·생존 확인을 제공하기 때문이다. 중복 제거의 좋은 예다.
6.2 QPACK: HPACK의 순서 의존성 탈출
HTTP 헤더는 반복이 심하다. User-Agent, Accept, Cookie가 매 요청마다 똑같이 실린다.
그래서 HTTP/2는 HPACK으로 동적 테이블을 만들어 인덱스만 보냈다.
문제는 HPACK이 "양쪽 테이블 상태가 완벽히 동기화되어 있다"고 가정한다는 것.
이는 TCP의 순서 보장에 전적으로 의존한 설계다.
QUIC에서는 스트림 간 순서가 보장되지 않으므로, 헤더 블록이 순서 뒤바뀌어 도착할 수 있다.
그대로 HPACK을 쓰면 테이블 불일치로 연결이 깨진다.
QPACK의 해법
1) 인코더/디코더 전용 단방향 스트림을 따로 둬서 테이블 갱신 명령을 분리 전송
2) 각 헤더 블록 앞에 Required Insert Count를 붙여 "이 블록을 풀려면 테이블에 최소 N개 항목이 있어야 함"을 명시
3) 아직 도달 못 했으면 그 스트림만 잠시 블록. 다른 스트림은 계속 진행
즉 HOL 블로킹을 완전히 없애는 대신, "압축률 vs 블로킹 위험"을 튜닝 가능한 값으로 전환한 것이다.
서버는 SETTINGS_QPACK_BLOCKED_STREAMS 값을 0으로 두어 블로킹을 원천 차단할 수도 있다.
이 경우 압축률은 떨어지지만 지연 예측성은 높아진다. 전형적인 엔지니어링 트레이드오프다.
6.3 Alt-Svc: HTTP/3로 갈아타는 법
브라우저는 처음엔 HTTP/3를 쓸 수 있는지 모른다. 그래서 보통 HTTPS(TCP)로 먼저 접속한다.
서버는 응답에 이런 헤더를 실어 보낸다.
Alt-Svc: h3=":443"; ma=86400
# 또는 DNS 기반 사전 발견 (RFC 9460)
example.com. HTTPS 1 . alpn="h3,h2" port=443 ipv4hint=203.0.113.10
이걸 본 브라우저는 "아, 다음부터는 QUIC으로 와도 되는구나" 하고 기억한다.
최근에는 DNS의 HTTPS 리소스 레코드로 첫 접속부터 바로 HTTP/3를 쓰는 방식이 확산 중이다. 이러면 TCP 왕복 한 세트를 통째로 생략할 수 있다.
또한 브라우저는 Happy Eyeballs 방식으로 QUIC과 TCP를 동시에 시도해, 먼저 성공하는 쪽을 쓰기도 한다. UDP가 차단된 네트워크에서의 폴백 지연을 줄이기 위함이다.
7. 혼잡 제어와 손실 복구: 보이지 않는 두뇌
7.1 알고리즘을 갈아 끼울 수 있다는 자유
RFC 9002는 기본 알고리즘으로 NewReno를 서술하지만, 다른 알고리즘 사용을 허용한다.
실제 구현체들은 CUBIC, BBR, BBRv2/v3 등을 자유롭게 쓴다.
이게 왜 혁명적인가? TCP 혼잡 제어를 바꾸려면 OS 커널을 업데이트해야 한다.
QUIC은 라이브러리만 바꾸면 된다. 실험 → 측정 → 배포 사이클이 수년에서 수주로 줄어든다.
7.2 정교해진 손실 탐지
QUIC은 TCP의 여러 타이머를 PTO(Probe Timeout) 하나로 통합했다.
TCP의 RTO, TLP(Tail Loss Probe), F-RTO 등이 얽혀 있던 복잡성을 정리한 것이다.
손실 판정 기준도 명확하다.
패킷이 손실로 간주되는 조건 (둘 중 하나)
1) 패킷 번호 기반 (reordering threshold)
더 큰 번호의 패킷이 ACK되었고,
그 차이가 kPacketThreshold(=3) 이상
2) 시간 기반 (time threshold)
더 큰 번호의 패킷이 ACK되었고,
경과 시간 > max(SRTT, latest_RTT) × 9/8
또한 QUIC의 ACK 프레임에는 ACK Delay 필드가 있다.
수신 측이 "나는 패킷 받고 3ms 뒤에 ACK 보냈어"라고 알려주므로,
송신 측은 네트워크 RTT와 수신 측 처리 지연을 분리해서 계산할 수 있다. TCP에는 없던 정밀함이다.
7.3 흐름 제어의 이중 구조
QUIC은 두 단계 흐름 제어를 쓴다.
스트림 단위: MAX_STREAM_DATA로 각 스트림이 보낼 수 있는 바이트 제한
연결 단위: MAX_DATA로 연결 전체의 총량 제한
이 구조 덕분에 한 스트림이 수신 버퍼를 독식하는 것을 막으면서도, 전체 처리량은 유지할 수 있다.
추가로 MAX_STREAMS로 동시 스트림 개수까지 제어해 리소스 고갈 공격을 방어한다.
8. 실제 성능: 숫자로 보는 효과
8.1 공개된 측정 결과들
Google (YouTube·검색, gQUIC 시절 측정)
검색 지연 중앙값 약 8% 개선, 상위 1% 느린 사용자군에서는 약 16% 개선.
YouTube 리버퍼링(끊김) 비율 약 9% 감소, 모바일에서는 더 큰 폭.
Facebook (Meta)
자체 QUIC 구현 mvfst 배포 후 요청 오류율 감소 및 테일 레이턴시 개선을 보고.
Cloudflare
고손실·고지연 네트워크일수록 HTTP/3 이득이 커지며, 저손실 유선 환경에서는 차이가 미미하거나 CPU 비용으로 상쇄될 수 있음을 공개.
여기서 중요한 공학적 교훈이 나온다.
평균 응답 시간 8% 개선은 심심해 보인다.
하지만 p99(상위 1% 느린 요청)에서의 개선은 사용자 이탈률에 직접 영향을 준다.
실제 서비스 지표에서 중요한 것은 평균이 아니라 꼬리다.
8.2 어디서 가장 효과적인가
| 환경 | HTTP/3 이득 | 이유 |
|---|---|---|
| 모바일 셀룰러 (이동 중) | 매우 큼 | 커넥션 마이그레이션 + 손실 복구 |
| 고지연 국제 회선 | 큼 | 핸드셰이크 RTT 절감 |
| 패킷 손실 1% 이상 | 큼 | HOL 블로킹 제거 |
| 위성 인터넷 | 큼 | RTT 500ms대에서 왕복 절감 효과 극대화 |
| 사내 기가비트 유선 | 작음 또는 역전 | 손실 거의 없음, UDP 처리 CPU 비용 부각 |
| 대용량 단일 파일 다운로드 | 작음 | 멀티플렉싱 이점 없음, 처리량 지배 |
8.3 배포 현황
W3Techs 등의 집계에 따르면, 전 세계 웹사이트 중 HTTP/3를 지원하는 비율은 30%를 넘어 꾸준히 상승 중이다.
Cloudflare, Google, Meta, Akamai, Fastly 등 주요 CDN이 기본 활성화했기 때문에 실제 트래픽 기준 비중은 이보다 높다.
브라우저 측면에서는 Chrome, Edge, Firefox가 오래전부터 기본 지원하고, Safari도 정식 지원한다.
서버 측은 nginx(1.25+), Caddy, LiteSpeed, H2O, IIS 등이 지원하며, 라이브러리로는 quiche(Rust), msquic(C, MS), ngtcp2, quic-go, mvfst, aioquic 등이 있다.
# curl로 HTTP/3 확인
curl --http3 -I https://cloudflare-quic.com/
# 응답 예
HTTP/3 200
server: cloudflare
alt-svc: h3=":443"; ma=86400
9. 그림자: HTTP/3가 만능이 아닌 이유
9.1 CPU 비용
TCP는 수십 년간 커널·NIC 하드웨어 오프로드로 극한까지 최적화됐다.
TSO/LRO, 체크섬 오프로드, zero-copy 등 온갖 가속이 붙어 있다.
반면 QUIC은 유저 스페이스에서 돌고, 패킷마다 시스템 콜과 암복호화가 발생한다.
초기 측정에서는 TCP+TLS 대비 CPU 사용량이 2~3배에 달한다는 보고도 있었다.
완화 기술들
sendmmsg()/recvmmsg()로 배치 처리
UDP GSO/GRO(Generic Segmentation/Receive Offload)로 커널 왕복 감소
kTLS 유사의 QUIC 하드웨어 오프로드 NIC 등장
io_uring 기반 비동기 I/O
→ 현재는 격차가 상당히 좁혀졌으나, 여전히 TCP보다 무겁다
9.2 UDP 차단과 스로틀링
일부 기업 방화벽, 학교망, 공공 와이파이는 UDP 443을 막는다.
DDoS 증폭 공격의 매개로 오인되거나, 정책상 "검사 불가 트래픽"으로 분류되기 때문이다.
이 경우 브라우저는 TCP로 폴백하는데, 폴백 판정에 걸리는 시간 자체가 지연이 된다.
그래서 Happy Eyeballs 병렬 시도나 DNS HTTPS RR 기반 사전 정보가 중요해진다.
9.3 관측 가능성(Observability)의 후퇴
헤더까지 암호화되니 네트워크 운영자는 트래픽 내부를 볼 수 없다.
기존 TCP 기반 성능 분석 도구, 침입 탐지 시스템, QoS 정책이 무력화된다.
대안으로 qlog(QUIC 이벤트 로그 표준)와 qvis 시각화 도구가 등장했지만,
이는 엔드포인트가 자발적으로 로그를 남길 때만 유효하다. 네트워크 중간에서의 진단은 여전히 어렵다.
9.4 스펙 복잡도
QUIC은 전송, 암호, 손실 복구, 흐름 제어, 마이그레이션을 한 몸에 담았다.
RFC 9000만 해도 150페이지가 넘고, 관련 문서를 합치면 수백 페이지다.
직접 구현하는 것은 매우 어렵고 버그 위험이 크다.
그래서 현실적으로는 검증된 라이브러리(quiche, msquic, ngtcp2 등)를 쓰는 것이 정석이다.
10. 정보 지능공학의 관점: QUIC이 던지는 설계 철학
10.1 계층 분리의 재검토
OSI 7계층 모델은 훌륭한 교육 도구지만, 절대 진리는 아니다.
QUIC은 전송 계층과 세션/표현 계층의 경계를 의도적으로 허물었다.
그 결과 얻은 것: 핸드셰이크 병합, 중복 프레임 제거, 크로스 레이어 최적화.
잃은 것: 모듈성, 독립적 교체 가능성.
정보 지능공학에서 배우는 "추상화는 비용이 있다"는 명제의 실물 사례다.
계층은 복잡도를 관리하지만, 계층 간 정보 단절은 성능 손실을 낳는다.
10.2 배포 경로가 설계를 결정한다
QUIC이 UDP를 택한 것은 기술적 우월성 때문이 아니다.
"배포 가능한가"라는 질문에 대한 답이었다.
아무리 훌륭한 프로토콜이라도 인터넷에 배포할 수 없으면 무의미하다.
SCTP, MPTCP, TFO가 겪은 좌절이 그 증거다.
엔지니어링 원칙
"기존 인프라의 가장 넓은 공통분모 위에 새로운 층을 쌓아라."
UDP는 그 공통분모였다. 이 발상은 네트워크뿐 아니라 소프트웨어 아키텍처 전반에 적용된다. WebAssembly가 브라우저 위에, 컨테이너가 리눅스 커널 위에 쌓인 것도 같은 논리다.
10.3 암호화가 진화를 지킨다
QUIC이 헤더까지 암호화한 것은 프라이버시만의 문제가 아니었다.
미래에 프로토콜을 바꿀 수 있는 권리를 지키기 위한 조치였다.
보이지 않으면 간섭할 수 없고, 간섭받지 않으면 굳지 않는다.
IETF는 여기에 더해 GREASE(의도적으로 미지의 값을 섞어 보내 구현체의 유연성을 강제하는 기법)와 QUIC Version 2까지 도입했다.
이는 "진화 가능성을 설계 목표로 명시한" 드문 사례다.
AI 모델 인터페이스, 데이터 포맷 설계에서도 곱씹어 볼 만한 교훈이다.
이처럼 하나의 프로토콜 안에 담긴 제약·트레이드오프·배포 전략을 읽어내는 능력이야말로 정보 지능공학의 핵심 역량이다.
재능넷의 '지식인의 숲'에서는 이런 구조적 사고를 기를 수 있는 전문 지식 콘텐츠를 계속 축적하고 있다.
11. 실무 체크리스트: 지금 무엇을 하면 되나
11.1 서비스 운영자라면
| 항목 | 확인 내용 |
|---|---|
| CDN 설정 | HTTP/3 토글 활성화 여부 (대부분 클릭 한 번) |
| 방화벽 | UDP 443 인바운드 허용 |
| Alt-Svc | 헤더 정상 송출 및 ma 값 적절성 |
| DNS | HTTPS RR(TYPE65) 등록으로 첫 접속부터 h3 |
| 0-RTT | GET 등 안전 메서드로 제한, 재전송 방어 확인 |
| 모니터링 | qlog 수집, h3/h2 비율 및 p95/p99 비교 |
| 폴백 | UDP 차단 환경에서 TCP 전환 지연 측정 |
11.2 프론트엔드 개발자라면
HTTP/3 환경에서는 과거의 최적화 상식이 일부 뒤집힌다.
도메인 샤딩은 해롭다 — 연결을 쪼개면 혼잡 제어와 QPACK 테이블 공유 이점을 잃는다.
과도한 번들링은 재고 대상 — 파일 수 페널티가 줄었으므로, 캐시 효율을 위해 적절히 쪼개는 편이 낫다.
스프라이트 이미지는 대부분 불필요 — 개별 요청 비용이 낮아졌다.
우선순위 힌트 활용 — fetchpriority 속성과 Extensible Priorities(RFC 9218)로 중요 리소스를 먼저.
<!-- LCP 이미지 우선 로딩 -->
<img src="/hero.webp" fetchpriority="high" alt="메인 배너">
<!-- 비필수 스크립트 후순위 -->
<script src="/analytics.js" defer fetchpriority="low"></script>
다만 주의할 점: 여전히 HTTP/2·1.1 사용자도 존재하므로 극단적인 최적화 전환은 A/B 테스트로 검증해야 한다.
11.3 학습자라면
이론만으로는 감이 오지 않는다. 직접 관찰하자.
# 1) 크롬 개발자도구 → Network → Protocol 열 추가
# h3 / h2 / http/1.1 표시 확인
# 2) chrome://net-export 로 로그 캡처 후
# https://netlog-viewer.appspot.com 에서 분석
# 3) Wireshark로 QUIC 패킷 관찰
# 필터: quic
# SSLKEYLOGFILE 환경변수 설정 시 복호화 가능
# 4) qlog 생성 후 qvis(qvis.quictools.info)로 시각화
# - 혼잡 윈도우 변화
# - 스트림별 데이터 흐름
# - RTT 추정 그래프
12. 앞으로: QUIC이 열어젖힌 문들
12.1 WebTransport
QUIC 위에서 양방향·다중 스트림·비신뢰 데이터그램을 웹 API로 노출하는 기술.
WebSocket이 하지 못했던 "순서 보장 없는 빠른 전송"이 가능해진다.
게임, 실시간 협업, 저지연 스트리밍에서 주목받고 있다.
12.2 MASQUE
QUIC 기반 프록시 프레임워크. CONNECT-UDP, CONNECT-IP로 터널을 만든다.
Apple의 iCloud Private Relay가 이 기술을 실제로 활용한다.
VPN과 프록시 영역의 판도를 바꾸고 있다.
12.3 Multipath QUIC
Wi-Fi와 셀룰러를 동시에 사용해 대역폭을 합치거나 가용성을 높이는 확장.
MPTCP가 배포에 실패했던 지점을, QUIC의 유연성으로 재도전하는 중이다.
12.4 Media over QUIC (MoQ)
RTMP·HLS·WebRTC의 장점을 QUIC 위에서 통합하려는 시도.
초저지연 라이브 스트리밍의 차세대 후보로 IETF에서 활발히 논의 중이다.
이 모든 것의 공통점: QUIC이 "확장 가능한 범용 전송 계층"이 되었다는 것.
HTTP/3는 QUIC의 첫 번째 응용일 뿐이다. 진짜 이야기는 이제 시작이다.
마무리: 50밀리초의 무게
인간은 100ms 이하의 반응을 "즉각적"으로 인식한다.
1초를 넘으면 흐름이 끊기고, 10초를 넘으면 떠난다.
HTTP/3와 QUIC이 아껴주는 50~150ms는 숫자로 보면 사소하다.
하지만 그것은 "기다린다는 느낌이 드느냐, 안 드느냐"의 경계선 위에 있는 값이다.
그리고 그 값을 얻기 위해 엔지니어들은 30년 된 TCP를 우회하고,
UDP라는 가장 원시적인 도구 위에 전송 계층 전체를 다시 지었다.
기술의 발전은 대개 이렇게 생겼다.
화려한 발명이 아니라, 낡은 가정을 끝까지 의심하는 집요함.
다음에 웹페이지가 눈 깜짝할 새 뜨는 순간,
그 아래에서 QUIC 패킷들이 UDP 위를 병렬로 질주하고 있다는 사실을 떠올려보자.
그것이 바로, 보이지 않는 공학의 아름다움이다.
관련 키워드
댓글 작성
이 글에 대한 여러분의 생각을 들려주세요
로그인이 필요합니다
댓글을 작성하려면 먼저 로그인해주세요.
댓글 0
지식인의 숲 - 지적 재산권 보호 고지
지적 재산권 보호 고지
- 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
- AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
- 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
- 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
- AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.
아직 댓글이 없습니다.