iroh 1.0까지의 여정 - IPFS 구현에서 공개 키 기반 연결 라이브러리로
요약
Rust 기반의 P2P 네트워킹 라이브러리 iroh가 1.0 버전을 출시했습니다. 초기 IPFS 구현에서 출발했으나, 성능 및 사용성 제약에 맞춰 QUIC와 BLAKE3를 결합한 공개 키 기반 연결 라이브러리로 방향을 전환했습니다. 이로써 다양한 환경의 기기 간 안정적이고 신뢰할 수 있는 데이터 동기화 기능을 제공합니다.
핵심 포인트
- IPFS 호환성을 포기하고 QUIC/BLAKE3 기반으로 단순화하여 성능 최적화를 달성함.
- 공개 키를 이용해 인증 및 암호화된 연결을 구축하며, 홀 펀칭과 릴레이로 신뢰성을 확보함.
- 초기 목표였던 IPFS 구현에서 벗어나 실제 앱(Delta Chat)의 요구사항에 맞춰 경량 동기화 라이브러리로 진화함.
공개 키만으로 상대를 지정해 인증되고 암호화된 연결을 만드는 Rust 라이브러리 iroh 가 4년간의 개발 끝에 1.0 출시. 여러 차례 방향을 바꾸며 핵심 연결 기능에 집중
처음에는 모바일 기기를 위한 IPFS 구현 이었지만, Delta Chat의 채팅 기록 전송조차 성능과 의존성 제약을 충족하기 어려웠음. IPFS 호환성을 포기하고 QUIC와 BLAKE3 기반 전송 으로 단순화
서로 다른 네트워크의 기기도 연결하도록 홀 펀칭과 릴레이, 공개 키 기반 주소 조회 를 도입. 직접 연결이 어려운 환경에서는 보조 서버를 활용하며 연결의 신뢰성을 우선
문서와 데이터 동기화까지 갖춘 통합 개발 도구로 확장했지만, 커진 API 전체의 품질을 유지하기 어려워짐. 모든 사용자에게 공통으로 필요한 연결만 남기고 나머지는 별도 크레이트로 분리
1.0은 통신 형식과 API의 안정화를 의미 하며 내부 개선은 계속됨. 네트워크 경로를 끊김 없이 전환하기 위한 멀티패스 지원은 quinn을 포크한 자체 QUIC 구현 noq 로 발전
IPFS 구현에서 출발한 전송 실험
초기 iroh는 휴대전화처럼 자원이 제한된 기기를 목표로 한 Rust 기반 IPFS 구현 이었으며, 여러 IPFS 프로토콜을 구현하고 기존 구현과의 상호운용도 지원함
기존 블롭 전송 프로토콜에 만족하지 못해 IPFS 커뮤니티 안에 move the bytes 워킹 그룹 을 만들고 새 프로토콜을 추진함
실험용 라이브러리 krakensync 는 콘텐츠 주소 지정에 BLAKE3 만 사용함. 대용량 블롭을 점진적으로 스트리밍하면서 검증할 수 있기 때문임
기본 알고리듬을 만든 뒤 다음 회의까지 이틀 안에 네트워킹을 붙여야 했으나, 당시 rust-libp2p 로는 어렵다고 판단함
quinn-noise 를 통해 알게 된 quinn 은 수정하기 쉽고 Rust다운 간결한 API를 제공해, QUIC 기반 데모를 만드는 데 적합했음
이 실험은 LLM 코딩 도우미가 등장하기 전 진행됨
Delta Chat의 요구와 IPFS 호환성 포기
병행하던 프로젝트는 Delta Chat 의 새 기기 설정 과정에서 채팅 기록 백업 하나를 전송 하는 기능이었음
디스크와 네트워크 사용량에 엄격한 제약이 있었고, 중단된 전송을 재개할 수 있어야 했음
IPFS 기반 iroh로는 이 좁은 요구조차 충족하기 어려웠으며, 네트워크 성능이 충분하지 않고 의존성 트리도 너무 커졌음
별도의 경량 동기화 라이브러리를 처음부터 만들면서 QUIC 네트워킹과 BLAKE3 검증 스트리밍 을 결합함
본 프로젝트보다 실험용 동기화 프로젝트가 성능 가능성을 더 잘 보여주자, 기존 IPFS 구현과의 호환성을 포기하기로 결정 함
기능은 크게 줄었지만 남은 기능은 최적에 가까운 성능을 냈고, Delta Chat의 Rust 코드베이스에 포함 할 만큼 가벼워짐
Windows, Linux, iOS, Android에서 수천 명이 사용하는 실제 앱에 네트워킹과 동기화 기능이 배포됨
이전 IPFS 기반 코드는 beetle 에 남아 있음
TLS를 유지하면서 인증서 복잡성 줄이기
QUIC는 클라이언트와 서버 역할이 명확하고 서버를 인증서 체인으로 식별하므로, 초기 P2P 연결에는 자체 서명 인증서 를 추가로 활용해야 했음
rustls 자체가 무거운 의존성이고 기본 암호화 제공자가 C에 의존한다는 점 때문에, TLS 전체를 P2P용 Noise 기반 프로토콜로 대체하는 방안도 검토함
최종적으로는 산업 표준인 TLS를 유지 함. TLS를 쓰지 않으면 QUIC 자체가 아니라 일부 구성 요소만 재사용하는 형태가 되기 때문임
마침 원시 공개 키 지원이 rustls에 병합 되면서, 자체 서명 인증서 대신 TLS의 원시 공개 키 방식으로 전환 함
같은 네트워크를 넘어서는 홀 펀칭
초기 Delta Chat 기록 전송은 두 기기가 같은 네트워크 에 있어야 했음. 인터넷에 연결돼 있다면 어디서든 빠르게 전송하도록 홀 펀칭 )을 도입함
완전한 P2P 구성보다 신뢰할 수 있는 연결 을 우선했으며, 필요하다면 보조 서버를 사용하는 것도 허용함
여러 오픈소스 구현 중 Tailscale 의 접근법이 요구에 가장 잘 맞아, 초기에는 이와 매우 유사한 방식을 대규모 작업을 거쳐 구현 함
일반적인 환경에서는 거의 즉시 홀 펀칭에 성공함
홀 펀칭이 불가능한 일부 기업 네트워크에서도 릴레이를 통해 데이터를 전송할 수 있었음
통합 P2P 개발 도구로의 확장
연결은 간단하고 안정적으로 동작했지만, 초기 API는 Delta Chat 같은 숙련된 Rust 팀이 아닌 일반 P2P 앱 개발자가 쓰기에는 기능이 부족했음
블롭 API에 BLAKE3 검증 스트리밍 기능을 더 많이 노출하고, BLAKE3 청크 그룹 같은 고급 기능으로 성능도 최적화함
앱 고유 코드만 추가하면 되는 통합 개발 프레임워크를 목표로 문서 추상화 도 도입함
더 많은 개발자가 접근하도록 대부분의 주요 언어에 바인딩 을 제공함
실제로 자주 사용됐지만, 1.0까지 API가 빈번하게 바뀌어 유지보수 부담이 컸음
ALPN으로 프로토콜 협상 단순화
프로토콜이 늘면서 협상이 필요해졌지만, 각 스트림마다 작은 핸드셰이크 프로토콜 을 넣으면 스트림별 오버헤드 가 생기고 순수한 P2P QUIC에서 멀어짐
복잡한 하위 호환성 체계는 테스트해야 할 프로토콜 변형의 조합을 폭발적으로 늘리므로, TLS ALPN 확장 을 사용하는 단순한 방식을 선택함
연결 측이 ALPN 목록을 제안하고 서버 측이 하나를 선택하거나 핸드셰이크를 거절함
QUIC 핸드셰이크 중 처리되므로 ALPN 문자열 바이트 외의 추가 오버헤드가 없음
가공하지 않은 QUIC 스트림을 제공하므로, Media over QUIC 처럼 스트림을 독창적으로 활용하는 방식 도 그대로 지원할 수 있음
다만 ALPN을 담은 ClientHello
는 암호화되지 않아 , 경로상의 관찰자가 사용 프로토콜을 알아낼 수 있음
QUIC 연결 하나는 정확히 하나의 ALPN에 대응하므로, 같은 두 엔드포인트가 여러 프로토콜을 사용하면 연결도 여러 개 열림
연결 사이에 일부 내부 상태를 공유해 홀 펀칭 등을 처음부터 반복하지 않도록 함
sendme와 dumbpipe로 확인한 활용성
공개 키만으로 연결하기 위한 주소 조회
오랫동안 연결에는 엔드포인트 ID뿐 아니라 IP 주소 또는 릴레이 URL 도 필요했으며, sendme는 지금도 이 방식을 사용함
추가 주소 정보는 안정적이지 않음
ISP가 공인 IP를 바꾸거나 기기가 다른 지역으로 이동해 기본 릴레이가 바뀔 수 있음
피어가 많은 대규모 시스템에서는 연결 티켓을 다루는 것도 번거로움
자체 분산 해시 테이블(DHT) 을 구현하고 보급할 자원이 부족하다고 판단해, Cloudflare Workers 같은 중앙화된 선택지도 검토함
이후 발견한 Pkarr 는 서명된 DNS 레코드를 BitTorrent Mainline DHT 에 저장하는 방식임
Mainline에는 당분간 해소되기 어려운 제약이 있어, iroh의 0-RTT 연결 을 활용하는 별도 DHT 실험 도 진행함
현재는 연결의 한계를 시험하는 실험일 뿐 프로덕션 도구가 아님
다시 연결만 남기고 안정화하기
통합 도구로 확장하면서 API가 크게 늘었고, 모든 영역에 동일한 품질을 보장하기 어려워짐. 사용자마다 사용하는 API 부분도 달랐음
모두가 공통으로 필요로 한 기능은 엔드포인트 ID 기반 연결과 신뢰할 수 있는 홀 펀칭 이었으므로, iroh의 범위를 직접 연결로 축소 함
이미 중요한 프로젝트들이 iroh에 의존하는 상황에서 개발 자유도도 확보하려고, 첫 장기 안정 버전 0.35 와 최신 변경을 따르는 canary 계열 을 운영함
별도 기능 브랜치 대신 main에서 개발을 계속하고 사용자도 변경을 따라올 수 있게 함
0.35는 지금도 여러 프로젝트가 의존하는 안정적인 버전이며, 개발팀이 돌아보기에는 이를 1.0으로 불러도 무방했을 수준임
역할에 맞게 이름 정리하기
엔드포인트 식별자는 과거 NodeId
로 불렸음. 여러 프로토콜을 내장한 큰 바이너리였던 당시에는 적합한 이름이었음
기존 Discovery
는 이미 알고 있는 엔드포인트 ID의 릴레이 주소나 IP 주소를 찾는 동작에 맞춰 주소 조회로 정리함
새 엔드포인트 ID를 발견하는 것이 아니라 기존 ID에 관한 추가 데이터를 조회하는 작업임
mDNS처럼 실제로 새 엔드포인트를 발견하는 제공자도 있지만, 그 기능은 AddressLookup 트레이트 의 범위에 포함되지 않음
멀티패스 재설계와 quinn 포크
하위 전송 경로를 끊김 없이 전환하려면 일부 임시방편적인 처리 가 필요했고, 기존 구조는 장기적으로 제약이 될 수 있었음
이미 여러 경로를 사용하고 있었지만 QUIC 자체는 이를 알지 못하는 점 이 여러 문제의 근본 원인이었으므로, 멀티패스 중심으로 내부 구조를 재설계 함
quinn에 멀티패스 지원 을 추가하면서 처음에는 변경을 원본 프로젝트에 반영하려 했으나, 차이가 커져 가능성이 낮아짐
1.0에 포함하지 않은 기능
키 알고리듬 선택 기능 은 자주 요청됐지만 도입하지 않음
Pkarr 주소 조회를 비롯한 현재 시스템 상당수가 Ed25519 키에만 대응함
secp256k1이나 P-256 지원은 기술적으로 어렵지 않더라도 전체 복잡성을 높임
TLS 핸드셰이크의 키 인코딩 은 이미 특정 키 알고리듬에 종속되지 않아, 향후 통신 형식을 깨뜨리지 않고 추가할 가능성이 있음
양자내성 서명 도 포함하지 않음. 현재 표준화된 알고리듬은 공개 키가 너무 커서, 크기를 관리하려면 엔드포인트 ID를 공개 키 자체가 아닌 공개 키에서 파생한 값으로 바꿔야 함
최근 표준화된 Encrypted ClientHello 또는 유사한 방식으로 ALPN 등 핸드셰이크 메타데이터를 숨기는 기능은 향후 도입을 검토할 수 있음
1.0이 확정하는 범위
4년간 LLM 도움 없이 많은 코드를 작성하고 그에 못지않은 양을 버린 결과, 기존 표준에 크게 의존하는 최소한의 라이브러리가 남음
최종 기능은 공개 키만으로 상대를 지정하는 인증되고 암호화된 직접 연결 임
1.0은 통신 형식과 API가 안정적이라는 뜻 이며, 내부 개선이 끝났다는 뜻은 아님
통신 형식과 API 양쪽에 확장 지점이 있고, 내부 구현 개선은 계속됨
댓글과 토론
AI 자동 생성 콘텐츠
본 콘텐츠는 RSS: GeekNews (한국어)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기