QUIC과 전송 계층의 진화
TCP는 인터넷의 기반이며 수십 년 동안 잘 동작해 왔습니다. 하지만 웹이 점점 더 빠른 응답을 요구하면서, TCP의 구조적 한계가 부각되기 시작했습니다. TCP를 개선하면 되지 않나?라는 질문에 대한 답은, TCP가 운영체제 커널에 깊이 박혀 있어 변경이 매우 어렵다는 현실입니다.
TCP 구현 위치: 운영체제 커널 (Linux, Windows, macOS)
변경 프로세스
1. 리눅스 커널 패치 작성 (수개월)
2. 커널 메인라인 병합 승인 (수개월~수년)
3. 리눅스 배포판 반영 (수개월)
4. 기업/클라우드 OS 업그레이드 (수년)
5. 전 세계 미들박스(방화벽) 업데이트 (사실상 불가능)
결론: TCP 개선 아이디어 → 전 세계 적용까지 5~10년
그 사이에도 미들박스가 새 옵션을 차단할 수 있음!
Google의 발상 전환
"커널을 바꿀 수 없다면... 사용자 공간에서 새로 만들자"
"UDP는 커널이 거의 건드리지 않으니, UDP 위에 올리자"이 배경에서 구글이 만든 것이 QUIC입니다.
HTTP 버전별 진화와 한계
QUIC을 이해하려면 HTTP가 어떻게 발전해 왔고, 각 버전에서 무엇이 문제였는지 알아야 합니다.
HTTP/1.0 (1996)
요청마다 새 TCP 연결
┌─TCP─┐ ┌─TCP─┐ ┌─TCP─┐
│GET /│ │GET /│ │GET /│
│html │ │css │ │js │
└─────┘ └─────┘ └─────┘
문제: 연결 오버헤드 × N
↓
HTTP/1.1 (1997) - Keep-Alive
하나의 TCP에서 순차 요청
┌────────TCP─────────┐
│ GET html → 응답 │
│ GET css → 응답 │ ← 앞 응답 완료 후 다음 요청
│ GET js → 응답 │
└────────────────────┘
문제: 응용 레벨 HOL Blocking (파이프라이닝 시도했으나 실패)
↓
HTTP/2 (2015) - 멀티플렉싱
하나의 TCP에서 동시 요청
┌────────TCP────────┐
│ [html][css][js] │ ← 한 연결에서 동시 전송
│ 스트림이 인터리빙 │
└───────────────────┘
해결: 응용 레벨 HOL Blocking ✓
문제: TCP 레벨 HOL Blocking! 패킷 1개 손실 → 모든 스트림 정지
↓
HTTP/3 (2022) - QUIC
UDP 위의 QUIC에서 독립 스트림
┌────────QUIC────────┐
│ 스트림A: [html] │ ← 각 스트림 독립
│ 스트림B: [css] │ ← A 손실해도 B 정상
│ 스트림C: [js] │
└────────────────────┘
해결: TCP 레벨 HOL Blocking ✓HTTP/2가 응용 레벨의 HOL Blocking은 해결했지만, TCP라는 전송 계층 자체의 HOL Blocking은 해결할 수 없었습니다. 하나의 TCP 연결에서 여러 스트림을 동시에 전송해도, TCP가 순서를 보장하기 때문에 하나의 패킷이 손실되면 모든 스트림이 그 패킷의 재전송을 기다려야 합니다.
송신: [A1][B1][C1][A2][B2][C2][A3][B3][C3]
↑
B2 패킷 손실!
TCP 수신 버퍼
[A1][B1][C1][A2][ ][C2][A3][B3][C3]
↑
빈 자리 (B2 대기)
TCP의 동작
→ B2 이후의 모든 데이터를 애플리케이션에 전달하지 않음
→ C2, A3, B3, C3 모두 블로킹!
→ 스트림 A, C는 B와 무관한데도 피해
손실률 2%에서의 영향
HTTP/1.1 (6개 병렬 연결): 각 연결 독립 → 손실된 연결만 영향
HTTP/2 (1개 TCP 연결): 전체 멀티플렉싱이 블로킹됨
→ 높은 손실률에서 HTTP/2가 HTTP/1.1보다 느릴 수 있음!QUIC의 핵심 구조
QUIC은 UDP 위에서 동작하지만, 단순히 UDP 위의 TCP가 아닙니다. TCP와 TLS의 기능을 통합하면서 근본적으로 다르게 설계되었습니다.
HTTP/2 스택
┌──────────┐
│ HTTP/2 │
├──────────┤
│ TLS 1.2 │
│ / 1.3 │
├──────────┤
│ TCP │
├──────────┤
│ IP │
└──────────┘
커널 영역: TCP, IP
사용자 영역: HTTP, TLS
HTTP/3 스택
┌──────────┐
│ HTTP/3 │
├──────────┤
│ QUIC │ ← TCP+TLS 통합
│ (TLS 1.3 │
│ 내장) │
├──────────┤
│ UDP │
├──────────┤
│ IP │
└──────────┘
커널 영역: UDP, IP
사용자 영역: HTTP, QUIC(TLS 포함)| 기능 | TCP + TLS | QUIC |
|---|---|---|
| 연결 수립 | 1 RTT (TCP) + 1-2 RTT (TLS) | 1 RTT (통합) |
| 재연결 | 1 RTT (TCP) + 1 RTT (TLS) | 0 RTT |
| HOL Blocking | 있음 (바이트 스트림) | 없음 (독립 스트림) |
| 암호화 범위 | 페이로드만 | 헤더 + 페이로드 |
| 연결 마이그레이션 | 불가 (IP:Port 기반) | 가능 (Connection ID 기반) |
| 구현 위치 | 커널 | 사용자 공간 |
| 업데이트 속도 | 커널 업데이트 필요 (수년) | 앱 업데이트로 가능 (수주) |
| 혼잡 제어 | 커널 구현 | 사용자 공간 (자유롭게 교체 가능) |
연결 수립 시간 비교
TCP + TLS와 QUIC의 연결 수립 과정을 비교하면, QUIC의 장점이 선명하게 드러납니다.
클라이언트 서버
│ │
│──── SYN ──────────────────────────→│ ┐
│←─── SYN-ACK ───────────────────────│ │ 1 RTT (TCP)
│──── ACK + ClientHello ────────────→│ ┘
│←─── ServerHello + Finished ────────│ ┐
│──── Finished + HTTP 요청 ─────────→│ │ 1 RTT (TLS)
│←─── HTTP 응답 ─────────────────────│ ┘
│ │
총: 2 RTT 후 첫 데이터 전송
클라이언트 서버
│ │
│──── QUIC Initial ─────────────────→│ ┐
│ (ClientHello 포함) │ │
│←─── QUIC Handshake ────────────────│ │ 1 RTT
│ (ServerHello + Finished) │ │
│──── HTTP 요청 ────────────────────→│ ┘
│←─── HTTP 응답 ─────────────────────│
│ │
총: 1 RTT 후 첫 데이터 전송 (TCP 대비 50% 감소)재연결 시에는 차이가 더 극적입니다. QUIC은 이전 연결에서 협상한 키를 캐시하여, 0 RTT로 즉시 데이터를 전송할 수 있습니다.
클라이언트 서버
│ │
│──── QUIC Initial ─────────────────→│
│ + 0-RTT 데이터 (HTTP 요청) │ ← 연결과 동시에 데이터 전송!
│←─── QUIC Handshake + HTTP 응답 ────│
│ │
총: 0 RTT! 첫 패킷부터 데이터 포함
※ 0-RTT는 Replay Attack 위험이 있어 멱등(GET) 요청에만 사용서울 → 미국 서버 기준 RTT가 약 150ms라면, TCP+TLS는 300ms, QUIC은 150ms, 0-RTT는 0ms 후 첫 요청을 보낼 수 있습니다. 모바일 환경에서 이 차이는 체감 성능에 큰 영향을 미칩니다.
연결 마이그레이션
TCP에서는 연결이 4-tuple(소스IP, 소스포트, 목적지IP, 목적지포트)로 식별됩니다. 스마트폰에서 Wi-Fi → LTE로 전환하면 소스 IP가 바뀌므로, 기존 TCP 연결이 끊기고 새로 연결해야 합니다.
TCP (4-tuple 기반)
Wi-Fi 연결: 192.168.1.5:12345 → 93.184.216.34:443
LTE 전환: 10.0.0.7:54321 → 93.184.216.34:443
↑ IP 변경!
→ TCP 연결 끊어짐
→ 새 3-way handshake + TLS handshake 필요
→ 진행 중이던 다운로드 처음부터 다시 시작
QUIC (Connection ID 기반)
Wi-Fi 연결: CID = 0xABCD1234
LTE 전환: CID = 0xABCD1234 ← 같은 Connection ID
→ IP 바뀌어도 서버가 같은 연결로 인식
→ 끊김 없이 계속 전송
→ 사용자는 네트워크 전환을 느끼지 못함이 Connection ID 기반의 연결 식별은, 모바일 환경에서 Wi-Fi ↔ LTE 전환이 빈번한 현대 사용 패턴에 특히 중요합니다. 지하철에서 영상을 보다가 역 사이를 지날 때, 네트워크가 바뀌어도 스트리밍이 끊기지 않습니다.
HTTP/3와 QUIC의 관계
HTTP/3는 전송 계층으로 TCP 대신 QUIC을 사용하는 HTTP의 최신 버전입니다.
QUIC 패킷
┌──────────────────────────────────┐
│ QUIC Header (Connection ID 등) │ ← 부분 암호화
├──────────────────────────────────┤
│ QUIC Frame 1: │
│ Stream ID: 0 │
│ HTTP/3 HEADERS frame │ ← 전체 암호화
│ (QPACK 압축 헤더) │
├──────────────────────────────────┤
│ QUIC Frame 2: │
│ Stream ID: 0 │
│ HTTP/3 DATA frame │
│ (응답 바디) │
└──────────────────────────────────┘
QUIC이 제공하는 기능 → HTTP/3가 중복 없이 사용
* 멀티플렉싱 → QUIC 스트림으로 대체
* 흐름 제어 → QUIC 흐름 제어 사용
* 헤더 압축 → HPACK → QPACK (독립 스트림에 맞게 개선)2022년에 IETF가 QUIC(RFC 9000)과 HTTP/3(RFC 9114)를 정식 표준으로 발표했습니다. 현재 대부분의 주요 브라우저(Chrome, Firefox, Safari, Edge)와 CDN(Cloudflare, CloudFront)이 HTTP/3를 지원합니다.
# 특정 사이트의 HTTP/3 지원 확인
curl -I --http3 https://www.google.com 2>&1 | head -5
# Chrome에서 QUIC 연결 확인
# chrome://net-internals/#quic 접속
# curl로 QUIC 연결 상세 정보
curl -v --http3 https://cloudflare.com 2>&1 | grep -i "quic\|http/3\|alt-svc"
# Alt-Svc 헤더로 HTTP/3 지원 확인 (HTTP/2 응답에 포함됨)
curl -sI https://www.google.com | grep -i alt-svc
# alt-svc: h3=":443"; ma=2592000
# h3 = HTTP/3 지원, 443 포트, max-age=30일QUIC의 현실적 고려사항
QUIC이 만능은 아닙니다. 도입 시 고려해야 할 현실적인 문제들이 있습니다.
장점
✓ 연결 수립 시간 단축 (1 RTT, 0 RTT 재연결)
✓ HOL Blocking 해결
✓ 연결 마이그레이션 (모바일 친화)
✓ 기본 암호화 (보안 강화)
✓ 사용자 공간 구현 (빠른 배포/업데이트)
단점
✗ UDP 차단: 일부 기업 방화벽이 UDP 443 차단
✗ CPU 사용량: 사용자 공간 암호화 → 커널 TCP보다 CPU↑
✗ 미들박스 호환성: 방화벽/IDS가 QUIC 트래픽 검사 어려움
✗ UDP 성능: 커널 UDP 스택은 대량 트래픽에 최적화 안 됨
✗ 디버깅: Wireshark로 패킷 분석 어려움 (암호화)
현실적 전략 (브라우저)
1. HTTP/3(QUIC)으로 연결 시도
2. UDP가 차단되었으면 HTTP/2(TCP)로 폴백
3. Alt-Svc 헤더로 서버의 QUIC 지원 여부 확인| 환경 | QUIC 효과 |
|---|---|
| 모바일 (높은 손실률) | 매우 효과적 (HOL Blocking 제거) |
| 모바일 (네트워크 전환) | 매우 효과적 (연결 마이그레이션) |
| 저지연 LAN | 효과 미미 (TCP와 차이 作음) |
| 높은 RTT (해외 서버) | 효과적 (RTT 절감 큼) |
| 기업 네트워크 | 주의 필요 (UDP 차단 가능성) |
| 대용량 파일 전송 | 커널 TCP가 여전히 효율적일 수 있음 |
멀티캐스트, 브로드캐스트, 애니캐스트
전송 계층의 마지막 주제로, 일대다 통신 패턴을 살펴보겠습니다.
유니캐스트 (1:1)
A ──→ B
네트워크 사용량: 수신자 수 × 데이터 크기
브로드캐스트 (1:ALL)
A ──→ B, C, D, E, F (같은 네트워크 전체)
┌─────────────────────┐
│ A ──broadcast──→ │
│ B C D E F │ ← 원하든 원하지 않든 전부 수신
└─────────────────────┘
범위: LAN 내 한정, 라우터를 넘지 못함
예: ARP, DHCP
멀티캐스트 (1:GROUP)
A ──→ B, D (그룹 가입자만)
┌─────────────────────┐
│ A ──multicast──→ │
│ B* C D* E F │ ← *그룹 가입자만 수신
└─────────────────────┘
범위: 라우터를 넘어 전달 가능 (IGMP/PIM)
예: IPTV, 화상회의, 주식 시세
애니캐스트 (1:NEAREST)
같은 IP를 가진 여러 서버 중 가장 가까운 곳으로
┌────────────────────────────────┐
│ 클라이언트(한국) │
│ │ │
│ ├── 서버A(도쿄) ← 선택! │
│ ├── 서버B(미국) │
│ └── 서버C(유럽) │
│ 3개 서버 모두 IP: 1.1.1.1 │
└────────────────────────────────┘
예: CDN, DNS 루트 서버, Cloudflare| 통신 패턴 | 수신자 | 범위 | 프로토콜 | 사용 사례 |
|---|---|---|---|---|
| 유니캐스트 | 특정 1개 | 전역 | TCP/UDP | 웹, 이메일, 파일 전송 |
| 브로드캐스트 | 모든 장치 | LAN | UDP | ARP, DHCP |
| 멀티캐스트 | 그룹 가입자 | 설정에 따라 | UDP | IPTV, 화상회의 |
| 애니캐스트 | 가장 가까운 1개 | 전역 | TCP/UDP | CDN, DNS 루트 서버 |
같은 영상을 100명에게 보낼 때, 유니캐스트로 100개의 스트림을 보내는 것보다 멀티캐스트로 한 번만 보내는 것이 훨씬 효율적입니다.
유니캐스트로 100명에게 4K 영상 전송
서버 ──┬── 25Mbps → User1
├── 25Mbps → User2
├── 25Mbps → User3
│ ...
└── 25Mbps → User100
서버 대역폭: 25Mbps × 100 = 2,500Mbps = 2.5Gbps
멀티캐스트로 100명에게 4K 영상 전송
서버 ── 25Mbps → 라우터 ──┬→ User1
├→ User2
├→ ...
└→ User100
서버 대역폭: 25Mbps (100배 절약!)
라우터가 패킷을 복제하여 그룹 멤버에게 전달UDP는 이런 일대다 통신에 자연스럽게 적합합니다. TCP는 연결 지향이라 일대일 통신에 특화되어 있지만, UDP는 연결이 없으므로 하나의 패킷을 여러 수신자에게 유연하게 전달할 수 있습니다.
전송 계층 면접 총정리
| 주제 | 질문 | 핵심 답변 |
|---|---|---|
| QUIC | QUIC이 UDP 위에 구현된 이유? | TCP는 커널에 있어 변경이 어렵고, UDP는 커널이 거의 처리하지 않아 사용자 공간에서 자유롭게 구현 가능 |
| QUIC | 0-RTT의 보안 위험? | Replay Attack 가능 → 멱등 요청(GET)에만 사용, POST 등은 1-RTT 필요 |
| QUIC | 연결 마이그레이션이란? | Connection ID 기반 식별로, IP 변경(Wi-Fi→LTE)에도 연결 유지 |
| HTTP/3 | HTTP/2 대비 장점? | TCP HOL Blocking 제거, 연결 설정 시간 단축, 기본 암호화 |
| 통신패턴 | 유니캐스트/멀티캐스트 차이? | 유니캐스트는 1:1, 멀티캐스트는 1:그룹, 네트워크 효율성 차이 |
| 애니캐스트 | CDN에서 애니캐스트 활용? | 같은 IP를 전 세계 서버에 할당, BGP가 가장 가까운 서버로 라우팅 |
다음 장에서는 브라우저에 도메인 이름을 입력하면 벌어지는 일, DNS의 세계를 들여다보겠습니다.