Noq - Rust로 구현된 n0의 새로운 QUIC 구현

Noq: n0's new QUIC implementation in Rust

요약

Iroh 팀이 멀티패스와 NAT 트래버설을 지원하는 독립형 QUIC 프로토콜 구현인 Noq를 공개했다. Quinn에서 하드 포크하여 QUIC 멀티패스, NAT 트래버설, 주소 발견 등 고급 기능을 제공한다.

핵심 포인트

  • QUIC Multipath 스펙 완전 구현으로 멀티 경로 연결을 QUIC 계층에서 직접 관리 가능
  • NAT 트래버설을 QUIC 레벨 작업으로 표현하여 신뢰성과 지연 시간 개선
  • QLog 지원 확대 및 WeakConnectionHandle 등 새로운 API 추가로 개발자 경험 향상

왜 중요한가

P2P 네트워킹, 실시간 통신, IoT 등 다양한 네트워크 환경에서 안정적인 연결이 필요한 애플리케이션 개발에 필수적인 기반 기술이다.

📄 전문 번역

noq 공개: iroh가 만든 범용 QUIC 구현체

오늘 우리는 noq(Number 0 QUIC)를 발표하게 되어 기쁩니다. 멀티패스와 NAT 트래버설 기능을 갖춘 범용 QUIC 구현체인데요, iroh v0.96부터 이를 통해 강화된 전송 계층을 사용하고 있습니다. 물론 noq는 iroh에만 국한되지 않습니다.

소프트 포크에서 하드 포크로

iroh의 개발 과정을 따라오셨다면, 2024년에 Quinn을 포크한 이유에 대해 읽으셨을 수도 있어요. 간단히 말하면 iroh는 QUIC 계층에서 정말 많은 작업을 하고 있었습니다. 릴레이와 직접 연결 경로를 오가며, NAT 트래버설을 관리하고, 혼잡 상태를 조절하는 식이죠.

그런데 QUIC 자체는 이 모든 작업이 벌어지고 있다는 걸 아무것도 몰랐습니다. 이런 불일치가 외부에서 고칠 수 없는 문제들을 만들어냈어요.

처음에는 작은 규모였습니다. 우리는 Quinn의 업스트림을 긴밀히 따라가면서 기여하고, 차이를 최소한으로 유지하려고 했습니다. 그 당시엔 올바른 선택이었어요.

하지만 QUIC 멀티패스, NAT 트래버설, 그리고 우리의 릴레이-애즈-어-패스 아키텍처로 더 나아가면서, 두 프로젝트의 개발 속도가 맞지 않기 시작했습니다. 우리의 끊임없는 변화가 Quinn 유지보수자들에게 합리적이지 않은 리뷰 부담을 지워졌을 테니까요.

n0 팀은 QUIC 구현체에 더 깊은 구조적 변화를 시도하고 싶었는데, 그것이 모든 Quinn 사용자에게 영향을 미치는 건 공정하지 않았습니다. 계속 협력하겠다는 약속 아래 하드 포크하는 것이 모두에게 합리적이라고 생각했죠.

