리눅스 커널을 위한 QUIC
(lwn.net)- QUIC 프로토콜이 리눅스 커널에 공식적으로 통합되는 첫 패치가 제출됨
- 기존 TCP가 가진 한계점(지연, head-of-line blocking, 중간 장치로 인한 프로토콜 고착화 등)들을 개선하려는 목적
- QUIC은 UDP 기반으로 멀티스트림 지원과 End-to-End 암호화 기능을 제공하며, 커널 도입 시 더 넓은 플랫폼 및 하드웨어 활용 가능성 높음
- 초기 커널 구현의 성능은 기존 TCP 및 커널 TLS에 비해 낮게 측정되었지만, 향후 하드웨어 오프로딩과 최적화를 통해 성능 개선 기대 가능함
- 현재 Samba, 커널 기반 SMB/NFS, curl 등에서 지원 논의가 활발하게 이루어지고 있지만, 메인라인 합병까지는 시간이 더 소요될 전망임
QUIC 프로토콜의 등장 배경 및 TCP의 한계점
- QUIC은 기존 인터넷에서 TCP가 가진 다양한 문제점을 해결하려는 목적으로 만들어짐
- TCP의 연결 과정에서 발생하는 3-way 핸드셰이크로 인한 지연, 멀티스트림 지원 미흡, 패킷 손실에 따른 head-of-line blocking 현상 등으로 웹 사용 경험이 저하됨
- TCP의 메타데이터가 암호화되지 않은 채 전송되어 정보 유출 위험이 존재하고, 인터넷의 미들박스(중간 장치) 들이 연결 정보를 바탕으로 트래픽을 필터링, 그 결과 프로토콜의 고착화(ossification) 로 발전함
- TCP 개선 시도(예: Multipath TCP 등)도 기존 TCP로 위장하지 않으면 정상적으로 작동하지 못하는 상황임
QUIC의 특징 및 기술적 장점
- QUIC은 UDP 위에서 동작하며, 연결 과정에서 별도의 3-way 핸드셰이크 없이 빠르게 연결 설정 가능함
- 패킷 손실이 전체 스트림에 영향을 주지 않도록 멀티스트림 전송 설계가 반영됨
- QUIC 관련 전송 데이터는 항상 종단 간 암호화(TLS 기반) 되어, 중간 장치가 내부 메시지에 접근할 수 없게 됨
- UDP 패킷이 통과할 수 있는 네트워크 환경이라면 QUIC 역시 정상적으로 동작 가능함
리눅스 커널 내 QUIC 통합 패치 개요
- 제출된 패치에서는 IPPROTO_QUIC라는 새로운 프로토콜 타입이 도입되어, 기존 socket() 시스템 콜을 활용 가능함
- TCP와 유사하게 bind() , connect() , listen() , accept() 등의 콜을 사용할 수 있지만, 이후 처리 방식에는 차별점이 존재함
- TLS 세션 관리 및 인증/암호화 과정은 사용자 공간에서 처리되며, 연결 후에 각 단에서 TLS 핸드셰이크가 완료되어야 데이터 송수신이 가능함
- 초기 연결 이후에는 TLS 협상 결과를 캐싱하여, 두 시스템간 재연결 시 속도를 크게 높일 수 있음
성능 측면의 과제 및 전망
- 제출된 커널 내부 QUIC 구현은 아직 성능 면에서 기존 커널 TLS 및 TCP 대비 열세를 보임
- 인커널 TLS 대비 3배 이하 처리량, 암호화 비활성화 시에도 TCP에 비해 최대 4배까지 처리량 저조
- 원인으로는 세그멘테이션 오프로딩 미지원, 송신 경로 내 추가 데이터 복사, 헤더 암호화 과정 등이 지적됨
- 향후 하드웨어 오프로딩 지원이 추가되고, 인커널 구현이 최적화되면 성능이 향상될 것으로 기대됨
채택 현황과 향후 전망
- Samba 서버/클라이언트, 커널 SMB 및 NFS 파일시스템, curl 등 다양한 프로젝트에서 인커널 QUIC 지원 논의가 활발함
- 패치는 약 9,000 라인 규모이며, 현재 저수준 지원 코드만 포함되어 있음. 전체 구현은 추가 패치로 예고된 상태임
- 코드 리뷰 및 병합 논의가 이제 막 시작된 단계로, 실사용까지는 시간이 더 소요될 전망임
- 최근 Homa 프로토콜의 커널 병합이 9개월간 11회 제출이 필요했던 전례를 볼 때, QUIC 역시 2026년 이후 메인라인 진입이 예상됨
Hacker News 의견
- 최근 NGINX 설정에서
ssl_preread_server_name
을 추가하여 특정 도메인 요청을 다른 NGINX 인스턴스로proxy_pass
함
첫 번째 인스턴스는 단순히 원시 TLS 스트림을 전달하고(proxy_protocol
포함), 두 번째 인스턴스가 실제 TLS 종료를 맡음
이 방식은 장애 조치 구현 시 효과적임 - 서버의 기본 경로가 다운되면 DNS A 레코드를 장애 조치 머신의 NGINX로 업데이트하고, 해당 인스턴스가 특정 도메인 요청을 별도 경로로 원래 백엔드로 라우팅함
전체 TLS 구성을 복제할 필요가 없어서 편리함
단, 이 방법은 HTTP/3에는 적용 불가
HTTP/3는 QUIC 기반이고, UDP 위에서 동작하며 핸드셰이크 시 SNI를 암호화하므로ssl_preread_server_name
로 도메인 기반 라우팅 불가
HTTP/3에서 SNI 기반 라우팅을 지원할 대안이 있는지, 아니면 이 기능이 필요하다면 여전히 HTTP/1.1이나 HTTP/2 over TLS로 유지해야 하는지 궁금함- QUIC을 지원하는 클라이언트 대부분은 HTTPS DNS 레코드도 지원하므로, 낮은 우선순위 레코드를 장애 조치로 추가해 클라이언트에 일임하는 방법이 있음
실제로는 클라이언트 구현에 따라 동작이 다르지만(Chromium의 HTTPS 레코드 지원 현황 참고 이슈 링크), QUIC 접속 실패 시 클라이언트가 투명하게 HTTP/1.1/2로 폴백하며, Alt-Svc헤더 설명 헤더도 존중함
계획된 장애 조치라면 Alt-Svc 헤더를 보내지 않고 대기하면서 대체 인스턴스로 타임아웃되기를 기다릴 수도 있음
QUIC 라우팅이 정말 필요하다면, 다행히 SNI 정보가 항상 첫 패킷에 있으므로 패킷 검사로 라우팅이 가능함
cloudflare의 udpgrm이 참고가 될 수 있고, 이는 ECH(Encrypted Client Hello)가 없을 때 사용 가능함
ECH가 있을 경우 라우터가 해독 키를 가져야 라우팅 결정을 할 수 있고, 프로토콜 상 캐스케이드 장애 조치도 설계 가능함
구체적 코드 구현은 udpgrm 예시에서 확인 가능함 - TLS를 에지(예: NGINX)에서 바로 종료하는 것은 오늘날 letsencrypt 환경에서 별 위험 포인트가 아님
공격자가 해당 서버에 접근한다면 SSL 인증서 새로 발급하는 것도 쉬우므로, 굳이 복잡한 장애 조치 시스템을 고민하기보다는 직접 TLS 종료하는 편이 더 합리적임
개인적으로 QUIC의 성능·신뢰성 이점을 직접 재현해 본 적 없음
몇 년간 반복 테스트하지만, 성능 등 이유로 대부분 비활성화함
DNS 기반 장애 조치 역시 실질적으로 반영되기까지 수 분 걸리고, 브라우저 같은 단순 클라이언트는 장애 조치가 잘 안 이루어짐
그래서 직접 onerror 핸들러를 써서 두 번째 경로를 로드하는 방식 사용함
예를 들어 광고 추적 용도로 이런 식의 코드 사용하고, fetch API도 같은 방식으로 래핑해 제공함
이 방식이 다른 어떤 시도보다 훨씬 효율적임 - 장애 조치 환경이라면 QUIC 장애 조치는 신경 쓰지 않음
브라우저가 QUIC 연결에 실패해도(심지어 DNS에 광고돼 있어도) HTTP/1 혹은 HTTP/2 over TLS로 자동 폴백하므로, 기존 장애 조치 방식을 동일하게 사용 가능함 - 이 문제는 "버그가 아니다" 유형에 해당함
HTTP/3의 설계 특징이, TLS 단까지 엔드포인트 정보를 노출시키지 않는 것임
개인적으로는 이 점을 장점이라고 생각함
HAProxy는 원시 TLS 프록시 가능하지만, 호스트명 기준 라우팅은 불가함
Cloudflare tunnel은 TLS 종료 없이 호스트명 기반 라우팅이 가능한 특별한 기능이 있는데, 이를 사용하려면 DNS도 Cloudflare로 연결이 필요함
관련 xkcd 만화에서 표현한 것 참고함 - 흥미로운 질문임
TCP+TLS 환경에서 Encrypted Client Hello가 사용되는 경우에도 같은 한계가 존재하는지 의문임
답변은 거의 동일하리라 생각함
- QUIC을 지원하는 클라이언트 대부분은 HTTPS DNS 레코드도 지원하므로, 낮은 우선순위 레코드를 장애 조치로 추가해 클라이언트에 일임하는 방법이 있음
- QUIC의 단점에 대한 관련 글을 예전부터 기억함
이번 논의는 이런 문제를 조금씩 해결하는 방향이라고 느껴짐
앞으로 네트워크 카드의 하드웨어 지원 가능성도 열려 있음- QUIC은 머신 간 트래픽에는 별로 적합하지 않음
하지만 요즘 인터넷 트래픽 대부분이 모바일과 서버 간에 오가기 때문에, 그 구간에서는 QUIC과 HTTP/3가 진가를 발휘함
그 외 용도에서는 TCP 계속 활용 가능함
- QUIC은 머신 간 트래픽에는 별로 적합하지 않음
- 멀티 스트림용 소켓 API가 어떻게 나올지 궁금함
기존처럼 여러 커넥션으로 보이지만 내부적으로는 캐싱된다는 식일 듯함
나는 명시적으로 커넥션 객체를 받아서 스트림을 따로 여는 식이면 좋겠지만, 일단 현재 방식도 수용 가능함
관련 논의 확인 결과, 이게 확장 기능이 아니라면 서버 쪽에서도 커넥션 수립 후에 새 스트림 생성이 가능함
클라이언트에서 실제는 스트림이지만 "커넥션"처럼 분리 추상화가 어렵고, 근본적으로 완전 새로운 API 추상화가 필요해 보임
아마 새로운 스트림마다 recvmsg로 파일 디스크립터 받는 구조 예상함- 다중 스트림 기능은 SCTP 소켓 API가 지원하므로 SCTP 인터페이스 참고할 만함
- 커널 구현에 상관없이, OpenSSH에 QUIC 지원이 있으면 좋겠음
모쉬(Mosh)처럼 네트워크 문제에 강하면서 OpenSSH의 모든 기능(SFTP, SOCKS, 포트포워딩, 스테이트 관리, 로밍 등)도 그대로 쓰고 싶음
과연 OpenSSH가 커널 지원을 활용할 수 있을지 궁금함
Mosh 보기- SSH는 암호화와 멀티플렉싱 레이어를 QUIC으로 완전히 대체해야 하므로 대규모 작업 필요함
차라리 QUIC 기반 별도 로그인 프로토콜을 새로 만드는 게 나을 듯함
여러 접근이 프로토타입 단계로 진행 중임 - OpenSSH는 OpenBSD 프로젝트라서, Linux API에 크게 신경 쓰지 않을 가능성이 있음
- SSH는 암호화와 멀티플렉싱 레이어를 QUIC으로 완전히 대체해야 하므로 대규모 작업 필요함
- TCP의 병목이 핸드셰이크 때문이라고 하는데, 커넥션 재사용이나 멀티플렉싱으로 해결된다고 알고 있음
그런데 현재 QUIC 커널 구현이 리눅스 대비 3~4배 느리며, 성능 차이도 조만간 좁혀질 거라는 얘기 있음
속도가 QUIC의 장점인데 실제로 더 느리다면 QUIC을 쓸 이유가 무엇인지 궁금함
PR의 작성자 말로도 일부 성능 저하의 원인이 프로토콜 설계에 있다는데, 혹시 TCP에서 별도로 고칠 문제가 더 있는지 질문함- 기사에서도 QUIC이 느린 원인을 많이 언급함
대부분 "아직 최적화를 안 했다"로 요약 가능함
예컨대 세그먼트 오프로드 미지원, 트랜스미션 경로에서 추가 데이터 복사, 헤더 암호화로 인한 오버헤드 등이 있고, 모두 해결 가능성 높음
여기서 벤치마킹은 매우 이상적인 환경에서 했음
현실적으로 모바일 환경은 네트워크 변동성이 크기 때문에 TCP의 구조적 한계가 두드러짐
실제로 HTTP/2처럼 TCP 위에서도 이미 QUIC과 유사 기능을 구현하는 경우 많음
결국 QUIC은 OSI 5계층 이상에서 동작하는 종합적 네트워킹 스택이고, TCP는 3계층 수준 엔진이라 구조적으로 비교가 힘듦
무엇보다 QUIC은 더 신속한 커넥션 연결·재연결이 장점이고, IP 변동 시에도 세션 연속성을 보장함
멀티플렉싱·비차단 스트림 구조는 상위 프로토콜 설계를 획기적으로 단순화함
이런 구조가 커널에 들어오면 성능 최적화 여지도 엄청 큼
앞으로는 TCP의 한계 위에서 다층 솔루션 만들기보다는, 일상적으로 QUIC 같은 진보된 기반 기술을 더 많이 써야 함 - TCP의 병목은 핸드셰이크만이 아님
패킷 손실이 생기면, 그 이후 전송분 전체가 복구될 때까지 지연되므로(HOL blocking) 구조적 한계가 큼 - "존재하지 않는 커넥션"을 재사용할 수 없으므로, 많은 논의가 레이턴시(지연) 단축에 초점 맞춤
그냥 속도 문제가 아니라 지연 개선임 - QUIC의 이점은 서버 제공 connection ID 기반 추적 기능임
기술 설명 문서 참고
- 기사에서도 QUIC이 느린 원인을 많이 언급함
- 네트워킹 스택을 유저스페이스로 옮겨서 성능을 높인다는 메시지와, 커널 쪽으로 옮기자는 이번 논의에서 혼란이 듦
- 대부분의 QUIC 스택은 커널 내 UDP위에서 동작함
커널과 사용자 공간 간 컨텍스트 스위치가 주요 병목임
유저스페이스 네트워킹(예: NIC 직접 접근)은 커널 진입을 없애줌
반대로 커널 공간에서 기능 제공(예: sendfile, in-kernel TLS, NIC 오프로딩, 디스크에서 NIC로 바로 DMA)도 전체 컨텍스트 스위치와 데이터 복사를 줄임
현재 QUIC 스택은 양쪽 장점을 모두 활용하지 못함
패킷 입출력이 syscall 기반이고, 데이터 복사를 피하지 못함
io_uring 등으로 배치 IO하면 스위치는 줄지만, 복사 자체는 줄이지 못함 - 맞는 말임
커널 바이패스+DMA, 혹은 sendfile/ktls 구조처럼 사용자 공간 제외 등 두 가지 방식이 있음
Quic 커널 구현에는 양쪽 이점이 다 없음 - 결국 NIC 버퍼로 데이터를 넘겨야 하는 건 같은 구조임
DMA로 니팅 직접 쓸 수 있거나, 커널 syscall로 넘긴다면 성능 차이가 크기 때문에
사용자 공간 네트워킹은 이런 privilege 전환 및 DMA 구조가 있을 때만 설득력 있음 - 유저스페이스가 직접 네트워크 데이터 접근(아마도 syscall 없이)하는 방식이 적용되는 것은 일반 사용자 소프트웨어에는 별 의미 없음
대규모 기업(MOFAANG 등)에서만 활용
이론적으로 io_uring이 위 혜택을 일반화할 것이란 기대가 있지만, 아직 실사용 단계는 아님 - 하드웨어 접근 시 컨텍스트 전환이 너무 느림
그래서 TCP/IP는 주요 OS에서 커널에 남아 있음
- 대부분의 QUIC 스택은 커널 내 UDP위에서 동작함
- "왜 커널에 점점 기능을 더 넣는가?"
커널은 메모리, 하드웨어, 태스크 관리가 역할이라 생각했는데, IP 위 프로토콜은 유저랜드에서 처리해야 옳지 않은가 질문함- 네트워킹, 라우팅, VPN 등을 모두 커널 공간에서 처리하면 일부 사용 사례에서 성능 개선됨
반대로 이런 스택을 유저스페이스로 분리해도 일부 사례는 성능 개선 효과 있음 - 커널에 들어가면 하드닝(보안성), LTS 지원, 그리고 커널 및 네트워크 수준 최적화의 장점이 있음
- 주된 이유는 DMA 트랜스퍼 및 NIC 오프로딩 최적화임
- IP 위 프로토콜 전체를 유저스페이스에 두면, 멀티프로세스 사용이 불가능함
TCP/UDP가 커널에서 포트기반으로 소켓 라우팅을 중재하기 때문에, 여러 프로그램이 동시에 TCP/UDP 사용 가능함
QUIC은 UDP 위에서 동작하며, 따라서 논의의 요지는 여전히 설득력 있음
IP 바로 위 프로토콜만 유저스페이스에서 못 돌린다는 점 강조함
- 네트워킹, 라우팅, VPN 등을 모두 커널 공간에서 처리하면 일부 사용 사례에서 성능 개선됨
- QUIC은 많은 이들에게 획기적 변화를 제공한다고 생각됨
앞으로 인터넷이 좀 더 빨라질 것이라고 기대함
5G 같은 통신환경에서는 차이가 안 느껴질 수도 있지만, 가치 있는 발전임
별도 링크 핸드셰이크 구조가 있다는 게 신기함
원래 QUIC이 TLS를 자체 내장하는 줄 알았던 것과는 달랐음 - 웹 전체가 느려진 주된 이유는 웹사이트가 너무 무거워져서임
그래도 게임 레이턴시는 이번 기술로 더 낮아질 수 있다고 생각함-
제번스의 역설이 여기에도 적용됨
컴퓨팅 리소스와 네트워크 효율이 올라가면 수요 자체도 늘어남
게임이나 과학연산에서는 "더 나은 결과"를 위해 상관없지만
웹에서는 광고, 추적, 자바스크립트 증가로 인해 역효과가 많음
-
제번스의 역설이 여기에도 적용됨
- 기사에서 QUIC은 TCP처럼 bind(), connect(), listen(), accept() 등으로 커넥션을 수립하지만, 이후 sendmsg()와 recvmsg() syscall을 이용한 구조로 달라짐
왜 이 접근방식을 채택했는지, 왜 QUIC에 맞는 별도 시스템콜을 만들지 않았는지 설명도 있었으면 좋겠음