noq · WASM/브라우저 지원 · 포스트양자 키교환)한 문장으로 이 프로젝트가 뭘 하는지부터.
iroh = "공개키로 다이얼하는 P2P QUIC 연결 라이브러리." 보통 네트워크 프로그램은 상대의 IP 주소:포트를 알아야 연결한다. 그런데 휴대폰·노트북은 와이파이를 옮기고 NAT 뒤에 숨고 IP가 수시로 바뀐다 — 주소는 끊임없이 변한다. iroh는 발상을 뒤집는다. 변하지 않는 것, 즉 그 기기의 공개키(=신원)로 연결을 건다. "저 폰에 연결해 줘"라고 공개키만 건네면, iroh가 알아서 상대의 현재 주소를 찾고, NAT를 뚫고, 가장 빠른 경로로 암호화된 QUIC 연결을 만들어 유지한다.
전화번호(IP 주소)는 통신사·지역·기기를 바꾸면 달라진다. 번호로만 연결하는 세상에선, 상대가 이사할 때마다 새 번호를 알아내야 한다. NAT·방화벽은 "이 번호는 외부에서 못 건다"는 사설 교환대까지 끼워 일을 더 어렵게 만든다.
iroh는 번호가 아니라 "이름(공개키)"으로 거는 전화다. 이름은 절대 안 바뀐다. 상대가 어디로 이사하든, "그 이름에게 연결해 줘"라고만 하면 iroh의 안내 시스템(릴레이 + 디스커버리)이 지금 어디 있는지 찾아 연결해 준다. 게다가 이름 자체가 암호키라서, 연결이 곧 상대 본인임을 증명한다 — 잘못 걸 수가 없다.
정리하면 iroh의 핵심 약속은 세 가지다. ① 주소가 아니라 공개키로 연결한다(EndpointId). ② 처음엔 릴레이로 무조건 잇고, 가능해지면 홀펀칭으로 직접 연결로 갈아탄 뒤 릴레이를 뺀다. ③ 모든 연결은 QUIC + TLS로 암호화되며, 공개키가 곧 신원이라 중간자 공격이 원천 차단된다. 이 위에 파일 전송(iroh-blobs), 펍섭(iroh-gossip), 동기화 DB(iroh-docs) 같은 프로토콜을 얹어 "로컬 퍼스트(local-first)" 앱을 만든다.
TrendShift 일간 24위 — "공개키로 다이얼"이라는 단순한 약속과, 1.0 도달이 핵심.
분산·로컬 퍼스트 앱이 늘면서 "중앙 서버 없이 두 기기를 직접 잇는 일"의 수요가 커졌다. 하지만 NAT 통과·디스커버리·암호화·릴레이를 직접 구현하는 건 악명 높게 어렵다. iroh는 그 모든 걸 한 줄짜리 API 뒤로 숨겨 준다. 최근 주목도가 오른 이유를 다섯 가지로 본다:
iroh의 모든 매력은 한 문장에서 나온다. connect(EndpointId, ALPN) — 상대의 32바이트 공개키와 프로토콜 이름만 주면 끝이다. IP·포트·NAT·릴레이는 라이브러리가 알아서 처리한다. "어디에 있는가"가 아니라 "누구인가"로 연결을 거는 이 모델은, 기기가 이동해도 연결 식별자가 안 변한다는 결정적 장점을 준다.
noq로 갈아탔다iroh는 오랫동안 Rust의 대표 QUIC 구현인 quinn 위에서 돌았는데, 1.0에 오며 자체 QUIC 엔진 noq(n0가 직접 개발)로 교체했다. 멀티패스(여러 경로 동시 사용)·커스텀 전송·홀펀칭 같은 iroh 특유의 요구를 QUIC 계층에서 직접 제어하려는 결정이다. 인증 암호화, 스트림 우선순위, 데이터그램 전송을 기본 제공한다.
iroh의 릴레이 프로토콜과 NAT 탐지는 Tailscale의 검증된 설계(DERP 릴레이, netcheck)에서 갈라져 나왔다(코드 주석에 출처 명시). 거기에 STUN 대신 QAD(QUIC Address Discovery)라는 최신 방식으로 자기 주소를 알아낸다. "그 회사가 수년간 프로덕션에서 검증한 NAT 통과 노하우"를 오픈소스 라이브러리로 쓸 수 있다는 점이 크다.
이번에 v1.0.0에 도달하며 공개 API가 안정화됐다(외부 노출 타입을 cargo_check_external_types로 엄격히 관리). 게다가 wasm32 타깃을 1급으로 지원해 브라우저 안에서도 iroh 연결이 가능하고, 포스트양자 키교환 예제(pq-only-key-exchange)까지 들어 있다. "지금 쓸 수 있고, 미래도 대비했다"는 신호.
iroh는 연결만 주고 끝이 아니다. 그 위에 얹는 iroh-blobs(BLAKE3 콘텐츠 주소 파일전송), iroh-gossip(펍섭 오버레이), iroh-docs(동기화 KV 저장소)가 함께 큰다. 게다가 n0가 전 세계 4곳에 공용 릴레이(북미 동/서·EU·아태)와 디스커버리 서버(dns.iroh.link)를 무료로 운영해, 별도 인프라 없이 바로 시작할 수 있다.
| 접근 방식 | 두 기기를 어떻게 잇나 | iroh와의 차이 |
|---|---|---|
| 직접 소켓(TCP/UDP) | 상대 IP:포트를 알아야 직접 연결 | NAT 뒤 기기엔 직접 못 닿음. iroh는 릴레이+홀펀칭으로 NAT를 뚫는다. |
| 중앙 서버 경유 | 모든 트래픽이 회사 서버를 통과 | 느리고 비싸고 사생활 노출. iroh는 직접 연결로 갈아타고 릴레이는 암호문만 중계. |
| WebRTC | 브라우저 P2P(STUN/TURN/ICE) | 브라우저 중심·시그널링이 복잡. iroh는 QUIC 기반·공개키 신원에 네이티브+WASM 모두. |
| iroh | 공개키로 다이얼 → 릴레이 → 홀펀칭 직접연결 | 주소가 아닌 신원으로 연결, 암호화 내장, 한 줄 API, 무료 공용 릴레이. |
NAT 통과·디스커버리·암호화·릴레이라는 네 가지 난제를 Endpoint::bind + connect 뒤로 숨겼다. 처음엔 릴레이로 안정적으로 잇고, 가능해지는 즉시 직접 연결로 승격해 릴레이를 빼므로 빠르면서도 끊김이 없다. 신원이 곧 암호키라 보안도 공짜로 따라온다.
iroh는 Rust 라이브러리다(다른 언어는 iroh-ffi 바인딩 필요). 1.0에서 핵심 용어가 대거 바뀌어(Node→Endpoint, NodeId→EndpointId) 옛 블로그·README 예제는 그대로 안 돌아갈 수 있다 — 반드시 1.0 기준 문서를 봐야 한다. 또 디스커버리·릴레이를 n0 공용 서버에 의존하면 가용성이 그쪽에 묶이고, 완전 자립하려면 릴레이·DNS 서버를 직접 운영해야 한다(가능은 하다). 마지막으로, 모든 NAT가 홀펀칭에 뚫리는 건 아니라 일부는 계속 릴레이를 거친다.
루트 Cargo.toml workspace · 각 crate의 Cargo.toml · 실제 소스 트리에서 확인한 구성.
마음의 준비부터. iroh는 "백엔드+프론트엔드" 웹 스택이 아니라 네트워킹 라이브러리 스택이다. 전부 Rust(edition 2024, MSRV 1.91)이고, 여러 crate를 묶은 workspace(모노레포)로 되어 있다. 계층은 크게 ⓐ 핵심 라이브러리, ⓑ QUIC·암호, ⓒ 디스커버리, ⓓ NAT 통과, ⓔ 런타임·생태계로 나뉜다.
| crate | 무엇 | 역할 |
|---|---|---|
| iroh | 핵심 라이브러리 ("p2p quic connections dialed by public key") | Endpoint·연결관리·홀펀칭·net_report·디스커버리·TLS. 가장 큰 덩어리. |
| iroh-base | 공용 기본 타입 | EndpointId·PublicKey/SecretKey·EndpointAddr·RelayUrl 같은 순수 타입. |
| iroh-relay | 릴레이 클라이언트 + 서버 | n0가 프로덕션에서 돌리는 바로 그 릴레이 구현. 직접 띄울 수도 있다. |
| iroh-dns | DNS 기반 디스커버리 클라이언트 | EndpointId를 DNS(pkarr)로 조회. hickory-resolver 사용. |
| iroh-dns-server | pkarr 릴레이 + DNS 서버 | dns.iroh.link에서 도는 서버. axum·redb·mainline(BitTorrent DHT). |
| 구성요소 | 무엇 | 역할 |
|---|---|---|
| noq / noq-proto / noq-udp | n0 자체 QUIC 구현 | endpoint 간 QUIC 연결을 수립. quinn을 대체. 멀티패스·데이터그램 지원. |
| ed25519-dalek / curve25519-dalek | 타원곡선 서명·키교환 | 각 endpoint의 SecretKey/PublicKey. 공개키가 곧 EndpointId. |
| rustls + ring / aws-lc-rs | Rust TLS + 암호 백엔드 | QUIC의 TLS. tls-ring(기본) 또는 tls-aws-lc-rs(포스트양자용) 선택. |
| raw public key TLS | 인증서 없는 TLS (RFC 7250류) | CA 인증서 체인 대신 endpoint 키쌍으로 서로를 인증. iroh/src/tls.rs. |
| 구성요소 | 무엇 | 역할 |
|---|---|---|
| Pkarr | Public Key Addressable Resource Records | 공개키로 서명한 DNS 레코드를 발행/조회. "내 EndpointId는 이 릴레이에 있다"를 공표. |
| DNS (hickory) | 표준 DNS 조회/서버 | DnsAddressLookup가 dns.iroh.link에서 endpoint 주소를 조회. DNS-over-HTTPS 지원. |
| mainline DHT | BitTorrent 메인라인 DHT | 중앙 서버 없는 분산 조회 경로(별도 crate). pkarr 레코드를 DHT에도 보관. |
| redb / governor | 임베디드 DB · 레이트리밋 | dns-server가 pkarr 패킷을 저장하고 남용을 막는 부품. |
iroh의 마법 대부분이 여기 있다. net_report(iroh/src/net_report.rs)는 "내가 IPv4/IPv6로 인터넷에 닿는지, NAT 상황은 어떤지, 릴레이까지 지연은 얼마인지"를 점검한다 — Tailscale의 netcheck에서 갈라져 나왔고, 자기 공인주소 파악에 STUN 대신 QAD(QUIC Address Discovery)를 쓴다. portmapper는 공유기에 UPnP·PCP·NAT-PMP로 포트 매핑을 요청해 직접 연결 가능성을 높인다. magic socket(socket.rs)은 직접IP·릴레이·커스텀 전송을 한데 묶고 RTT가 가장 낮은 경로를 골라 보낸다(biased_rtt_path_selector).
비동기 런타임은 tokio다. n0가 함께 만드는 보조 crate들 — n0-future(future 유틸), n0-watcher(값 변화를 구독하는 Watcher), n0-error(스택트레이스 친화 에러), netwatch(네트워크 변화 감지) — 가 곳곳에 쓰인다. WASM 타깃에선 ws_stream_wasm·wasm-bindgen-futures 등으로 브라우저 환경을 지원한다. 그리고 응용 계층에 iroh-blobs / iroh-gossip / iroh-docs를 얹어 실제 앱을 만든다(아래 §4·§6에서 상술).
먼저 전체 그림을 한 장으로 본 뒤, 대표 흐름 '공개키로 연결이 맺히는 과정'을 끝까지 따라간다.
iroh의 일은 "두 endpoint 사이에 가장 빠른 암호화 QUIC 경로를 만들고 유지하는 것"이다. 큰 그림은 이렇다. (1) 각 endpoint는 시작할 때 가장 가까운 릴레이를 home relay로 잡는다. (2) A가 B에 연결하려 하면 먼저 B의 home relay를 거쳐 잇는다. (3) 그 사이 양쪽은 서로의 주소를 교환하고 홀펀칭으로 직접 경로를 시도한다. (4) 직접 경로가 뚫리면 릴레이를 빼고 직접 연결만 쓴다. 부품 이름을 외우기 전에 숲부터 보자.
PublicKey 그 자체(32바이트 Ed25519). 신원이자 주소록 키이자 암호 검증 대상이다. ALPN(Application-Layer Protocol Negotiation)은 "이 연결에서 무슨 프로토콜로 말할지" 정하는 이름표(예: b"iroh-example/echo/0"). 연결하려면 ①상대 EndpointId ②주소 힌트(보통 RelayUrl) ③ALPN, 이 셋이 필요하다.endpoint.connect(addr, ALPN) 한 줄 뒤에서 벌어지는 일을 순서대로 풀면:
// A가 B의 EndpointId(공개키)만 들고 connect 했을 때
1. 주소 찾기 AddressLookup(Pkarr/DNS)로 "EndpointId_b 의 RelayUrl" 조회
2. 릴레이 경유 B의 home relay 에 접속 → 암호문을 EndpointId 로 라우팅
3. 경로 탐색 net_report 가 내 NAT/주소 파악(QAD), 양쪽이 후보 주소 교환
4. 홀펀칭 양쪽이 동시에 패킷을 쏘아 NAT 에 구멍 → 직접 경로 시도
5. 승격 직접 QUIC(noq) 연결 성공 → magic socket 이 릴레이→직접 전환
6. 암호화 raw-public-key TLS 로 "정말 EndpointId_b 인지" 검증 완료
핵심 관례 하나 — 릴레이와 직접 주소를 동시에 쓸 수 있다. 처음엔 릴레이로 0초 지연 없이 잇고, 직접 경로가 준비되면 자연스럽게 갈아탄다. 사용자 코드는 이 전환을 신경 쓸 필요가 없다. 또 하나, 상대가 이미 직접 닿을 수 있으면 릴레이 없이도 연결되고, 반대로 홀펀칭이 끝내 안 되면 계속 릴레이를 통해 (느리지만) 끊김 없이 통신한다.
받는 쪽은 "ALPN마다 다른 처리기"를 등록한다. Router가 들어오는 연결의 ALPN을 보고 알맞은 ProtocolHandler로 보낸다 — 한 endpoint가 여러 프로토콜을 동시에 서빙할 수 있다.
// 받는 쪽: ALPN "iroh-example/echo/0" 에 Echo 처리기 등록
let endpoint = Endpoint::bind(presets::N0).await?;
let router = Router::builder(endpoint)
.accept(ALPN, Echo) // ALPN → 처리기 매핑
.spawn();
// 보내는 쪽: 같은 ALPN 으로 다이얼 후 양방향 스트림
let conn = endpoint.connect(addr, ALPN).await?;
let (mut send, mut recv) = conn.open_bi().await?;
send.write_all(b"Hello, world!").await?;
send.finish()?; // 이 스트림은 더 안 보냄
let echo = recv.read_to_end(1000).await?;
QUIC 스트림은 비용을 아끼려고 게으르게(lazy) 생성된다. conn.open_bi()를 불러도, 실제로 데이터를 한 번 보내기 전까지 상대의 accept_bi()는 반환되지 않는다. "연결은 됐는데 상대가 스트림을 못 받는다"면 십중팔구 이 함정이다 — 여는 쪽이 write_all로 첫 바이트를 흘려보내야 받는 쪽이 깨어난다.
이 레포에서 배울 핵심 설계 패턴 둘. 첫째, magic socket(socket.rs, 108KB) — 직접IP·릴레이·커스텀을 하나의 소켓처럼 추상화하고 경로별 RTT·상태를 추적해 최적 경로로 자동 전환한다. 둘째, 릴레이는 "암호문 우체부" — 릴레이는 EndpointId만 보고 패킷을 전달할 뿐, 내용은 양쪽 키로만 풀리므로 릴레이 운영자도 트래픽을 못 읽는다. "중앙 서버를 쓰되 신뢰는 최소화"하는 모범 설계다.
workspace 멤버 crate들과, 간판 crate iroh/src/의 내부. 큰 덩어리만 본다.
루트는 여러 crate를 묶은 workspace다. 복잡성의 대부분은 iroh/src/ 안 두 거대 파일 — endpoint.rs(158KB)와 socket.rs(108KB) — 에 모여 있다. 전자는 공개 API(Endpoint·Connection), 후자는 그 마법을 떠받치는 멀티패스 소켓이다.
| 위치 | 한 줄 역할 |
|---|---|
| iroh/src/lib.rs | 시스템 전체를 설명하는 최상위 문서 주석. iroh를 이해하려면 가장 먼저 읽을 한 장. |
| iroh/examples/echo.rs | 두 endpoint를 잇는 최소 완전 예제. 여기서 시작. |
| iroh/src/endpoint.rs | 공개 API의 본체 — Endpoint·Builder·Connection·open_bi/accept_bi. |
| iroh/src/socket.rs | magic socket. 직접/릴레이/커스텀 경로 멀티플렉싱 + RTT 기반 경로 선택. |
| iroh/src/net_report.rs | NAT·도달성 진단. STUN 대신 QAD. Tailscale netcheck에서 파생. |
| iroh/src/address_lookup.rs | 디스커버리(옛 discovery). Pkarr 발행·DNS 조회·메모리 등록. |
| iroh-relay/ | 릴레이 클라이언트와 서버. n0 프로덕션과 같은 코드 — 직접 운영 가능. |
| iroh-dns-server/ | pkarr 릴레이 + DNS 서버. 공개키 서명 레코드를 DNS로 서빙. |
이 레포 한 채로 배울 수 있는 네트워킹 기술과, 각각의 실습 아이디어.
iroh는 "현대 P2P 네트워킹에서 어려운 것"이 골고루 한 코드베이스에 모여 있어 공부 소재로 훌륭하다. 기술별로 무엇을 건질지 짚는다.
iroh의 모든 연결은 QUIC(자체 엔진 noq)이다. 한 연결 안에 양방향/단방향 스트림과 데이터그램을 깔 수 있고, 스트림끼리 head-of-line blocking이 없다. examples/0rtt.rs로 0-RTT 재연결도 볼 수 있다. "TCP+TLS와 무엇이 다른가"를 코드로 체감하기 좋다.
실습: open_bi(양방향)와 open_uni(단방향), 그리고 데이터그램(listen-unreliable.rs)을 각각 써 보고 차이를 정리.
net_report가 NAT 종류와 공인주소를 파악하고(STUN 대신 QAD), portmapper가 UPnP/PCP로 포트를 열고, 릴레이가 양쪽 타이밍을 맞춰 홀펀칭을 돕는다. 네트워크 엔지니어링의 정수가 한 곳에 있다.
실습: RUST_LOG를 켜고 echo 예제를 다른 네트워크의 두 기기에서 돌려, "릴레이 경유 → 직접 연결 승격" 로그가 찍히는 순간을 관찰.
iroh는 CA 인증서 체인이 없다. 각 endpoint의 SecretKey로 TLS를 수행하고, 연결 상대가 정확히 그 EndpointId(공개키)인지 검증한다(src/tls.rs). "신원 = 암호키"라는 모델이 어떻게 중간자 공격을 원천 차단하는지 배운다.
실습: SecretKey를 생성·저장해 재시작해도 같은 EndpointId를 갖게 만들기. 잘못된 EndpointId로 connect하면 어떻게 거부되는지 확인.
iroh-relay는 Tailscale의 DERP를 개정한 프로토콜이다(protos/relay.rs). Ping/Pong, Datagram 프레임, 클라이언트 큐, Happy Eyeballs(IPv4/IPv6 경주), WebSocket 업그레이드, ACME TLS까지 — 프로덕션급 중계 서버를 통째로 읽을 수 있다.
실습: iroh-relay 바이너리를 로컬에 띄우고 RelayMode::Custom으로 내 릴레이만 쓰게 설정해 두 프로세스를 연결.
각 endpoint는 자기 주소를 Pkarr(공개키 서명 DNS 레코드)로 발행하고, 상대는 DNS나 DHT로 조회한다. 중앙 주소록 없이 "이름으로 사람 찾기"를 구현하는 실전 예다(iroh-dns·iroh-dns-server).
실습: PkarrPublisher::n0_dns() + DnsAddressLookup::n0_dns()만으로(직접 주소 없이) 두 기기를 연결해 보고, 발행된 DNS 레코드를 조회로 확인.
Router가 ALPN별로 ProtocolHandler를 라우팅한다. 직접 짜는 대신 iroh-blobs(파일전송)·iroh-gossip(펍섭)·iroh-docs(동기화 KV)를 얹으면 곧장 실전 앱이 된다. "전송 계층 위에 앱 프로토콜을 어떻게 구조화하나"의 모범.
실습: 나만의 ALPN으로 간단한 요청-응답 프로토콜(예: 핑퐁/채팅)을 ProtocolHandler로 구현해 Router에 등록.
GPU·고사양 불필요. "Rust 툴체인"과 "약간의 네트워크 권한"이면 충분하다.
iroh는 가벼운 라이브러리다 — gossip 같은 프로토콜도 "평범한 휴대폰이 감당할 자원"으로 돈다고 README가 명시한다. 추론 모델이 아니라 네트워킹 코드라 GPU는 전혀 필요 없다. 대신 최신 Rust 툴체인과, 직접 연결을 위한 UDP 통신 권한이 중요하다.
| 항목 | 요구사항 |
|---|---|
| Rust 툴체인 | rustc 1.91 이상(MSRV), edition 2024. cargo add iroh로 의존성 추가. |
| 비동기 런타임 | tokio 기반. #[tokio::main] 환경에서 동작. |
| 네트워크 | UDP 송수신 가능해야 함(홀펀칭). 막히면 자동으로 릴레이 폴백. 기본 릴레이 QUIC 포트 7842. |
| 공용 인프라(선택) | n0가 운영하는 릴레이 4곳(NA 동/서·EU·아태)과 dns.iroh.link가 기본값. 무료, 별도 설정 불필요. |
| 자립 운영(선택) | 완전 자체 운영 시 iroh-relay·iroh-dns-server를 직접 띄움(도커 자산 제공). |
| 브라우저(WASM) | wasm32-unknown-unknown 타깃 지원. 브라우저에선 릴레이 경유(WebSocket) 중심. |
| 포스트양자(선택) | PQ 키교환 예제는 tls-aws-lc-rs 백엔드 필요(ring 기본에선 미지원). |
| GPU | 불필요. |
가장 빠른 출발점은 레포를 클론해 cargo run --example echo를 돌리는 것이다. 한 프로세스 안에서 두 endpoint가 서로 echo를 주고받으므로, 외부 네트워크 설정 없이도 iroh의 연결·스트림·Router 흐름을 즉시 눈으로 확인할 수 있다.
"echo 돌리기"는 5분, "직접 프로토콜·릴레이"는 한나절. 난이도 순으로.
레포를 클론해 cargo run --example echo를 돌린다. 한 프로세스 안에서 두 endpoint가 연결·스트림·Router를 거쳐 "Hello, world!"를 echo한다. RUST_LOG=iroh=debug를 붙여 어떤 단계가 찍히는지 관찰한다.
받는 쪽 프로그램이 endpoint.id()(EndpointId)와 endpoint.addr()를 콘솔에 찍게 하고, 보내는 쪽은 그 값을 인자로 받아 connect한다. examples/listen.rs·connect.rs가 그대로 본보기다.
IP·포트를 전혀 주지 않고 EndpointId만으로 연결해 본다. 받는 쪽은 PkarrPublisher::n0_dns()로 주소를 발행하고, 보내는 쪽은 DnsAddressLookup::n0_dns()로 조회한다. 진짜 "이름으로 전화 걸기"를 구현하는 단계.
ProtocolHandler를 구현해 간단한 요청-응답(예: 시간 묻기, 핑퐁, 한 줄 채팅) 프로토콜을 만든다. 고유 ALPN을 붙여 Router::builder(endpoint).accept(MY_ALPN, handler).spawn()으로 등록하고, 같은 ALPN으로 다이얼한다.
iroh-relay 바이너리를 로컬/서버에 띄우고, 클라이언트는 RelayMode::Custom(RelayMap)으로 n0 공용 릴레이 대신 내 릴레이만 쓰게 설정한다. 두 프로세스를 그 릴레이로 연결해 본다.
전송 계층 위에 생태계 프로토콜을 얹는다. iroh-blobs로 두 기기 간 파일을 콘텐츠 주소(BLAKE3)로 전송하거나, iroh-gossip으로 여러 노드가 메시지를 펍섭하는 작은 채팅방을 만든다.
iroh를 100% 소화하기 위한 6주 코스(주당 5~7시간 가정).
| 주차 | 주제 | 학습 자료 / 할 일 |
|---|---|---|
| 1주차 | P2P·NAT·QUIC 기초 | NAT/홀펀칭 개념 + QUIC가 TCP+TLS와 뭐가 다른지 정리. iroh/src/lib.rs 정독. 실습 1. |
| 2주차 | iroh 기본 API | Endpoint·Connection·open_bi/accept_bi·게으른 스트림 함정. 실습 2. |
| 3주차 | 디스커버리(Pkarr·DNS) | "공개키 → 주소" 원리, address_lookup 읽기. 직접주소 없이 연결. 실습 3. |
| 4주차 | 프로토콜 설계(Router·ALPN) | protocol.rs + 예제. 나만의 ALPN 프로토콜 구현. 실습 4. |
| 5주차 | 릴레이·홀펀칭 내부 | net_report(QAD)·iroh-relay(DERP)·magic socket 읽기. 내 릴레이 운영. 실습 5. |
| 6주차 | 생태계 + WASM | iroh-blobs/gossip/docs로 앱 만들기, 브라우저(WASM) 빌드 맛보기. 실습 6. |
이 문서와 레포에 등장한 용어를 한자리에.
| 용어 | 의미 |
|---|---|
| P2P | 중앙 서버 없이 두 기기가 직접 통신하는 방식. iroh가 풀어 주는 핵심 문제. |
| QUIC | UDP 위의 차세대 전송 프로토콜. 신뢰성+TLS 암호화+다중 스트림 내장. HTTP/3의 바탕. |
| noq | n0가 자체 개발한 QUIC 구현. iroh 1.0에서 quinn을 대체. 멀티패스·데이터그램 지원. |
| EndpointId | endpoint의 공개키(32바이트 Ed25519) 그 자체. 신원·주소록 키·암호 검증 대상. |
| Endpoint | iroh의 연결 단위(옛 Node). connect·bind·id·addr를 제공. |
| ALPN | Application-Layer Protocol Negotiation. 연결에서 쓸 프로토콜 이름표. Router 라우팅 키. |
| 홀펀칭 / NAT | NAT(공유기)에 임시 구멍을 내 직접 연결을 트는 기술. iroh가 릴레이 도움으로 수행. |
| 릴레이(relay) | NAT를 못 뚫을 때 암호문을 중계하는 서버. EndpointId로만 라우팅, 내용은 못 읽음. |
| DERP | Tailscale의 릴레이 프로토콜(Designated Encrypted Relay for Packets). iroh 릴레이의 계보. |
| home relay | endpoint가 시작 시 잡는 "가장 가까운 릴레이". 다른 endpoint가 나에게 닿는 첫 통로. |
| Pkarr | Public Key Addressable Resource Records. 공개키로 서명한 DNS 레코드로 주소를 발행/조회. |
| 디스커버리(AddressLookup) | "공개키 → 현재 주소"를 찾는 시스템. DNS·Pkarr·mDNS·DHT 경로 제공. |
| QAD | QUIC Address Discovery. STUN을 대체해 자기 공인주소를 알아내는 최신 방식. |
| net_report | NAT 종류·IPv4/6 도달성·릴레이 지연을 진단하는 모듈. Tailscale netcheck 계보. |
| magic socket | 직접IP·릴레이·커스텀 경로를 하나로 묶고 RTT 최저 경로를 자동 선택하는 소켓 추상화. |
| raw public key TLS | CA 인증서 없이 endpoint 키쌍으로 서로를 인증하는 TLS(RFC 7250류). |
| Router / ProtocolHandler | 들어오는 연결을 ALPN별 처리기로 라우팅하는 구조. 한 endpoint에 여러 프로토콜. |
| RelayMode / RelayMap | 릴레이 사용 방식 설정. Default(n0 공용)·Custom(내 릴레이)·Disable. |
| portmapper | 공유기에 UPnP/PCP/NAT-PMP로 포트 매핑을 요청해 직접 연결 가능성을 높이는 모듈. |
| iroh-blobs / gossip / docs | iroh 위에 얹는 프로토콜: 파일전송(BLAKE3)·펍섭 오버레이·동기화 KV 저장소. |
| n0 (number 0) | iroh를 만든 팀/회사. 공용 릴레이·DNS 인프라도 운영. |
원문·문서·관련 기술 더 파기.