그렇게 우리는 완전한 분리를 선택했습니다. [Quinn multipath 이슈 스레드](https://github.com/quinn-rs/quinn/issues/1570)에서 우리의 생각을 설명했으니 참고하세요.

이건 Quinn을 거부하는 것이 아닙니다. Quinn은 훌륭한 구현체고, 지금도 그렇습니다. 우리가 해결하는 문제들이 충분히 구체적이어서, 관심사가 겹치는 부분에서만 협력하는 별개의 코드베이스가 정직한 길이라는 걸 인정하는 것일 뿐입니다.

noq가 담은 것들

QUIC Multipath

가장 주목할 기능은 QUIC Multipath 스펙의 완전한 구현입니다. 이게 진짜 아키텍처 변화가 일어난 곳이에요.

예전에는 iroh가 여러 경로(릴레이, 직접 IPv4, 직접 IPv6)를 QUIC 계층 아래에서 손재주처럼 관리했습니다. 마치 Quinn 주위에 iroh만의 작은 NAT이 있는 것처럼요. Quinn은 한 IP 주소를 통해 상대방과 대화한다고 생각하는 동안, 우리는 가장 잘 작동하는 경로로 패킷을 옮겼던 거죠.

이제 멀티패스가 생기면서 이런 경로들이 QUIC의 1급 개념이 됐습니다. 릴레이 경로도 QUIC 경로고, 직접 UDP 경로도 QUIC 경로입니다. QUIC이 모두를 알고 있으며, 경로별 혼잡 상태를 유지하고, 어느 경로를 사용할지 판단할 수 있게 되었어요.

덕분에 혼잡 컨트롤러 리셋으로 억지로 개선했던 지연 시간 문제가 이제는 올바르고 체계적으로 처리됩니다.

다만 이 멀티패스 구현은 iroh만을 위한 게 아닙니다. QUIC Multipath 스펙의 완전한 구현을 목표로 하며, 어떤 용도에든 쓸 수 있도록 설계했어요. 구현이 아직 젊으니, 더 필요한 API가 있으면 알려주세요.

QUIC NAT Traversal

우리는 QUIC NAT traversal 드래프트의 우리만의 해석을 구현했습니다. 알려진 한 우리가 처음으로 프로덕션 수준에서, 견고하게 이를 구현했어요.

NAT 트래버설은 악명 높게 까다롭습니다. 실제 환경의 다양한 NAT 동작을 모두 아우르며 제대로 하는 건 어려운 문제거든요. 이미 iroh를 실행 중인 수십만 대의 기기에서 우리 접근법을 전투 테스트했습니다.

아직 확정된 스펙은 아니지만 계속 개선해 나갈 거고요.

NAT 트래버설 홀 펀칭을 QUIC 아래에서 벌어지는 것이 아닌 QUIC 레벨 작업으로 표현하는 것이 더 깔끔하고 신뢰할 수 있습니다. QUIC 혼잡 컨트롤러가 이를 인지하고 손실 탐지를 더 잘할 수 있기 때문이에요.

QUIC Address Discovery

iroh는 iroh v0.32부터 우리의 QUIC Address Discovery(QAD) 구현을 사용해왔습니다. 예전에는 STUN을 이용해서 클라이언트의 공개 IP 주소를 알아냈는데, QAD는 QUIC 연결을 이용합니다.

QUIC을 쓰면 STUN 대비 왕복을 희생하지 않으면서 이 패킷들을 암호화할 수 있어요. 덕분에 프로토콜 경화를 방지하고 사용자 프라이버시를 강화할 수 있습니다.

더 나은 QLog 지원

QLog는 QUIC 연결에 대한 엄청나게 많은 정보를 기록하는 드래프트 표준입니다. qvis 같은 시각화 도구를 이용하면 두 피어 사이의 패킷 흐름을 볼 수 있어서 디버깅할 때 정말 좋아요.

noq에서는 QLog 지원을 크게 확장했습니다. 메인 QLog 로깅 스키마와 QUIC 이벤트 정의에서 훨씬 더 많은 이벤트를 지원하게 됐거든요. 추가로 QLog의 확장성을 이용해 QUIC 멀티패스 이벤트도 넣었습니다.

심지어 여러 경로를 넘나드는 패킷 흐름을 보여주는 뷰어 프로토타입도 만들었습니다.

WeakConnectionHandle

noq의 API 변화 대부분은 멀티패스 지원 중심이지만, WeakConnectionHandle도 추가했습니다.

이건 연결을 살아있게 유지하지는 않지만, 아직 드롭되지 않았다면 완전한 Connection으로 업그레이드할 수 있는 타입입니다. std::sync::Weak처럼 동작하는데, Arc로 감싸지 않아도 되거든요(항상 쉬운 건 아니니까요).

이건 연결 관리자 같은 걸 만들 때 유용합니다. iroh 내부에서도 이미 필요했고, 다른 좋은 사용 사례들도 분명 있을 거예요.