WebTransport

W3C 작업 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-webtransport-20250702/
최신 공개 버전:
https://www.w3.org/TR/webtransport/
편집자 초안:
https://w3c.github.io/webtransport/
히스토리:
https://www.w3.org/standards/history/webtransport/
피드백:
public-webtransport@w3.org 제목에 “[webtransport] … 메시지 주제 …” 포함 (아카이브)
GitHub
명세 내 인라인
편집자:
Nidhi Jaju (Google)
Victor Vasiliev (Google)
Jan-Ivar Bruaroey (Mozilla)
이전 편집자:
Bernard Aboba (Microsoft Corporation)
Peter Thatcher (Google)
Robin Raymond (Optical Tone Ltd.)
Yutaka Hirano (Google)

요약

이 문서는 브라우저와 서버 간에 데이터를 보내고 받을 수 있도록 [WEB-TRANSPORT-HTTP3][WEB-TRANSPORT-HTTP2]를 활용하여 WebIDL에서 ECMAScript API 집합을 정의합니다. 이 명세는 IETF WEBTRANS 작업 그룹에서 개발된 프로토콜 명세와 함께 개발되고 있습니다.

이 문서의 상태

이 섹션은 문서가 발행된 시점의 상태를 설명합니다. 최신 W3C 출판물과 이 기술 보고서의 최신 개정본 목록은 W3C 기술 보고서 색인에서 확인할 수 있습니다.

이 문서는 WebTransport 작업 그룹에서 권고안 경로를 따라 작업 초안으로 공개되었습니다. 이 문서는 W3C 권고안이 될 예정입니다.

이 문서에 대한 피드백 및 의견을 환영합니다. 문서의 이슈를 등록해 주세요 또는 GitHub 저장소에서 의견을 남겨주세요.

작업 초안으로 공개되었다고 해서 W3C 및 회원의 지지를 의미하지 않습니다. 이 문서는 초안 문서이며 언제든지 업데이트, 교체 또는 폐기될 수 있습니다. 이 문서를 진행 중인 작업 외의 것으로 인용하는 것은 부적절합니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 제작되었습니다. W3C는 이 그룹 결과물과 관련하여 공개된 특허 공개 목록을 유지합니다; 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허에 대해 필수 청구항이 포함되어 있다고 판단한 경우, W3C 특허 정책 6항에 따라 정보를 공개해야 합니다.

이 문서는 2023년 11월 3일 W3C 프로세스 문서에 따라 관리됩니다.

1. 소개

이 섹션은 규범적인 내용이 아닙니다.

이 명세는 [WEB-TRANSPORT-HTTP3][WEB-TRANSPORT-HTTP2]를 사용하여 서버와 데이터를 주고받습니다. WebSockets처럼 사용할 수 있지만, 여러 스트림, 단방향 스트림, 순서에 상관없는 전송, 신뢰성 있는 전송과 신뢰성이 없는 전송 모두를 지원합니다.

참고: 이 명세에서 제공하는 API는 IETF WEBTRANS WG에서 진행 중인 작업을 바탕으로 한 예비 제안입니다. [WEB-TRANSPORT-HTTP3][WEB-TRANSPORT-HTTP2] 명세가 진행 중이므로 프로토콜과 API 모두 앞으로 상당히 변경될 수 있습니다.

2. 준수

비규범적으로 표시된 섹션뿐만 아니라, 이 명세의 모든 작성 지침, 도표, 예시, 참고 사항은 규범적인 내용이 아닙니다. 그 외의 모든 내용은 규범적입니다.

이 명세에서 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL"이라는 핵심 용어는 [RFC2119][RFC8174]에서 설명된 대로, 오직 대문자로 나타날 때만 해당 의미로 해석됩니다.

이 명세는 하나의 제품에 적용되는 준수 기준을 정의합니다: 이 명세에 포함된 인터페이스를 구현하는 사용자 에이전트입니다.

알고리즘이나 특정 단계로 표현된 준수 요구사항은 최종 결과가 동일하기만 하면 어떤 방식으로 구현해도 됩니다. (특히, 이 명세에서 정의된 알고리즘은 따라가기 쉽도록 설계된 것이며, 성능을 위한 것이 아닙니다.)

이 명세에서 정의된 API를 ECMAScript로 구현하는 경우, 반드시 Web IDL 명세 [WEBIDL]에 정의된 ECMAScript 바인딩과 용어에 따라 일관되게 구현해야 합니다. 이 명세는 해당 명세와 용어를 사용합니다.

3. 프로토콜 개념

WebTransport에는 두 가지 주요 프로토콜 개념이 있습니다: 세션과 스트림. 각 WebTransport 세션은 여러 개의 WebTransport 스트림을 포함할 수 있습니다.

이들은 프로토콜 이름과 혼동해서는 안 되며, 이는 애플리케이션 수준의 API 구조입니다.

3.1. WebTransport 세션

WebTransport 세션은 HTTP/3 또는 HTTP/2 하위 연결에서의 WebTransport 세션입니다. 풀링이 활성화되면 하나의 연결에 여러 WebTransport 세션이 있을 수 있습니다.

WebTransport 세션[WEB-TRANSPORT-OVERVIEW]에 정의된 다음 기능을 가집니다:

기능 정의
데이터그램 보내기 [WEB-TRANSPORT-OVERVIEW] 섹션 4.2
데이터그램 받기 [WEB-TRANSPORT-OVERVIEW] 섹션 4.2
단방향(송신) 스트림 생성 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3
양방향 스트림 생성 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3
단방향(수신) 스트림 받기 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3
양방향 스트림 받기 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3

WebTransport 세션origin originprotocols 배열로 설정하려면, [WEB-TRANSPORT-OVERVIEW] 섹션 4.1을 따르며, origin직렬화동형 인코딩해서 요청의 `Origin` 헤더로 사용합니다. 동형 인코딩된 protocols는 클라이언트가 세션에서 서버가 사용하길 원하는 프로토콜 목록(우선 순위대로)으로, [WEB-TRANSPORT-OVERVIEW] 섹션 3.1을 따릅니다. 세션을 설정할 때, 클라이언트는 어떤 인증 정보도 제공해서는 안 됩니다. 결과 하위 트랜스포트 스트림은 세션의 CONNECT 스트림이라 부릅니다.

WebTransport 세션 session드레인하려면 [WEB-TRANSPORT-OVERVIEW] 섹션 4.1을 따릅니다.

WebTransport 세션 session드레인 중일 때는, CONNECT 스트림이 서버에 의해 정상적으로 닫히도록 요청된 경우를 의미하며, [WEB-TRANSPORT-OVERVIEW] 섹션 4.1에 설명되어 있습니다.

WebTransport 세션 session을 선택적 정수 code 및 선택적 바이트 시퀀스 reason과 함께 종료하려면 [WEB-TRANSPORT-OVERVIEW] 섹션 4.1을 따릅니다.

WebTransport 세션 session이 선택적으로 정수 code바이트 시퀀스 reason과 함께 종료됨일 때는 CONNECT 스트림이 서버에 의해 닫힌 경우를 의미하며, [WEB-TRANSPORT-OVERVIEW] 섹션 4.1에 설명되어 있습니다.

3.2. WebTransport 스트림

WebTransport 스트림WebTransport 세션 내에서 신뢰성 있고 순서가 보장되는 바이트 스트림 개념으로, [WEB-TRANSPORT-OVERVIEW] 섹션 4.3에 설명되어 있습니다.

WebTransport 스트림단방향(수신), 단방향(송신) 또는 양방향 중 하나입니다.

WebTransport 스트림은 다음과 같은 기능을 가집니다:

기능 정의 단방향(수신) 단방향(송신) 양방향
바이트 전송(FIN 포함 가능) [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
바이트 수신(FIN 포함 가능) [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
STOP_SENDING 전송 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
WebTransport 스트림 리셋 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오

WebTransport 스트림은 다음과 같은 신호를 가집니다:

이벤트 정의 단방향(수신) 단방향(송신) 양방향
STOP_SENDING [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
RESET_STREAM [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
흐름 제어 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오

4. WebTransportDatagramsWritable 인터페이스

WebTransportDatagramsWritableWritableStream으로, 데이터그램 보내기를 위한 송신 스트리밍 기능을 제공합니다.

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportDatagramsWritable : WritableStream {
  attribute WebTransportSendGroup? sendGroup;
  attribute long long sendOrder;
};

4.1. 내부 슬롯

WebTransportDatagramsWritable 객체는 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[OutgoingDatagramsQueue]] 송신 데이터그램, 타임스탬프, 데이터그램이 전송 또는 폐기될 때 해결되는 프로미스의 튜플 큐입니다.
[[Transport]] WebTransport로, 이 WebTransportDatagramsWritable의 소유자입니다.
[[SendGroup]] 선택적 WebTransportSendGroup 또는 null입니다.
[[SendOrder]] 선택적 송신 순서 번호이며 기본값은 0입니다.

생성하려면, WebTransportDatagramsWritable을, WebTransport transport, sendGroup, sendOrder로 다음 절차를 수행합니다.

  1. streamnew WebTransportDatagramsWritable로 생성하며, 다음을 포함합니다:

    [[OutgoingDatagramsQueue]]

    빈 큐

    [[Transport]]

    transport

    [[SendGroup]]

    sendGroup

    [[SendOrder]]

    sendOrder

  2. writeDatagramsAlgorithmwriteDatagramstransportstream으로 실행하는 동작으로 정의합니다.

  3. Set up streamwriteAlgorithmwriteDatagramsAlgorithm으로 설정합니다.

  4. stream을 반환합니다.

4.2. 속성

sendGroup, 타입 WebTransportSendGroup, nullable

getter 단계:

  1. this[[SendGroup]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. value가 null이 아니고, value.[[Transport]]this.[[Transport]]와 다르면, InvalidStateError 예외를 throw합니다.

  2. this.[[SendGroup]]value로 설정합니다.

sendOrder, 타입 long long

getter 단계:

  1. this[[SendOrder]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. this.[[SendOrder]]value로 설정합니다.

4.3. 절차

writeDatagrams 알고리즘은 transportwritable을 매개변수로 하고, 입력으로 data를 받습니다. 다음 단계로 정의합니다:

  1. timestamp를 현재 시점을 나타내는 타임스탬프로 설정합니다.

  2. dataBufferSource 객체가 아니라면, TypeError로 거부된 프로미스를 반환합니다.

  3. datagramstransport.[[Datagrams]]로 설정합니다.

  4. datagrams.[[OutgoingMaxDatagramSize]]data의 [[ByteLength]]보다 작으면, undefined로 해결된 프로미스를 반환합니다.

  5. 새 프로미스 promise를 생성합니다.

  6. data가 나타내는 바이트를 복사하여 bytes로 설정합니다.

  7. chunkbytes, timestamp, promise의 튜플로 설정합니다.

  8. writable.[[OutgoingDatagramsQueue]]chunk를 큐에 추가합니다.

  9. writable.[[OutgoingDatagramsQueue]]의 길이가 datagrams.[[OutgoingDatagramsHighWaterMark]]보다 작으면, promise를 undefined로 resolve합니다.

  10. promise를 반환합니다.

참고: 관련 WritableStream은 해당 스트림에 대해 writeDatagrams로 반환된 모든 프로미스가 resolve된 후에만 writeDatagrams를 호출합니다. 따라서 타임스탬프와 만료 기간은 웹 개발자가 WritableStreamDefaultWriter.ready를 신경 쓸 때만 효과적으로 동작합니다.

sendDatagramsWebTransport 객체 transportWebTransportDatagramsWritable 객체 writable을 받아, 네트워크 작업을 큐에 추가하여 transport로 다음 절차를 실행합니다:

  1. queuewritable.[[OutgoingDatagramsQueue]]의 복사본으로 설정합니다.

    참고: 위 복사와 네트워크 작업 큐잉은 최적화할 수 있습니다.

  2. maxSizetransport.[[Datagrams]].[[OutgoingMaxDatagramSize]]로 설정합니다.

  3. durationtransport.[[Datagrams]].[[OutgoingDatagramsExpirationDuration]]로 설정합니다.

  4. duration이 null이면, duration구현 정의 값으로 설정합니다.

  5. 다음 단계를 병렬로 실행합니다:

    1. queue가 비어 있지 않은 동안:

      1. bytes, timestamp, promisequeue의 첫 번째 요소로 설정합니다.

      2. timestamp로부터 duration 밀리초 이상 경과했다면:

        1. queue의 첫 번째 요소를 제거합니다.

        2. 네트워크 작업을 큐에 추가하여 transportpromise를 undefined로 resolve합니다.

      3. 그렇지 않으면, 이 루프를 종료합니다.

    2. transport.[[State]]"connected"가 아니면 반환합니다.

    3. queue가 비어 있지 않은 동안:

      1. bytes, timestamp, promisequeue의 첫 번째 요소로 설정합니다.

      2. bytes 길이 ≤ maxSize이면:

        1. bytes를 즉시 네트워크에 보낼 수 없다면 이 루프를 종료합니다.

        2. 데이터그램 보내기transport.[[Session]]bytes로 실행합니다.

      3. queue의 첫 번째 요소를 제거합니다.

      4. 네트워크 작업을 큐에 추가하여 transportpromise를 undefined로 resolve합니다.

사용자 에이전트는 WebTransport 객체 중 [[State]]"connecting" 또는 "connected"인 경우, 관련 WebTransportDatagramsWritable 객체의 일부(송신 순서 규칙에 따라 결정됨)에 대해 sendDatagrams를 실행해야 하며, 알고리즘이 진행 가능할 때 최대한 빨리 실행하는 것이 바람직합니다.

송신 순서 규칙은, 일반적으로 송신은 이전에 큐에 추가된 스트림 및 데이터그램, 앞으로 큐에 추가될 스트림 및 데이터그램의 송신과 교차될 수 있지만, 송신은 동일한 [[SendGroup]] 및 더 높은 [[SendOrder]] 값을 가진, 에러나 에러 상태 또는 흐름 제어로 인해 블록되지 않은 모든 바이트가 송신될 때까지 대기해야 한다는 것입니다.

참고: 트랜스포트의 [[State]] 값이 "connecting"일 때 데이터그램 작성이 허용됩니다. 데이터그램은 [[OutgoingDatagramsQueue]]에 저장되고, "connected" 상태일 때와 동일한 방식으로 폐기될 수 있습니다. 트랜스포트의 [[State]]"connected"가 되면 큐에 있던 데이터그램 송신을 시작합니다.

5. WebTransportDatagramDuplexStream 인터페이스

WebTransportDatagramDuplexStream는 범용 이중 스트림입니다.

[Exposed=(Window,Worker), SecureContext]
interface WebTransportDatagramDuplexStream {
  WebTransportDatagramsWritable createWritable(
      optional WebTransportSendOptions options = {});
  readonly attribute ReadableStream readable;

  readonly attribute unsigned long maxDatagramSize;
  attribute unrestricted double? incomingMaxAge;
  attribute unrestricted double? outgoingMaxAge;
  attribute unrestricted double incomingHighWaterMark;
  attribute unrestricted double outgoingHighWaterMark;
};

5.1. 내부 슬롯

WebTransportDatagramDuplexStream 객체는 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[Readable]] 수신 데이터그램을 위한 ReadableStream.
[[Writables]] 순서가 있는 집합WebTransportDatagramsWritable 스트림. 처음에는 비어 있음.
[[IncomingDatagramsQueue]] 수신 데이터그램과 타임스탬프의 쌍으로 이루어진 큐.
[[IncomingDatagramsPullPromise]] pullDatagrams에 의해 설정되며, 수신 데이터그램을 기다리는 프로미스.
[[IncomingDatagramsHighWaterMark]] 수신 데이터그램의 하이 워터마크를 나타내는 unrestricted double 값.
[[IncomingDatagramsExpirationDuration]] 수신 데이터그램의 만료 기간(밀리초)을 나타내는 unrestricted double 값 또는 null.
[[OutgoingDatagramsHighWaterMark]] 송신 데이터그램의 하이 워터마크를 나타내는 unrestricted double 값.
[[OutgoingDatagramsExpirationDuration]] 송신 데이터그램의 만료 기간(밀리초)을 나타내는 unrestricted double 값 또는 null.
[[OutgoingMaxDatagramSize]] 송신 데이터그램의 최대 크기를 나타내는 정수 값.
최대 데이터그램 크기는 사용 중인 프로토콜에 따라 다릅니다. HTTP/3 [WEB-TRANSPORT-HTTP3]에서는 경로 MTU 추정치와 관련 있으며, 오버헤드를 감안해 구현 정의 값만큼 줄어듭니다. HTTP/2 [WEB-TRANSPORT-HTTP2]에서는 해당 제한이 없습니다.

데이터그램 처리에는 전체 데이터그램을 메모리에 보관하는 과정이 포함되므로, 구현에는 크기 제한이 있을 수 있습니다. 향후 프로토콜 확장으로 모든 프로토콜 변형에 대해 이러한 크기 제한을 신호할 수 있을 것입니다.

사용자 에이전트는 [[OutgoingMaxDatagramSize]] 값을 WebTransport 객체 중 [[State]]"connecting" 또는 "connected"인 경우에 업데이트할 수 있습니다.

생성하려면, WebTransportDatagramDuplexStreamreadable로 다음 절차를 수행합니다.

  1. streamnew WebTransportDatagramDuplexStream으로 생성하며, 다음을 포함합니다:

    [[Readable]]

    readable

    [[Writables]]

    비어 있는 순서가 있는 집합

    [[IncomingDatagramsQueue]]

    빈 큐

    [[IncomingDatagramsPullPromise]]

    null

    [[IncomingDatagramsHighWaterMark]]

    구현 정의 값

    [[IncomingDatagramsExpirationDuration]]

    null

    [[OutgoingDatagramsHighWaterMark]]

    구현 정의 값

    이 구현 정의 값은 전송 데이터의 적절한 처리량을 보장하면서도 시의성(timeliness)을 해치지 않도록 조정되어야 합니다.

    [[OutgoingDatagramsExpirationDuration]]

    null

    [[OutgoingMaxDatagramSize]]

    구현 정의 정수

  2. stream을 반환합니다.

5.2. 메서드

createWritable()

WebTransportDatagramsWritable를 생성합니다.

createWritable() 메서드가 호출되면, 사용자 에이전트는 다음 절차를 실행해야 합니다:

  1. transportthis와 연관된 WebTransport 객체로 설정합니다.

  2. transport.[[State]]"closed" 또는 "failed"라면, InvalidStateError 예외를 throw합니다.

  3. sendGroupoptionssendGroup으로 설정합니다.

  4. sendOrderoptionssendOrder로 설정합니다.

  5. 생성WebTransportDatagramsWritabletransport, sendGroup, sendOrder로 반환합니다.

5.3. 속성

readable, 타입 ReadableStream, 읽기 전용

getter 단계:

  1. this[[Readable]]을 반환합니다.

incomingMaxAge, 타입 unrestricted double, nullable

getter 단계:

  1. this[[IncomingDatagramsExpirationDuration]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. value가 음수 또는 NaN이면, RangeError 예외를 throw합니다.

  2. value0이면, value를 null로 설정합니다.

  3. this[[IncomingDatagramsExpirationDuration]]value로 설정합니다.

maxDatagramSize, 타입 unsigned long, 읽기 전용

WebTransportDatagramsWritable에 전달될 수 있는 최대 데이터 크기입니다. getter 단계는 this[[OutgoingMaxDatagramSize]]을 반환합니다.

outgoingMaxAge, 타입 unrestricted double, nullable

getter 단계:

  1. this[[OutgoingDatagramsExpirationDuration]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. value가 음수 또는 NaN이면, RangeError 예외를 throw합니다.

  2. value0이면, value를 null로 설정합니다.

  3. this[[OutgoingDatagramsExpirationDuration]]value로 설정합니다.

incomingHighWaterMark, 타입 unrestricted double

getter 단계:

  1. this[[IncomingDatagramsHighWaterMark]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. value가 음수 또는 NaN이면, RangeError 예외를 throw합니다.

  2. value1보다 작으면, value1로 설정합니다.

  3. this[[IncomingDatagramsHighWaterMark]]value로 설정합니다.

outgoingHighWaterMark, 타입 unrestricted double

getter 단계:

  1. this[[OutgoingDatagramsHighWaterMark]]을 반환합니다.

setter 단계 (값 value 주어짐):

  1. value가 음수 또는 NaN이면, RangeError 예외를 throw합니다.

  2. value1보다 작으면, value1로 설정합니다.

  3. this[[OutgoingDatagramsHighWaterMark]]value로 설정합니다.

5.4. 절차

pullDatagrams를 수행하려면, WebTransport 객체 transport로 다음 절차를 실행합니다:

  1. datagramstransport.[[Datagrams]]로 설정합니다.

  2. 단언: datagrams.[[IncomingDatagramsPullPromise]]가 null임을 보장합니다.

  3. queuedatagrams.[[IncomingDatagramsQueue]]로 설정합니다.

  4. queue가 비어 있으면:

    1. datagrams.[[IncomingDatagramsPullPromise]]에 새 프로미스를 설정합니다.

    2. datagrams.[[IncomingDatagramsPullPromise]]를 반환합니다.

  5. datagramtimestampqueue에서 dequeue한 결과로 설정합니다.

  6. datagrams.[[Readable]]현재 BYOB 요청 view가 null이 아니면:

    1. viewdatagrams.[[Readable]]현재 BYOB 요청 view로 설정합니다.

    2. viewbyte lengthdatagram의 크기보다 작으면, RangeError로 거부된 프로미스를 반환합니다.

    3. elementSizeTyped array constructors table에서 view.[[TypedArrayName]]에 지정된 요소 크기로 설정합니다. view에 [[TypedArrayName]] 내부 슬롯이 없으면(DataView인 경우), elementSize를 0으로 설정합니다.

    4. elementSize가 1이 아니면, TypeError로 거부된 프로미스를 반환합니다.

  7. 바이트로부터 풀 datagramdatagrams.[[Readable]]에 넣습니다.

  8. undefined로 resolve된 프로미스를 반환합니다.

receiveDatagrams를 수행하려면, WebTransport 객체 transport로 다음 절차를 실행합니다:

  1. timestamp를 현재 시점을 나타내는 타임스탬프로 설정합니다.

  2. queuedatagrams.[[IncomingDatagramsQueue]]로 설정합니다.

  3. durationdatagrams.[[IncomingDatagramsExpirationDuration]]로 설정합니다.

  4. duration이 null이면, 구현 정의 값으로 설정합니다.

  5. sessiontransport.[[Session]]로 설정합니다.

  6. session에서 수신 가능한 데이터그램이 존재하는 동안:

    1. datagram데이터그램 수신 결과로 session과 함께 설정합니다.

    2. timestamp를 현재 시점을 나타내는 타임스탬프로 설정합니다.

    3. chunkdatagramtimestamp의 쌍으로 설정합니다.

    4. 큐에 추가 chunkqueue에 넣습니다.

  7. toBeRemovedqueue의 길이에서 datagrams.[[IncomingDatagramsHighWaterMark]]를 뺀 값으로 설정합니다.

  8. toBeRemoved가 양수이면, 큐에서 dequeuequeue에 대해 toBeRemoved번(내림) 반복합니다.

  9. queue가 비어 있지 않은 동안:

    1. bytestimestampqueue의 첫 번째 요소로 설정합니다.

    2. timestamp로부터 duration 밀리초 이상 경과했다면 queue에서 dequeuequeue에 대해 실행합니다.

    3. 그렇지 않으면 이 루프를 종료합니다.

  10. queue가 비어 있지 않고 datagrams.[[IncomingDatagramsPullPromise]]가 null이 아니면:

    1. bytestimestampqueue에서 dequeue한 결과로 설정합니다.

    2. promisedatagrams.[[IncomingDatagramsPullPromise]]로 설정합니다.

    3. datagrams.[[IncomingDatagramsPullPromise]]를 null로 설정합니다.

    4. 네트워크 작업을 큐에 추가하여 transport로 다음 절차를 실행합니다:

      1. chunkUint8Array 객체로, bytes를 나타내는 것으로 생성합니다.

      2. chunk를 enqueue datagrams.[[Readable]]에 넣습니다.

      3. promise를 undefined로 resolve합니다.

사용자 에이전트는 WebTransport 객체 중 [[State]]"connected"인 경우, 알고리즘이 진행 가능할 때 최대한 빨리 receiveDatagrams를 실행하는 것이 바람직합니다.

6. WebTransport 인터페이스

WebTransport[WEB-TRANSPORT-OVERVIEW]에 정의된 하위 전송 기능에 대한 API를 제공합니다.

[Exposed=(Window,Worker), SecureContext]
interface WebTransport {
  constructor(USVString url, optional WebTransportOptions options = {});

  Promise<WebTransportConnectionStats> getStats();
  [NewObject] Promise<ArrayBuffer> exportKeyingMaterial(BufferSource label, optional BufferSource context);
  readonly attribute Promise<undefined> ready;
  readonly attribute WebTransportReliabilityMode reliability;
  readonly attribute WebTransportCongestionControl congestionControl;
  [EnforceRange] attribute unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams;
  [EnforceRange] attribute unsigned short? anticipatedConcurrentIncomingBidirectionalStreams;
  readonly attribute DOMString protocol;

  readonly attribute Promise<WebTransportCloseInfo> closed;
  readonly attribute Promise<undefined> draining;
  undefined close(optional WebTransportCloseInfo closeInfo = {});

  readonly attribute WebTransportDatagramDuplexStream datagrams;

  Promise<WebTransportBidirectionalStream> createBidirectionalStream(
      optional WebTransportSendStreamOptions options = {});
  /* a ReadableStream of WebTransportBidirectionalStream objects */
  readonly attribute ReadableStream incomingBidirectionalStreams;

  Promise<WebTransportSendStream> createUnidirectionalStream(
      optional WebTransportSendStreamOptions options = {});
  /* a ReadableStream of WebTransportReceiveStream objects */
  readonly attribute ReadableStream incomingUnidirectionalStreams;
  WebTransportSendGroup createSendGroup();

  static readonly attribute boolean supportsReliableOnly;
};

enum WebTransportReliabilityMode {
  "pending",
  "reliable-only",
  "supports-unreliable",
};

6.1. 내부 슬롯

WebTransport 객체는 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[SendStreams]] WebTransport 객체가 소유한 WebTransportSendStream순서가 있는 집합.
[[ReceiveStreams]] WebTransport 객체가 소유한 WebTransportReceiveStream순서가 있는 집합.
[[IncomingBidirectionalStreams]] ReadableStream으로, WebTransportBidirectionalStream 객체로 구성됨.
[[IncomingUnidirectionalStreams]] ReadableStream으로, WebTransportReceiveStream 객체로 구성됨.
[[State]] 전송의 상태를 나타내는 enum. "connecting", "connected", "draining", "closed", "failed" 중 하나.
[[Ready]] 관련 WebTransport 세션설정되면 fulfilled되고, 설정 과정이 실패하면 rejected되는 프로미스.
[[Reliability]] WebTransportReliabilityMode로, 첫 홉이 비신뢰성(UDP) 전송을 지원하는지, 또는 신뢰성(TCP 폴백) 전송만 가능한지를 나타냄. 연결이 설정될 때까지 "pending" 반환.
[[CongestionControl]] WebTransportCongestionControl로, 애플리케이션이 처리량 또는 저지연에 최적화된 혼잡 제어 알고리즘의 선호도를 요청했고 사용자 에이전트가 이를 만족시켰는지, 아니면 "default"인지를 나타냄.
[[AnticipatedConcurrentIncomingUnidirectionalStreams]] 애플리케이션이 서버에서 생성할 것으로 예상하는 동시에 열린 단방향(수신) 스트림의 개수 또는 null.
[[AnticipatedConcurrentIncomingBidirectionalStreams]] 애플리케이션이 서버에서 생성할 것으로 예상하는 동시에 열린 양방향 스트림의 개수 또는 null.
[[Protocol]] 서버에서 선택한 애플리케이션 수준 프로토콜을 나타내는 문자열. 초깃값은 빈 문자열.
[[Closed]] 관련 WebTransport 객체가 정상적으로 종료되면 fulfilled, 비정상적으로 종료되거나 초기화에 실패하면 rejected되는 프로미스.
[[Draining]] 관련 WebTransport 세션드레인됨 경우 fulfilled되는 프로미스.
[[Datagrams]] WebTransportDatagramDuplexStream.
[[Session]] WebTransport 객체에 대한 WebTransport 세션 또는 null.

6.2. 생성자

WebTransport() 생성자가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:
  1. baseURLthisrelevant settings objectAPI base URL로 설정합니다.

  2. parsedURLURL record로, parsing urlbaseURL을 이용하여 생성합니다.

  3. parsedURL이 실패라면, SyntaxError 예외를 throw합니다.

  4. parsedURLschemehttps가 아니면, SyntaxError 예외를 throw합니다.

  5. parsedURLfragment가 null이 아니면, SyntaxError 예외를 throw합니다.

  6. allowPoolingoptionsallowPooling 값으로 설정합니다.

  7. dedicatedallowPooling의 부정으로 설정합니다.

  8. serverCertificateHashesoptionsserverCertificateHashes 값이 있다면 그 값으로, 없으면 null로 설정합니다.

  9. dedicated가 false이고 serverCertificateHashes가 null이 아니면 NotSupportedError 예외를 throw합니다.

  10. requireUnreliableoptionsrequireUnreliable 값으로 설정합니다.

  11. congestionControloptionscongestionControl 값으로 설정합니다.

  12. congestionControl"default"가 아니면서 사용자 에이전트가 [RFC9002] Section 7에 따라 congestionControl에 최적화된 혼잡 제어 알고리즘을 지원하지 않으면, congestionControl"default"로 설정합니다.

  13. protocolsoptionsprotocols 값으로 설정합니다.

  14. protocols 값 중 중복이 존재하거나, WebTransport 프로토콜에 정의된 협상된 애플리케이션 프로토콜 값 요건을 충족하지 못하거나, isomorphic encoded 길이가 0이거나 512를 초과하면, SyntaxError 예외를 throw합니다. [WEB-TRANSPORT-OVERVIEW] Section 3.1.

  15. anticipatedConcurrentIncomingUnidirectionalStreamsoptionsanticipatedConcurrentIncomingUnidirectionalStreams 값으로 설정합니다.

  16. anticipatedConcurrentIncomingBidirectionalStreamsoptionsanticipatedConcurrentIncomingBidirectionalStreams 값으로 설정합니다.

  17. incomingDatagramsnew ReadableStream으로 생성합니다.

  18. datagramsWebTransportDatagramDuplexStream 생성 결과로, readableincomingDatagrams로 설정합니다.

  19. transport을 새롭게 생성한 WebTransport 객체로, 다음과 같이 설정합니다:

    [[SendStreams]]

    비어 있는 순서가 있는 집합

    [[ReceiveStreams]]

    비어 있는 순서가 있는 집합

    [[IncomingBidirectionalStreams]]

    ReadableStream

    [[IncomingUnidirectionalStreams]]

    ReadableStream

    [[State]]

    "connecting"

    [[Ready]]

    새 프로미스

    [[Reliability]]

    "pending"

    [[CongestionControl]]

    congestionControl

    [[AnticipatedConcurrentIncomingUnidirectionalStreams]]

    anticipatedConcurrentIncomingUnidirectionalStreams

    [[AnticipatedConcurrentIncomingBidirectionalStreams]]

    anticipatedConcurrentIncomingBidirectionalStreams

    [[Protocol]]

    빈 문자열

    [[Closed]]

    새 프로미스

    [[Draining]]

    새 프로미스

    [[Datagrams]]

    datagrams

    [[Session]]

    null

  20. pullDatagramsAlgorithmpullDatagramstransport로 실행하는 동작으로 정의합니다.

참고: 데이터그램에 64kB 버퍼를 사용하는 것이 권장됩니다. WebTransport 데이터그램 프레임의 최대 크기는 QUIC 데이터그램 프레임의 최대 크기(권장값 64kB)를 상한으로 하므로 ([QUIC-DATAGRAM] Section 3 참조), 버퍼보다 큰 데이터그램으로 스트림이 에러되는 것을 방지할 수 있습니다.

  1. Set up with byte reading support incomingDatagramspullAlgorithmpullDatagramsAlgorithm으로, highWaterMark를 0으로 설정합니다.

  2. pullBidirectionalStreamAlgorithmpullBidirectionalStreamtransport로 실행하는 동작으로 정의합니다.

  3. Set up transport.[[IncomingBidirectionalStreams]]pullAlgorithmpullBidirectionalStreamAlgorithm으로, highWaterMark를 0으로 설정합니다.

  4. pullUnidirectionalStreamAlgorithmpullUnidirectionalStreamtransport로 실행하는 동작으로 정의합니다.

  5. Set up transport.[[IncomingUnidirectionalStreams]]pullAlgorithmpullUnidirectionalStreamAlgorithm으로, highWaterMark를 0으로 설정합니다.

  6. WebTransport over HTTP 초기화transport, parsedURL, dedicated, requireUnreliable, congestionControl, protocols, serverCertificateHashes로 실행합니다.

  7. transport를 반환합니다.

HTTP를 통한 WebTransport 초기화를 수행하려면, WebTransport 객체 transport, URL record url, 불리언 dedicated, 불리언 requireUnreliable, WebTransportCongestionControl congestionControl, protocols 배열, 그리고 sequence<WebTransportHash> serverCertificateHashes로 다음 절차를 실행합니다.
  1. clienttransport관련 설정 객체로 설정합니다.

  2. originclientorigin으로 설정합니다.

  3. request를 새 request로, URLurl, clientclient, policy containerclientpolicy container, destination은 빈 문자열, originorigin, redirect mode는 "error"로 설정합니다.

  4. Content Security Policy 위반 보고request에 대해 실행합니다.

  5. Content Security Policy에 의해 요청이 차단되어야 하는지request로 검사하여 "Blocked"를 반환하거나, request잘못된 포트로 인해 차단되어야 하는지 검사하여 blocked를 반환하면, 남은 절차를 중단하고 네트워크 작업 큐에 추가하여 transport로 다음 절차를 실행합니다:

    1. transport.[[State]] 값이 "closed" 또는 "failed"이면 절차를 중단합니다.

    2. error생성WebTransportError로, source 값은 "session"으로 설정합니다.

    3. Cleanup transporterror를 실행합니다.

  6. networkPartitionKey네트워크 파티션 키 결정 결과로, transport관련 설정 객체로 실행합니다.

  7. 다음 단계를 병렬로 실행하되, 아래의 경우 중단: transport.[[State]] 값이 "closed" 또는 "failed"가 되는 경우:

    1. newConnectiondedicated이 false면 "no", 아니면 "yes-and-dedicated"로 설정합니다.

    2. connection연결 획득 결과로, networkPartitionKey, url, false, newConnection, requireUnreliable로 실행합니다. 사용자 에이전트가 둘 이상의 혼잡 제어 알고리즘을 지원한다면, congestionControl에 적합한 알고리즘을 선택하여 connection에서 데이터 전송에 사용합니다. 연결 획득 시 serverCertificateHashes가 지정되면, 기본 인증서 검증 알고리즘 대신 사용자 지정 인증서 요구사항을 만족하고, 인증서 해시 검증 결과가 true면 인증서를 유효로 간주합니다. 둘 중 하나라도 만족하지 않으면 connection을 failure로 설정합니다.

    3. connection이 failure인 경우, 남은 절차를 중단하고 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. transport.[[State]] 값이 "closed" 또는 "failed"이면 절차를 중단합니다.

      2. error생성WebTransportError로, source 값은 "session"으로 설정합니다.

      3. Cleanup transporterror를 실행합니다.

        참고: 리다이렉트는 따르지 않습니다. 리다이렉트로 인한 네트워크 오류는 의도적으로 다른 네트워크 오류와 구별되지 않습니다. 교차 출처 컨텍스트에서는 CORS로 차단되는 정보를 노출할 수 있기 때문입니다. 동일 출처 컨텍스트에서는 핸드셰이크를 정보 전달 벡터로 악용할 수 있습니다.

    4. connection이 SETTINGS 프레임을 처음 받을 때까지 대기하고, settings를 그 SETTINGS 프레임을 나타내는 딕셔너리로 설정합니다.

    5. settings에 SETTINGS_ENABLE_WEBTRANPORT 값이 1인 항목이나 H3_DATAGRAM 값이 1인 항목이 없으면 남은 절차를 중단하고 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. transport.[[State]] 값이 "closed" 또는 "failed"이면 절차를 중단합니다.

      2. error생성WebTransportError로, source 값은 "session"으로 설정합니다.

      3. Cleanup transporterror를 실행합니다.

    6. WebTransport 세션 설정origin, protocols, connection으로 실행합니다.

      참고: 이 단계에서 [QUIC-DATAGRAM]에서 지정한 트랜스포트 파라미터 교환도 포함됩니다.

    7. 이전 단계가 실패하면 남은 절차를 중단하고 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. transport.[[State]] 값이 "closed" 또는 "failed"이면 절차를 중단합니다.

      2. error생성WebTransportError로, source 값은 "session"으로 설정합니다.

      3. Cleanup transporterror를 실행합니다.

    8. session을 설정된 WebTransport 세션으로 설정합니다.

    9. 단언: maxDatagramSize는 정수입니다.

    10. 네트워크 작업 큐에 추가하여 transport로 다음 절차를 실행합니다:

      1. transport.[[State]] 값이 "connecting"이 아니면:

        1. 병렬로 session 종료session으로 실행합니다.

        2. 절차를 중단합니다.

      2. transport.[[State]] 값을 "connected"로 설정합니다.

      3. transport.[[Session]] 값을 session으로 설정합니다.

      4. transport.[[Protocol]] 값을 협상된 애플리케이션 프로토콜의 문자열 값(존재하면)으로 설정하거나, [WEB-TRANSPORT-OVERVIEW] Section 3.1 절차에 따릅니다. 없다면 ""로 설정합니다.

      5. 연결이 HTTP/3 연결이면, transport.[[Reliability]] 값을 "supports-unreliable"로 설정합니다.

      6. 연결이 HTTP/2 연결이면 [WEB-TRANSPORT-HTTP2], transport[[Reliability]] 값을 "reliable-only"로 설정합니다.

      7. Resolve transport.[[Ready]] 값을 undefined로 설정합니다.

양방향 스트림 풀링을 수행하려면, WebTransport 객체 transport로 다음 단계를 실행합니다.
  1. transport.[[State]] 값이 "connecting"이면, transport.[[Ready]]이행될 때 다음 단계를 실행한 결과를 반환합니다:

    1. pullBidirectionalStreamtransport로 실행한 결과를 반환합니다.

  2. transport.[[State]] 값이 "connected"가 아니면, Rejected 프로미스와 InvalidStateError를 반환합니다.

  3. sessiontransport.[[Session]]로 설정합니다.

  4. p를 새 프로미스로 설정합니다.

  5. 다음 단계를 병렬로 실행합니다:

    1. 수신 가능한 양방향 스트림이 있을 때까지 대기합니다.

    2. internalStream양방향 스트림 수신 결과로 설정합니다.

    3. 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. streamWebTransportBidirectionalStream 생성 결과로, internalStreamtransport를 인자로 설정합니다.

      2. stream을 enqueue하여 transport.[[IncomingBidirectionalStreams]]에 넣습니다.

      3. p를 undefined로 resolve합니다.

  6. p를 반환합니다.

단방향 스트림 풀링을 수행하려면, WebTransport 객체 transport로 다음 단계를 실행합니다.
  1. transport.[[State]] 값이 "connecting"이면, transport.[[Ready]]이행될 때 다음 단계를 실행한 결과를 반환합니다:

    1. pullUnidirectionalStreamtransport로 실행한 결과를 반환합니다.

  2. transport.[[State]] 값이 "connected"가 아니면, Rejected 프로미스와 InvalidStateError를 반환합니다.

  3. sessiontransport.[[Session]]로 설정합니다.

  4. p를 새 프로미스로 설정합니다.

  5. 다음 단계를 병렬로 실행합니다:

    1. 수신 가능한 단방향 스트림이 있을 때까지 대기합니다.

    2. internalStream단방향 스트림 수신 결과로 설정합니다.

    3. 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. streamWebTransportReceiveStream 생성 결과로, internalStreamtransport를 인자로 설정합니다.

      2. stream을 enqueue하여 transport.[[IncomingUnidirectionalStreams]]에 넣습니다.

      3. p를 undefined로 resolve합니다.

  6. p를 반환합니다.

6.3. 속성

ready, 타입 Promise<undefined>, 읽기 전용

getter 시 this[[Ready]]를 반환해야 합니다.

closed, 타입 Promise<WebTransportCloseInfo>, 읽기 전용

getter 시 this[[Closed]]를 반환해야 합니다.

draining, 타입 Promise<undefined>, 읽기 전용

getter 시 this[[Draining]]를 반환해야 합니다.

datagrams, 타입 WebTransportDatagramDuplexStream, 읽기 전용

이 세션에서 데이터그램 송수신을 위한 단일 이중 스트림. datagrams 속성의 getter 단계는 다음과 같습니다:

  1. this[[Datagrams]]를 반환합니다.

incomingBidirectionalStreams, 타입 ReadableStream, 읽기 전용

서버로부터 수신된 WebTransportBidirectionalStream 객체의 ReadableStream을 반환합니다.

참고: 스트림에 이미 데이터가 있는지 여부는 서버 동작에 따라 다릅니다.

incomingBidirectionalStreams 속성의 getter 단계는 다음과 같습니다:

  1. this[[IncomingBidirectionalStreams]]를 반환합니다.

incomingUnidirectionalStreams, 타입 ReadableStream, 읽기 전용

서버로부터 수신된 단방향 스트림 각각을 WebTransportReceiveStream으로 나타내는 ReadableStream을 반환합니다.

참고: 스트림에 이미 데이터가 있는지 여부는 서버 동작에 따라 다릅니다.

incomingUnidirectionalStreams의 getter 단계는 다음과 같습니다:

  1. this.[[IncomingUnidirectionalStreams]]를 반환합니다.

reliability, 타입 WebTransportReliabilityMode, 읽기 전용

연결이 UDP 기반 비신뢰성 전송을 지원하는지, 혹은 TCP 폴백 신뢰성 전송만 지원하는지를 나타냅니다. 연결이 설정될 때까지는 "pending"을 반환합니다. getter 단계는 this[[Reliability]]를 반환합니다.

congestionControl, 타입 WebTransportCongestionControl, 읽기 전용

애플리케이션이 생성자에서 요청한 경우, 그리고 사용자 에이전트가 이를 만족시킨 경우, 이 연결에서 송신에 대해 처리량 또는 저지연에 최적화된 혼잡 제어 알고리즘을 사용할 선호도입니다. 선호도가 요청되었으나 만족되지 않으면 값은 "default"입니다. getter 단계는 this[[CongestionControl]]를 반환합니다.

supportsReliableOnly, 타입 boolean, 읽기 전용

사용자 에이전트가 WebTransport 세션을 오직 신뢰성 연결 위에서만 지원하는 경우 true, 그렇지 않으면 false를 반환합니다.

anticipatedConcurrentIncomingUnidirectionalStreams, 타입 unsigned short, nullable

애플리케이션이 서버가 동시에 생성할 것으로 예상하는 수신 단방향 스트림 개수를 지정할 수 있습니다. null이 아니면 사용자 에이전트는 이후 왕복(RTT)을 줄이기 위해 [[AnticipatedConcurrentIncomingUnidirectionalStreams]] 값을 서버와 협상 시 고려해야 합니다.

getter 단계는 this[[AnticipatedConcurrentIncomingUnidirectionalStreams]]를 반환합니다.

setter 단계에서 value가 주어지면 this[[AnticipatedConcurrentIncomingUnidirectionalStreams]]value로 설정합니다.

anticipatedConcurrentIncomingBidirectionalStreams, 타입 unsigned short, nullable

애플리케이션이 서버가 동시에 생성할 것으로 예상하는 양방향 스트림 개수를 지정할 수 있습니다. null이 아니면 사용자 에이전트는 이후 왕복(RTT)을 줄이기 위해 [[AnticipatedConcurrentIncomingBidirectionalStreams]] 값을 서버와 협상 시 고려해야 합니다.

getter 단계는 this[[AnticipatedConcurrentIncomingBidirectionalStreams]]를 반환합니다.

setter 단계에서 value가 주어지면 this[[AnticipatedConcurrentIncomingBidirectionalStreams]]value로 설정합니다.

참고: anticipatedConcurrentIncomingUnidirectionalStreams 또는 anticipatedConcurrentIncomingBidirectionalStreams를 설정하더라도, 애플리케이션이 예상한 만큼의 스트림을 반드시 수신할 것이라는 보장은 없습니다.

protocol, 타입 DOMString, 읽기 전용

WebTransport 세션이 설정되고, protocols 생성자 옵션에 비어있지 않은 배열이 제공된 경우, 서버가 선택한 애플리케이션 수준 프로토콜을 반환합니다(존재할 경우). 그렇지 않으면 빈 문자열을 반환합니다. getter 단계는 this[[Protocol]]를 반환합니다.

6.4. 메서드

close(closeInfo)

WebTransport 객체와 연결된 WebTransport 세션을 종료합니다.

close가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. transport.[[State]] 값이 "closed" 또는 "failed"라면, 이 절차를 중단합니다.

  3. transport.[[State]] 값이 "connecting"이면:

    1. error생성WebTransportError로, source 값은 "session"으로 설정합니다.

    2. Cleanup transporterror를 실행합니다.

    3. 이 절차를 중단합니다.

  4. sessiontransport.[[Session]]로 설정합니다.

  5. codecloseInfo.closeCode로 설정합니다.

  6. reasonStringcloseInfo.reason의 최대 코드 유닛 접두사로, 길이UTF-8 인코딩된 접두사가 1024를 넘지 않는 경우로 설정합니다.

  7. reasonreasonStringUTF-8 인코딩 값으로 설정합니다.

  8. 병렬로, session 종료session, code, reason으로 실행합니다.

    참고: 이 단계는 또한 리셋 또는 STOP_SENDING 전송WebTransport 스트림에 대해 실행하며, transport.[[SendStreams]][[ReceiveStreams]]에 포함된 스트림에 적용됩니다.

  9. Cleanup transportAbortError, closeInfo를 실행합니다.

getStats()

WebTransport기저 연결에 대한 통계를 수집하여 비동기로 결과를 반환합니다.

getStats가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. p를 새 프로미스로 설정합니다.

  3. transport.[[State]] 값이 "failed"라면, p를 reject하고 InvalidStateError와 함께 이 절차를 중단합니다.

  4. 다음 단계를 병렬로 실행합니다:

    1. transport.[[State]] 값이 "connecting"이면 변경될 때까지 대기합니다.

    2. transport.[[State]] 값이 "failed"라면, 네트워크 작업 큐에 추가하여 transportp를 reject하고 InvalidStateError와 함께 절차를 중단합니다.

    3. transport.[[State]] 값이 "closed"라면, 네트워크 작업 큐에 추가하여 transportp를 resolve하고, 연결에 대해 가장 최근 수집된 통계를 반환합니다. 해당 시점은 구현 정의입니다.

    4. 기저 연결에서 통계를 수집하고, 데이터그램 통계도 포함합니다.

    5. 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. statsnew WebTransportConnectionStats 객체로, 수집한 통계를 나타냅니다.

      2. p를 resolve하고 stats를 반환합니다.

  5. p를 반환합니다.

exportKeyingMaterial(BufferSource label, optional BufferSource context)

WebTransport기저 연결에 고유하게 연결된 TLS 세션에 대해 TLS Keying Material Exporter에서 암호화 키 재료를 추출합니다.

exportKeyingMaterial이 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. labelLengthlabel.바이트 길이로 설정합니다.

  3. labelLength가 255를 초과하면 RangeError로 reject된 프로미스를 반환합니다.

  4. contextLength를 0으로 설정합니다.

  5. context가 주어진 경우, contextLengthcontext.바이트 길이로 설정합니다.

  6. contextLength가 255를 초과하면 RangeError로 reject된 프로미스를 반환합니다.

  7. p를 새 프로미스로 설정합니다.

  8. 다음 단계를 병렬로 실행하지만, 다음 조건에서 중단: transport[[State]] 값이 "closed" 또는 "failed"가 될 때, 대신 네트워크 작업 큐에 추가하여 transportp를 reject하고 InvalidStateError와 함께 중단합니다:

    1. keyingMaterial[WEB-TRANSPORT-HTTP3] Section 4.7에 따라 labelLength, label, contextLength, context(있으면)로 TLS 키 재료를 추출한 결과로 설정합니다.

    2. 네트워크 작업 큐에 추가하여 transportp를 resolve하고 keyingMaterial을 반환합니다.

  9. p를 반환합니다.

createBidirectionalStream()

송신용 양방향 스트림을 위한 WebTransportBidirectionalStream 객체를 생성합니다. 스트림이 생성된 것만으로는 상대방에게 바로 보이지 않으며, 데이터가 전송될 때에야 상대방이 인지합니다.

참고: 서버는 해당 스트림에 데이터가 전송되기 전까지 스트림의 존재를 인지할 필요가 없습니다.

createBidirectionalStream이 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. transport.[[State]] 값이 "closed" 또는 "failed"라면, Rejected 프로미스와 InvalidStateError를 반환합니다.

  3. sendGroupoptionssendGroup 값으로 설정합니다.

  4. sendOrderoptionssendOrder 값으로 설정합니다.

  5. waitUntilAvailableoptionswaitUntilAvailable 값으로 설정합니다.

  6. p를 새 프로미스로 설정합니다.

  7. 다음 단계를 병렬로 실행하지만, 아래 조건에서 중단: transport[[State]] 값이 "closed" 또는 "failed"가 될 때, 대신 네트워크 작업 큐에 추가하여 transportp를 reject하고 InvalidStateError와 함께 중단합니다:

    1. streamIdtransport.[[Session]]에 대해 유효하고 고유한 새 스트림 ID로 설정합니다. ([QUIC] Section 19.11 참조) 바로 사용할 수 없을 경우, waitUntilAvailable가 true면 사용할 수 있을 때까지 대기, false면 네트워크 작업 큐에 추가하여 transportp를 reject하고, QuotaExceededError와 함께 중단합니다.

    2. internalStream양방향 스트림 생성 결과로, transport.[[Session]]streamId를 인자로 설정합니다.

    3. 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. transport.[[State]] 값이 "closed" 또는 "failed"라면, p를 reject하고 InvalidStateError와 함께 중단합니다.

      2. streamWebTransportBidirectionalStream 생성 결과로, internalStream, transport, sendGroup, sendOrder를 인자로 설정합니다.

      3. p를 resolve하고 stream을 반환합니다.

  8. p를 반환합니다.

createUnidirectionalStream()

송신용 단방향 스트림을 위한 WebTransportSendStream을 생성합니다. 스트림 생성만으로는 서버에 바로 보이지 않으며, 데이터가 전송될 때에야 서버가 인지합니다.

참고: 서버는 해당 스트림에 데이터가 전송되기 전까지 스트림의 존재를 인지할 필요가 없습니다.

createUnidirectionalStream()가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. transport.[[State]] 값이 "closed" 또는 "failed"라면, Rejected 프로미스와 InvalidStateError를 반환합니다.

  3. sendGroupoptionssendGroup 값으로 설정합니다.

  4. sendOrderoptionssendOrder 값으로 설정합니다.

  5. waitUntilAvailableoptionswaitUntilAvailable 값으로 설정합니다.

  6. p를 새 프로미스로 설정합니다.

  7. 다음 단계를 병렬로 실행하지만, 아래 조건에서 중단: transport[[State]] 값이 "closed" 또는 "failed"가 될 때, 대신 네트워크 작업 큐에 추가하여 transportp를 reject하고 InvalidStateError와 함께 중단합니다:

    1. streamIdtransport.[[Session]]에 대해 유효하고 고유한 새 스트림 ID로 설정합니다. ([QUIC] Section 19.11 참조) 바로 사용할 수 없을 경우, waitUntilAvailable가 true면 사용할 수 있을 때까지 대기, false면 네트워크 작업 큐에 추가하여 transportp를 reject하고, QuotaExceededError와 함께 중단합니다.

    2. internalStream송신 단방향 스트림 생성 결과로, transport.[[Session]]streamId를 인자로 설정합니다.

    3. 네트워크 작업 큐에 추가하여 transport로 다음을 실행합니다:

      1. transport.[[State]] 값이 "closed" 또는 "failed"라면, p를 reject하고 InvalidStateError와 함께 중단합니다.

      2. streamWebTransportSendStream 생성 결과로, internalStream, transport, sendGroup, sendOrder를 인자로 설정합니다.

      3. p를 resolve하고 stream을 반환합니다.

  8. p를 반환합니다.

createSendGroup()

WebTransportSendGroup를 생성합니다.

createSendGroup()가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. transportthis로 설정합니다.

  2. transport.[[State]] 값이 "closed" 또는 "failed"라면, InvalidStateError 예외를 throw합니다.

  3. WebTransportSendGroup 생성 결과를 transport로 반환합니다.

6.5. 절차

정리(cleanup)를 수행하려면, WebTransport transporterror, 그리고 선택적으로 closeInfo로 다음 단계를 실행합니다:
  1. sendStreamstransport.[[SendStreams]]의 복사본으로 설정합니다.

  2. receiveStreamstransport.[[ReceiveStreams]]의 복사본으로 설정합니다.

  3. outgoingDatagramWritablestransport.[[Datagrams]].[[Writables]]로 설정합니다.

  4. incomingDatagramstransport.[[Datagrams]].[[Readable]]로 설정합니다.

  5. readytransport.[[Ready]]로 설정합니다.

  6. closedtransport.[[Closed]]로 설정합니다.

  7. incomingBidirectionalStreamstransport.[[IncomingBidirectionalStreams]]로 설정합니다.

  8. incomingUnidirectionalStreamstransport.[[IncomingUnidirectionalStreams]]로 설정합니다.

  9. transport.[[SendStreams]]를 빈 집합(set)으로 설정합니다.

  10. transport.[[ReceiveStreams]]를 빈 집합(set)으로 설정합니다.

  11. transport.[[Datagrams]].[[OutgoingDatagramsQueue]]를 빈 큐(queue)로 설정합니다.

  12. transport.[[Datagrams]].[[IncomingDatagramsQueue]]를 빈 큐(queue)로 설정합니다.

  13. closeInfo가 주어지면 transport.[[State]]"closed"로 설정합니다. 그렇지 않으면 transport.[[State]]"failed"로 설정합니다.

  14. streamsendStreams에서 다음과 같이 처리합니다:

    1. stream.[[PendingOperation]]이 null이 아니면, stream.[[PendingOperation]]error로 reject합니다.

    2. 에러 처리(error)streamerror로 실행합니다.

  15. streamreceiveStreams에서 에러 처리(error)streamerror로 실행합니다.

    참고: 스크립트 작성자는 Promise 이행 시 동기적으로 코드를 삽입할 수 있으므로, 이후 transport를 예측 불가능하게 스크립트에 의해 변경될 수 있으니 접근하지 않습니다. 이 로직을 호출하는 부분에도 적용됩니다.

  16. closeInfo가 주어지면:

    1. resolve closedcloseInfo로 처리합니다.

    2. 단언: readysettled 상태입니다.

    3. closeincomingBidirectionalStreams에 실행합니다.

    4. closeincomingUnidirectionalStreams에 실행합니다.

    5. outgoingDatagramWritables의 각 writableclose를 실행합니다.

    6. closeincomingDatagrams에 실행합니다.

  17. 그렇지 않으면:

    1. reject closederror로 처리합니다.

    2. closed.[[PromiseIsHandled]]를 true로 설정합니다.

    3. reject readyerror로 처리합니다.

    4. ready.[[PromiseIsHandled]]를 true로 설정합니다.

    5. 에러 처리(error)incomingBidirectionalStreamserror로 실행합니다.

    6. 에러 처리(error)incomingUnidirectionalStreamserror로 실행합니다.

    7. outgoingDatagramWritables의 각 writable에러 처리(error)error로 실행합니다.

    8. 에러 처리(error)incomingDatagramserror로 실행합니다.

네트워크 작업 큐에 추가(queue a network task)를 수행하려면, WebTransport transport와 일련의 단계 steps로 다음을 실행합니다:

  1. 글로벌 작업 큐에 추가(queue a global task)네트워킹 작업 소스(network task source)에, transport관련 글로벌 객체(relevant global object)steps를 실행하도록 큐에 추가합니다.

6.6. 클라이언트가 시작하지 않은 세션 종료

WebTransport 세션WebTransport transport에 연결되어 있고 종료(terminated)될 때, 선택적으로 codereasonBytes와 함께 다음 절차를 실행합니다:
  1. 네트워크 작업 큐에 추가transport로, 다음 단계를 실행합니다:

    1. transport.[[State]] 값이 "closed" 또는 "failed"라면, 이 절차를 중단합니다.

    2. error생성WebTransportError로, source 값을 "session"으로 설정합니다.

    3. closeInfonew WebTransportCloseInfo로 생성합니다.

    4. code가 주어졌다면, closeInfocloseCodecode로 설정합니다.

    5. reasonBytes가 주어졌다면, closeInforeasonreasonBytesUTF-8 디코딩 값으로 설정합니다.

      참고: reasonBytes에는 언어 또는 방향 메타데이터가 없습니다. 값을 표시할 때 First-strong 휴리스틱을 사용할 수 있습니다.

    6. 정리(cleanup)transporterror, closeInfo로 실행합니다.

WebTransport transport기저 연결에서 연결 오류가 발생하면, 다음 절차를 실행합니다:
  1. 네트워크 작업 큐에 추가transport로, 다음 단계를 실행합니다:

    1. transport.[[State]] 값이 "closed" 또는 "failed"라면, 이 절차를 중단합니다.

    2. error생성WebTransportError로, source 값을 "session"으로 설정합니다.

    3. 정리(cleanup)transporterror로 실행합니다.

6.7. 컨텍스트 정리 절차

이 현행 표준은 컨텍스트 정리 절차(context cleanup steps)를 다음과 같이 정의합니다. WebTransport transport가 있을 때:

  1. transport.[[State]] 값이 "connected"라면:

    1. transport.[[State]] 값을 "failed"로 설정합니다.

    2. 병렬로, 세션 종료transport.[[Session]]에 대해 실행합니다.

    3. 네트워크 작업 큐에 추가transport로, 다음을 실행합니다:

      1. error생성WebTransportError로, source 값을 "session"으로 설정합니다.

      2. 정리(cleanup)transporterror로 실행합니다.

  2. transport.[[State]] 값이 "connecting"이면, transport.[[State]] 값을 "failed"로 설정합니다.

    이 작업은 워커에서도 수행되어야 합니다. #127whatwg/html#6731를 참조하세요.

6.8. 가비지 컬렉션(Garbage Collection)

WebTransport 객체의 [[State]] 값이 "connecting"일 때, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 하나라도 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태거나, ready, draining, closed 프로미스가 관찰되고 있다면 가비지 컬렉션되어서는 안 됩니다.

WebTransport 객체의 [[State]] 값이 "connected"일 때, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 하나라도 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태거나, draining 또는 closed 프로미스가 관찰되고 있다면 가비지 컬렉션되어서는 안 됩니다.

WebTransport 객체의 [[State]] 값이 "draining"일 때, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 하나라도 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태거나, closed 프로미스가 관찰되고 있다면 가비지 컬렉션되어서는 안 됩니다.

WebTransport 객체의 세션이 설정되어 있고 WebTransport 세션 에 네트워크로 전송될 대기 중인 데이터가 있다면(예: [[Datagrams]].[[OutgoingDatagramsQueue]]의 데이터그램 포함), 가비지 컬렉션되어서는 안 됩니다.

WebTransport 객체가 가비지 컬렉션되는 동안 기저 연결 이 아직 열려 있으면, 사용자 에이전트는 WebTransport 세션 종료를 Application Error Code 0 및 Application Error Message ""로 수행해야 합니다.

6.9. 구성(Configuration)

dictionary WebTransportHash {
  DOMString algorithm;
  BufferSource value;
};

dictionary WebTransportOptions {
  boolean allowPooling = false;
  boolean requireUnreliable = false;
  sequence<WebTransportHash> serverCertificateHashes;
  WebTransportCongestionControl congestionControl = "default";
  [EnforceRange] unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams = null;
  [EnforceRange] unsigned short? anticipatedConcurrentIncomingBidirectionalStreams = null;
  sequence<DOMString> protocols = [];
};

enum WebTransportCongestionControl {
  "default",
  "throughput",
  "low-latency",
};

WebTransportOptionsWebTransport 세션이 어떻게 설정되고 사용되는지 결정하는 매개변수들의 딕셔너리입니다.

allowPooling, 타입 boolean, 기본값 false

true로 설정하면 WebTransport 세션이 풀링될 수 있습니다. 즉, 기저 연결이 다른 WebTransport 세션과 공유될 수 있습니다.

requireUnreliable, 타입 boolean, 기본값 false

true로 설정하면, HTTP/3 연결이 불가능한 경우 HTTP/2 연결을 통해서는 WebTransport 세션을 설정할 수 없습니다.

serverCertificateHashes, 타입 sequence<WebTransportHash>

이 옵션은 전용 연결을 사용하는 전송에만 지원됩니다. 이 기능을 지원하지 않는 전송 프로토콜에서 해당 필드가 비어 있지 않으면 NotSupportedError 예외가 발생합니다.

지원되고 비어 있지 않으면, 사용자 에이전트는 인증서 해시 검증serverCertificateHashes에서 성공하고 사용자 지정 인증서 요구사항을 만족하는 경우에만 해당 서버 인증서를 신뢰해야 합니다. 사용자 에이전트는 알 수 없는 algorithm을 사용하는 해시는 무시해야 합니다. 비어 있으면, 평소 fetch 작업에서 사용하는 인증서 검증 절차를 사용해야 합니다.

이 옵션은 allowPooling과 함께 사용할 수 없습니다.

congestionControl, 타입 WebTransportCongestionControl, 기본값 "default"

애플리케이션이 이 연결을 통해 데이터를 전송할 때 처리량 또는 저지연에 최적화된 혼잡 제어 알고리즘을 선호함을 선택적으로 지정합니다. 이는 사용자 에이전트에 대한 힌트입니다.

이 구성 옵션은 저지연을 최적화하는 혼잡 제어 알고리즘이 브라우저에 구현되어 있지 않으므로 위험(Risk)이 있는 기능으로 간주됩니다.

anticipatedConcurrentIncomingUnidirectionalStreams, 타입 unsigned short, nullable, 기본값 null

애플리케이션이 서버가 동시에 만들 것으로 예상하는 수신 단방향 스트림 개수를 선택적으로 지정할 수 있습니다. 사용자 에이전트는 서버로부터 최소 100개의 수신 단방향 스트림을 허용해야 합니다. null이 아니면, 사용자 에이전트는 [[AnticipatedConcurrentIncomingUnidirectionalStreams]] 값을 서버와의 협상 시 고려하여 왕복을 줄이도록 노력해야 합니다.

anticipatedConcurrentIncomingBidirectionalStreams, 타입 unsigned short, nullable, 기본값 null

애플리케이션이 서버가 동시에 만들 것으로 예상하는 양방향 스트림 개수를 선택적으로 지정할 수 있습니다. 사용자 에이전트는 서버가 최소 100개의 양방향 스트림을 만들 수 있도록 허용해야 합니다. null이 아니면, 사용자 에이전트는 [[AnticipatedConcurrentIncomingBidirectionalStreams]] 값을 서버와의 협상 시 고려하여 왕복을 줄이도록 노력해야 합니다.

protocols, 타입 sequence<DOMString>, 기본값 []

애플리케이션 수준 프로토콜 이름 배열을 선택적으로 제공합니다. 서버는 선호하는 애플리케이션 프로토콜을 선택하여 클라이언트에 전달할 수 있습니다(선택적). 서버는 적절한 프로토콜이 제공되지 않으면 요청을 거부할 수도 있습니다.

인증서 해시 계산을 수행하려면, certificate가 주어졌을 때 다음 단계를 실행합니다:
  1. certcertificate로, [RFC5280]에 정의된 Certificate 메시지의 DER 인코딩으로 표현합니다.

  2. cert의 SHA-256 해시를 계산하여 그 값을 반환합니다.

인증서 해시 검증을 수행하려면, certificate와 해시 배열 hashes가 주어졌을 때 다음 단계를 실행합니다:
  1. referenceHash인증서 해시 계산certificate로 실행한 결과로 설정합니다.

  2. hashhashes에서 다음과 같이 처리합니다:

    1. hash.value 값이 null이 아니고, hash.algorithm 값이 "sha-256"과 ASCII 대소문자 구분 없이 일치하면:

      1. hashValuehash.value가 나타내는 바이트 시퀀스로 설정합니다.

      2. hashValuereferenceHash와 같으면 true를 반환합니다.

  3. false를 반환합니다.

사용자 지정 인증서 요구사항은 다음과 같습니다: 인증서는 [RFC5280]에 정의된 X.509v3 인증서여야 하며, Subject Public Key 필드에 사용된 키는 허용된 공개키 알고리즘 중 하나여야 하며, 현재 시간은 [RFC5280] 4.1.2.5절에 정의된 인증서 유효기간 내에 있어야 하며, 전체 유효기간 길이는 2주를 넘지 않아야 합니다. 사용자 에이전트는 인증서에 추가 구현 정의 요구사항을 적용할 수 있습니다.

Subject Public Key Info 필드(그리고 TLS CertificateVerify 메시지에도)에서 사용할 허용된 공개키 알고리즘의 정확한 목록은 구현 정의입니다. 하지만, 상호 운용 가능한 기본값으로 secp256r1(NIST P-256) 그룹의 ECDSA는 반드시 포함되어야 합니다([RFC3279] 2.3.5절, [RFC8422]). RSA 키는 포함되어서는 안 됩니다([RFC3279] 2.3.1절).

6.10. WebTransportCloseInfo 딕셔너리

WebTransportCloseInfo 딕셔너리는 WebTransport의 종료 에러 코드와 관련된 정보를 포함합니다. 이 정보는 CONNECTION_CLOSE 프레임의 에러 코드와 이유(reason)를 지정하는 데 사용됩니다.

dictionary WebTransportCloseInfo {
  unsigned long closeCode = 0;
  USVString reason = "";
};

이 딕셔너리는 다음 속성을 가집니다:

closeCode, 타입 unsigned long, 기본값 0

피어로 전달되는 에러 코드입니다.

reason, 타입 USVString, 기본값 ""

WebTransport를 종료하는 이유(reason)입니다.

6.11. WebTransportSendOptions 딕셔너리

WebTransportSendOptionscreateUnidirectionalStream, createBidirectionalStream, createWritable 메서드의 동작을 제어하는 기본 매개변수 딕셔너리입니다.

dictionary WebTransportSendOptions {
  WebTransportSendGroup? sendGroup = null;
  long long sendOrder = 0;
};

이 딕셔너리는 다음 속성을 가집니다:

sendGroup, 타입 WebTransportSendGroup, nullable, 기본값 null

생성된 스트림을 그룹(group)으로 묶기 위한 선택적 WebTransportSendGroup 또는 null입니다.

sendOrder, 타입 long long, 기본값 0

send order 번호를 지정하면 생성된 스트림이 엄격한 순서(strict ordering)에 참여합니다. 현재 엄격 순서(strictly ordered) 스트림에 대기 중인 바이트는 send order 번호가 더 낮은 엄격 순서(strictly ordered) 스트림에 대기 중인 바이트보다 먼저 전송됩니다.

send order 번호를 지정하지 않으면, 해당 스트림에서 바이트를 다른 스트림에 비해 언제 전송할지는 구현 정의입니다. 하지만, 사용자 에이전트는 send order 번호가 낮은 스트림에 bandwidth가 부족하지 않은 한 모든 스트림 간에 대역폭을 공평하게 분배하는 것이 권장됩니다.

참고: 이는 송신 측 데이터 우선순위화로, 수신 순서를 보장하지 않습니다.

6.12. WebTransportSendStreamOptions 딕셔너리

WebTransportSendStreamOptionsWebTransportSendStreamcreateUnidirectionalStream 또는 createBidirectionalStream 에 의해 생성될 때의 동작을 제어하는 매개변수 딕셔너리입니다.

dictionary WebTransportSendStreamOptions : WebTransportSendOptions {
  boolean waitUntilAvailable = false;
};

이 딕셔너리는 다음 속성을 가집니다:

waitUntilAvailable, 타입 boolean, 기본값 false

true일 때, createUnidirectionalStream 또는 createBidirectionalStream 호출의 프로미스는 이행(settled)되지 않습니다. 기저 연결에 스트림을 생성할 충분한 플로우 컨트롤 크레딧이 생기거나, 연결에서 더 이상 송신 스트림을 생성할 수 없는 상태가 될 때까지 대기합니다. false일 때는, 호출 시 플로우 컨트롤 윈도우가 없다면 프로미스가 reject됩니다.

6.13. WebTransportConnectionStats 딕셔너리

WebTransportConnectionStats 딕셔너리는 WebTransport 세션기저 연결에 대한 WebTransport 고유 통계 정보를 포함합니다.

참고: 풀링이 사용되는 경우, 동일한 WebTransport 세션이 동일한 연결에 풀링되어 있다면 모두 동일한 정보를 받습니다. 즉, 동일한 세션에 대해 네트워크 파티션 키가 같으면 정보가 공유됩니다.

참고: 제공되지 않는 통계 정보는 존재하지 않음(absent)으로 WebTransportConnectionStats 딕셔너리에 나타납니다.

dictionary WebTransportConnectionStats {
  unsigned long long bytesSent = 0;
  unsigned long long packetsSent = 0;
  unsigned long long bytesLost = 0;
  unsigned long long packetsLost = 0;
  unsigned long long bytesReceived = 0;
  unsigned long long packetsReceived = 0;
  required DOMHighResTimeStamp smoothedRtt;
  required DOMHighResTimeStamp rttVariation;
  required DOMHighResTimeStamp minRtt;
  required WebTransportDatagramStats datagrams;
  unsigned long long? estimatedSendRate = null;
  boolean atSendCapacity = false;
};

이 딕셔너리는 다음 속성을 가집니다:

bytesSent, 타입 unsigned long long, 기본값 0

기저 연결(underlying connection)에서 송신된 바이트 수(재전송 포함). UDP 등 외부 프레이밍은 포함하지 않습니다.

packetsSent, 타입 unsigned long long, 기본값 0

기저 연결에서 송신된 패킷 수(손실로 판명된 패킷도 포함).

bytesLost, 타입 unsigned long long, 기본값 0

기저 연결에서 손실된 바이트 수(단조 증가하지 않을 수 있음, 손실로 선언된 패킷이 나중에 수신될 수 있음). UDP 등 외부 프레이밍은 포함하지 않습니다.

packetsLost, 타입 unsigned long long, 기본값 0

기저 연결에서 손실된 패킷 수(단조 증가하지 않을 수 있음, 손실로 선언된 패킷이 나중에 수신될 수 있음).

bytesReceived, 타입 unsigned long long, 기본값 0

기저 연결에서 수신된 총 바이트 수(스트림의 중복 데이터 포함). UDP 등 외부 프레이밍은 포함하지 않습니다.

packetsReceived, 타입 unsigned long long, 기본값 0

기저 연결에서 수신된 총 패킷 수(처리 불가 패킷도 포함).

smoothedRtt, 타입 DOMHighResTimeStamp

현재 연결에서 측정된 평활화 RTT([RFC9002] 5.3절 참고).

rttVariation, 타입 DOMHighResTimeStamp

현재 연결에서 측정된 RTT 샘플의 평균 변화([RFC9002] 5.3절 참고).

minRtt, 타입 DOMHighResTimeStamp

전체 연결에서 관측된 최소 RTT입니다.

estimatedSendRate, 타입 unsigned long long, nullable, 기본값 null

사용자 에이전트가 대기 중인 데이터를 전송할 것으로 예상되는 속도(bps). 이 속도는 WebTransport 세션을 공유하는 모든 스트림과 데이터그램에 적용되며, 혼잡 제어 알고리즘(예: congestionControl)에 의해 계산됩니다. 프레이밍 오버헤드는 제외하며, 실제 애플리케이션 페이로드 전송 속도를 나타냅니다. 사용자 에이전트가 현재 추정값을 갖고 있지 않으면 null이어야 합니다. 이전 결과에서는 null이 아니었더라도 현재 null일 수 있습니다.

atSendCapacity, 타입 boolean, 기본값 false

false이면 estimatedSendRate 값이 애플리케이션에 의해 제한됨을 의미합니다. 즉, 애플리케이션이 혼잡 제어기가 허용하는 것보다 훨씬 적은 데이터를 전송하고 있을 수 있습니다. 혼잡 제어기가 네트워크 용량을 잘못 추정할 수 있습니다.

true이면 애플리케이션이 네트워크 용량만큼 데이터를 보내고 있고, estimatedSendRate 값이 애플리케이션에 허용된 네트워크 용량을 반영합니다.

atSendCapacitytrue일 때, estimatedSendRate 값은 상한값(ceiling)을 나타냅니다. 애플리케이션이 지속적으로 데이터를 전송하면 estimatedSendRate 는 네트워크 환경에 따라 적응합니다. 하지만 estimatedSendRatenull일 수도 있습니다(atSendCapacity 가 true여도).

6.14. WebTransportDatagramStats 딕셔너리

WebTransportDatagramStats 딕셔너리는 기저 연결을 통한 데이터그램 전송에 대한 통계를 포함합니다.

dictionary WebTransportDatagramStats {
  unsigned long long droppedIncoming = 0;
  unsigned long long expiredIncoming = 0;
  unsigned long long expiredOutgoing = 0;
  unsigned long long lostOutgoing = 0;
};

이 딕셔너리는 다음 속성을 가집니다:

droppedIncoming, 타입 unsigned long long, 기본값 0

애플리케이션이 datagramsreadable에서 읽기 전에, 새 데이터그램이 수신 큐를 넘치게 하여 드롭된 수신 데이터그램의 개수입니다.

expiredIncoming, 타입 unsigned long long, 기본값 0

수신된 데이터그램이 incomingMaxAge보다 오래되어 datagramsreadable에서 읽히기 전에 드롭된 개수입니다.

expiredOutgoing, 타입 unsigned long long, 기본값 0

송신 대기 중인 데이터그램이 outgoingMaxAge보다 오래되어 전송되기 전에 드롭된 개수입니다.

lostOutgoing, 타입 unsigned long long, 기본값 0

[RFC9002] 6.1절에 정의된 대로, 송신된 데이터그램이 손실로 선언된 개수입니다.

7. 인터페이스 WebTransportSendStream

WebTransportSendStreamWritableStream 으로, 출발지 단방향 또는 양방향 WebTransport 스트림을 통한 송신 스트리밍 기능을 제공합니다.

이것은 WritableStream 타입의 Uint8Array 데이터로, 서버로 데이터를 전송하기 위해 쓸 수 있습니다.

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportSendStream : WritableStream {
  attribute WebTransportSendGroup? sendGroup;
  attribute long long sendOrder;
  Promise<WebTransportSendStreamStats> getStats();
  WebTransportWriter getWriter();
};

WebTransportSendStream 은 항상 create 절차에 의해 생성됩니다.

WebTransportSendStream전송 단계전송-수신 단계WritableStream의 WritableStream의 단계와 동일합니다.

7.1. 속성

sendGroup, 타입 WebTransportSendGroup, nullable

getter 단계:

  1. this[[SendGroup]]를 반환합니다.

setter 단계, value가 주어진 경우:

  1. value가 null이 아니고, value.[[Transport]]this.[[Transport]]와 다르다면, InvalidStateError 예외를 InvalidStateError로 throw합니다.

  2. this.[[SendGroup]]value를 설정합니다.

sendOrder, 타입 long long

getter 단계:

  1. this[[SendOrder]]를 반환합니다.

setter 단계, value가 주어진 경우:

  1. this.[[SendOrder]]value를 설정합니다.

7.2. 메서드

getStats()

WebTransportSendStream의 성능과 관련된 통계를 수집하여, 결과를 비동기로 보고합니다.

getStats가 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:

  1. p를 새로운 promise로 둡니다.

  2. 다음 단계를 병렬로 실행합니다:

    1. WebTransportSendStream에 대한 통계를 수집합니다.

    2. 통계가 준비될 때까지 대기합니다.

    3. 네트워크 작업을 큐에 넣습니다. transport로 다음 단계를 실행:

      1. 수집된 통계를 나타내는 statsnew WebTransportSendStreamStats 객체로 생성합니다.

      2. Resolve pstats로 해결합니다.

  3. p를 반환합니다.

getWriter()

이 메서드는 getWriterWritableStream 에서 상속받은 것과 동일한 방식으로 구현되어야 하지만, WritableStreamDefaultWriter 를 생성하는 대신, WebTransportWriterWebTransportWriterthis와 함께 생성해야 합니다.

7.3. 내부 슬롯

WebTransportSendStream 은 다음의 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[InternalStream]] 출발지 단방향 또는 양방향 WebTransport 스트림입니다.
[[PendingOperation]] 보류 중인 쓰기 또는 닫기 작업을 나타내는 promise, 또는 null.
[[Transport]] WebTransport가 소유하는 WebTransportSendStream입니다.
[[SendGroup]] 옵션의 WebTransportSendGroup, 또는 null.
[[SendOrder]] 옵션의 전송 순서 번호, 기본값은 0.
[[AtomicWriteRequests]] ordered set의 promise 집합으로, 기본 싱크에 의해 처리 대기 중인 원자적 쓰기 요청의 부분집합을 추적합니다.
[[BytesWritten]] 스트림에 기록된 바이트 수.
[[CommittedOffset]] 스트림 내 오프셋으로, 리셋되어도 피어에게 전달될 바이트 수를 기록합니다; [RELIABLE-RESET] 참고.

7.4. 절차

생성 절차로, WebTransportSendStream출발지 단방향 또는 양방향 WebTransport 스트림 internalStream, WebTransport transport, sendGroup, sendOrder와 함께 생성하려면 다음 단계를 실행합니다:

  1. streamnew WebTransportSendStream로 생성합니다. 다음과 같이 초기화됩니다:

    [[InternalStream]]

    internalStream

    [[PendingOperation]]

    null

    [[Transport]]

    transport

    [[SendGroup]]

    sendGroup

    [[SendOrder]]

    sendOrder

    [[AtomicWriteRequests]]

    비어 있는 ordered set의 promise 집합

    [[BytesWritten]]

    0

    [[CommittedOffset]]

    0

  2. writeAlgorithmchunkstream쓰기 위한 동작으로 둡니다.

  3. closeAlgorithmstream닫기 위한 동작으로 둡니다.

  4. abortAlgorithmreason과 함께 stream중단하는 동작으로 둡니다.

  5. Set up streamwriteAlgorithmwriteAlgorithm으로, closeAlgorithmcloseAlgorithm으로, abortAlgorithmabortAlgorithm으로 설정합니다.

  6. abortSignalstream의 [[controller]].[[abortController]].[[signal]]로 둡니다.

  7. 다음 단계abortSignal에 추가합니다.

    1. pendingOperationstream.[[PendingOperation]]로 둡니다.

    2. pendingOperation이 null이면, 이 단계들을 중단합니다.

    3. stream.[[PendingOperation]]를 null로 설정합니다.

    4. reasonabortSignalabort reason으로 둡니다.

    5. promise중단 stream with reason의 결과로 둡니다.

    6. Upon fulfillment of promise, reject pendingOperationreason으로 거절합니다.

  8. Append streamtransport.[[SendStreams]]에 추가합니다.

  9. stream을 반환합니다.

쓰기 절차로, WebTransportSendStream streamchunk를 쓰려면 다음 단계를 실행합니다:
  1. transportstream.[[Transport]]로 둡니다.

  2. chunkBufferSource가 아니면, 거절된 promiseTypeError와 함께 반환합니다.

  3. promise를 새로운 promise로 둡니다.

  4. byteschunk가 나타내는 바이트 시퀀스의 복사본으로 둡니다.

  5. stream.[[PendingOperation]]promise로 설정합니다.

  6. inFlightWriteRequeststream.inFlightWriteRequest로 둡니다.

  7. atomicstream.[[AtomicWriteRequests]]inFlightWriteRequest를 포함하면 true, 그렇지 않으면 false로 둡니다.

  8. 다음 단계들을 병렬로 실행합니다:

    1. atomic이 true이고, 현재 흐름 제어 윈도우가 bytes 전체를 보내기에 너무 작으면, 나머지 단계를 중단하고 네트워크 작업을 큐에 넣고 transport에서 다음 하위 단계 실행:

      1. stream.[[PendingOperation]]를 null로 설정합니다.

      2. 모든 원자적 쓰기 요청 중단stream에 수행합니다.

    2. 그 외의 경우, 전송 bytesstream.[[InternalStream]]에서 보내고 작업이 완료될 때까지 대기합니다. 이 전송은 이전에 큐에 넣은 스트림 또는 데이터그램의 전송과, 앞으로 큐에 넣을 스트림 또는 데이터그램의 전송과 interleave될 수 있습니다.

      유저 에이전트는 전송 성능 향상을 위해 버퍼를 둘 수 있습니다. 이러한 버퍼는 고정된 상한값을 가져야 하며, WebTransportSendStream 사용자에게 backpressure 정보를 전달해야 합니다.

      이 전송은 같은 [[SendGroup]]과 더 높은 [[SendOrder]]를 가진 스트림에 큐된 모든 바이트가 먼저 전송되어야만 차단됩니다. 해당 스트림들이 에러 상태가 아니고, 흐름 제어로 인해 차단되지 않아야 합니다.

      stream.[[SendOrder]]병렬로 접근합니다. 유저 에이전트는 전송 중 해당 값의 실시간 업데이트에 반응해야 하지만, 자세한 동작은 구현 정의입니다.

      참고: 재전송의 순서는 구현 정의이지만, 유저 에이전트는 더 높은 [[SendOrder]] 값을 가진 데이터의 재전송을 우선시해야 합니다.

      이 전송은 다른 이유로 차단되어서는 안 되며, 단지 흐름 제어에러에 의해서만 차단될 수 있습니다.

      유저 에이전트는 차단되지 않은 모든 스트림에 대해 대역폭을 공정하게 분배해야 합니다.

      참고: 여기서의 공정성 정의는 구현 정의입니다.

    3. 이전 단계가 네트워크 오류로 실패하면, 나머지 단계를 중단합니다.

      참고: 여기서 promise를 거절하지 않는 이유는, 네트워크 오류는 별도의 단계에서 처리되며 그 단계에서 stream.[[PendingOperation]]를 거절하기 때문입니다.

    4. 그 외의 경우, 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      1. stream.[[PendingOperation]]를 null로 설정합니다.

      2. bytes의 길이를 stream.[[BytesWritten]]에 더합니다.

      3. stream.[[AtomicWriteRequests]]inFlightWriteRequest를 포함하는 경우, inFlightWriteRequest를 제거합니다.

      4. promise를 undefined로 해결합니다.

  9. promise를 반환합니다.

참고: 이 알고리즘(또는 write(chunk))에서 반환된 promise가 반드시 서버가 ack했다는 뜻은 아닙니다. 단지 버퍼에 추가되었음을 의미할 수 있습니다. 서버에 정상적으로 도달했는지 확인하려면, 서버가 응용 계층의 확인 메시지를 보내야 합니다. [QUIC]

닫기 절차로, WebTransportSendStream stream을 닫으려면 다음 단계를 실행합니다:
  1. transportstream.[[Transport]]로 둡니다.

  2. promise를 새로운 promise로 둡니다.

  3. streamtransport.[[SendStreams]]에서 제거합니다.

  4. stream.[[PendingOperation]]promise로 설정합니다.

  5. 다음 단계들을 병렬로 실행합니다:

    1. FIN 전송stream.[[InternalStream]]에서 수행하고, 작업이 완료될 때까지 대기합니다.

    2. stream.[[InternalStream]]가 "all data committed" 상태가 될 때까지 대기합니다. [QUIC]

    3. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      1. stream.[[PendingOperation]]를 null로 설정합니다.

      2. promise를 undefined로 해결합니다.

  6. promise를 반환합니다.

중단 절차로, WebTransportSendStream streamreason과 함께 중단하려면 다음 단계를 실행합니다:
  1. transportstream.[[Transport]]로 둡니다.

  2. promise를 새로운 promise로 둡니다.

  3. code를 0으로 둡니다.

  4. streamtransport.[[SendStreams]]에서 제거합니다.

  5. reasonWebTransportError이고, reason.[[StreamErrorCode]]가 null이 아니면, codereason.[[StreamErrorCode]]로 설정합니다.

  6. code가 0보다 작으면 code를 0으로 설정합니다.

  7. code가 4294967295보다 크면 code를 4294967295로 설정합니다.

  8. committedOffsetstream.[[CommittedOffset]]로 둡니다.

    참고: code의 유효값은 0에서 4294967295까지입니다. 기저 연결이 HTTP/3를 사용하면, code[WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162]로 인코딩됩니다.

  9. 다음 단계들을 병렬로 실행합니다:

    1. 리셋stream.[[InternalStream]]codecommittedOffset으로 수행합니다.

    2. 네트워크 작업을 큐에 넣고 transport에서 promise를 undefined로 해결합니다.

  10. promise를 반환합니다.

모든 원자적 쓰기 요청 중단 절차로, WebTransportSendStream stream에 대해 다음 단계를 실행합니다:
  1. writeRequestsstream.writeRequests로 둡니다.

  2. requestsToAbortstream.[[AtomicWriteRequests]]로 둡니다.

  3. writeRequestsrequestsToAbort에 없는 promise를 포함하면, 에러streamAbortError로 발생시키고, 이 단계들을 중단합니다.

  4. 비움stream.[[AtomicWriteRequests]]에 수행합니다.

  5. promise에 대해 requestsToAbort에서 promiseAbortError로 거절합니다.

  6. 병렬로, promise에 대해 requestsToAbort에서 해당 바이트 전송을 중단합니다.

7.5. 서버로부터 오는 STOP_SENDING 시그널

WebTransport streamWebTransportSendStream stream과 연관되어 있을 때 서버로부터 STOP_SENDING 시그널을 받으면, 다음 단계를 실행합니다:
  1. transportstream.[[Transport]]로 둡니다.

  2. code를 STOP_SENDING 프레임에 부착된 응용 프로토콜 오류 코드로 둡니다. [QUIC]

    참고: code의 유효값은 0에서 4294967295까지입니다. 기저 연결이 HTTP/3를 사용하면, code[WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162]로 인코딩됩니다.

  3. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

    1. transport.[[State]]"closed" 또는 "failed"이면, 이 단계들을 중단합니다.

    2. streamtransport.[[SendStreams]]에서 제거합니다.

    3. error새로 생성된 WebTransportError로 둡니다. source 값은 "stream"이고, streamErrorCode 값은 code입니다.

    4. stream.[[PendingOperation]] 이 null이 아니면, stream.[[PendingOperation]]error로 거절합니다.

    5. 에러streamerror로 발생시킵니다.

7.6. WebTransportSendStreamStats 사전

WebTransportSendStreamStats 사전은 하나의 WebTransportSendStream에 특화된 통계 정보를 포함합니다.

dictionary WebTransportSendStreamStats {
  unsigned long long bytesWritten = 0;
  unsigned long long bytesSent = 0;
  unsigned long long bytesAcknowledged = 0;
};

해당 사전은 다음 속성을 가집니다:

bytesWritten, 타입 unsigned long long, 기본값 0

애플리케이션이 해당 WebTransportSendStream에 성공적으로 기록한 총 바이트 수입니다. 이 값은 오직 증가할 수 있습니다.

bytesSent, 타입 unsigned long long, 기본값 0

해당 WebTransportSendStream에 기록된 애플리케이션 바이트가 적어도 한 번 전송된 진행 상황을 나타냅니다. 이 값은 오직 증가할 수 있고, bytesWritten 값 이하입니다.

참고: 이는 단일 스트림에서 전송된 앱 데이터의 진행 상황만을 나타내며, 네트워크 오버헤드는 포함하지 않습니다.

bytesAcknowledged, 타입 unsigned long long, 기본값 0

해당 WebTransportSendStream에 기록된 애플리케이션 바이트 중 서버가 QUIC의 ACK 메커니즘을 통해 수신을 인정한 바이트 수를 나타냅니다. 확인되지 않은 첫 바이트를 제외하고, 그 이전까지의 연속된 바이트만 집계됩니다. 이 값도 오직 증가할 수 있고, bytesSent 값 이하입니다.

참고: HTTP/2 환경에서는 이 값이 bytesSent와 일치합니다.

8. 인터페이스 WebTransportSendGroup

WebTransportSendGroup 은 여러 개의 개별 (일반적으로 엄격하게 순서화된) WebTransportSendStream에 걸쳐 분산된 데이터 전송을 추적하는 선택적 조직 객체입니다.

WebTransportSendStream은 생성 시 또는 sendGroup 속성 할당을 통해 언제든지 최대 하나의 WebTransportSendGroup그룹화될 수 있습니다. 기본적으로는 그룹화되지 않음 상태입니다.

유저 에이전트는 WebTransportSendGroup들에 대해 WebTransportSendStream 전송을 위한 대역폭 할당 시 동등하게 간주합니다. 각 WebTransportSendGroupsendOrder 평가를 위한 독립적인 번호 공간도 제공합니다.

[Exposed=(Window,Worker), SecureContext]
interface WebTransportSendGroup {
  Promise<WebTransportSendStreamStats> getStats();
};

WebTransportSendGroup 은 항상 create 절차에 의해 생성됩니다.

8.1. 메서드

getStats()

이 sendGroup에 그룹화된 모든 WebTransportSendStream의 통계를 집계하여 비동기로 결과를 보고합니다.

getStats가 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:

  1. p를 새로운 promise로 둡니다.

  2. streamsWebTransportSendStream[[SendGroup]]this인 모든 스트림으로 둡니다.

  3. 다음 단계들을 병렬로 실행합니다:

    1. streams의 모든 스트림에서 통계 정보를 수집합니다.

    2. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      1. 수집된 통계의 집계 값을 나타내는 statsnew WebTransportSendStreamStats 객체로 생성합니다.

      2. promisestats로 해결합니다.

  4. p를 반환합니다.

8.2. 내부 슬롯

WebTransportSendGroup 은 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[Transport]] WebTransport 객체가 해당 WebTransportSendGroup를 소유합니다.

8.3. 절차

생성 절차로, WebTransportSendGroupWebTransport transport와 함께 생성하려면 다음 단계를 실행합니다:

  1. sendGroupnew WebTransportSendGroup로 생성합니다. 다음과 같이 초기화됩니다:

    [[Transport]]

    transport

  2. sendGroup을 반환합니다.

9. 인터페이스 WebTransportReceiveStream

WebTransportReceiveStreamReadableStream으로, 수신 단방향 또는 양방향 WebTransport 스트림의 수신 스트리밍 기능을 제공합니다.

ReadableStream 타입의 Uint8Array 데이터이며, 서버로부터 수신된 데이터를 소비할 수 있습니다. WebTransportReceiveStream읽기 바이트 스트림이며, 따라서 소비자가 BYOB 리더기본 리더 모두 사용할 수 있습니다.

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportReceiveStream : ReadableStream {
  Promise<WebTransportReceiveStreamStats> getStats();
};

WebTransportReceiveStream 은 항상 create 절차에 의해 생성됩니다.

WebTransportReceiveStream전송 단계전송-수신 단계ReadableStream의 단계와 동일합니다.

9.1. 메서드

getStats()

WebTransportReceiveStream의 성능에 특화된 통계를 수집하여, 결과를 비동기로 보고합니다.

getStats가 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:

  1. p를 새로운 promise로 둡니다.

  2. 다음 단계들을 병렬로 실행합니다:

    1. WebTransportReceiveStream에 대한 통계를 수집합니다.

    2. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      1. 수집된 통계를 나타내는 statsnew WebTransportReceiveStreamStats 객체로 생성합니다.

      2. promisestats로 해결합니다.

  3. p를 반환합니다.

9.2. 내부 슬롯

WebTransportReceiveStream 은 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[InternalStream]] 수신 단방향 또는 양방향 WebTransport 스트림입니다.
[[Transport]] WebTransport 객체가 해당 WebTransportReceiveStream를 소유합니다.

9.3. 절차

생성 절차로, WebTransportReceiveStream수신 단방향 또는 양방향 WebTransport 스트림 internalStreamWebTransport transport로 생성하려면 다음 단계를 수행합니다:

  1. streamnew WebTransportReceiveStream으로 생성합니다. 다음과 같이 초기화합니다:

    [[InternalStream]]

    internalStream

    [[Transport]]

    transport

  2. pullAlgorithmstream으로부터 바이트를 풀하는 동작으로 둡니다.

  3. cancelAlgorithmreason과 함께 stream취소하는 동작으로 둡니다.

  4. 바이트 읽기 지원으로 설정streampullAlgorithmpullAlgorithm으로, cancelAlgorithmcancelAlgorithm으로 설정합니다.

  5. Append streamtransport.[[ReceiveStreams]]에 추가합니다.

  6. stream을 반환합니다.

바이트 풀 절차로, WebTransportReceiveStream stream에서 바이트를 풀하려면 다음 단계를 실행합니다.

  1. transportstream.[[Transport]]로 둡니다.

  2. internalStreamstream.[[InternalStream]]로 둡니다.

  3. promise를 새로운 promise로 둡니다.

  4. buffer, offset, maxBytes를 null로 둡니다.

  5. streamcurrent BYOB request view가 null이 아니면:

    1. offsetstreamcurrent BYOB request view.[[ByteOffset]]으로 둡니다.

    2. maxBytesstreamcurrent BYOB request viewbyte length로 둡니다.

    3. bufferstreamcurrent BYOB request viewunderlying buffer로 둡니다.

  6. 그 외의 경우:

    1. offset을 0으로 둡니다.

    2. maxBytes구현 정의 크기로 둡니다.

    3. buffernew ArrayBuffermaxBytes 크기로 둡니다. ArrayBuffer 할당이 실패하면, 거절된 promiseRangeError와 함께 반환합니다.

  7. 다음 단계들을 병렬로 실행합니다:

    1. 쓰기읽은 바이트를 internalStream에서 bufferoffset 위치에 최대 maxBytes 바이트까지 기록합니다. 최소 한 바이트가 읽히거나 FIN이 수신될 때까지 대기합니다. read를 읽은 바이트 수로, hasReceivedFIN을 FIN이 동반되었는지 여부로 둡니다.

      유저 에이전트는 전송 성능 향상을 위해 버퍼를 둘 수 있습니다. 이러한 버퍼는 고정된 상한값을 가져야 하며, 서버로 backpressure 정보를 전달해야 합니다.

      참고: 이 동작은 buffer 전체를 채우기 전에 반환될 수 있습니다.

    2. 이전 단계가 실패하면, 나머지 단계를 중단합니다.

      참고: 여기서 promise를 거절하지 않는 이유는, 네트워크 오류는 별도의 단계에서 처리되며 그 단계에서 에러stream에 발생되어 해당 풀을 대기 중인 읽기 요청이 거절되기 때문입니다.

    3. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      참고: 위의 버퍼가 해당 이벤트 루프에 존재하면, 아래 단계가 즉시 실행될 수 있습니다.

      1. read > 0이면:

        1. viewbuffer, offset, read로 새로운 Uint8Array로 둡니다.

        2. Enqueue viewstream에 넣습니다.

      2. hasReceivedFIN이 true이면:

        1. Remove streamtransport.[[ReceiveStreams]]에서 제거합니다.

        2. Close stream을 닫습니다.

      3. promise를 undefined로 해결합니다.

  8. promise를 반환합니다.

취소 절차로, WebTransportReceiveStream streamreason과 함께 취소하려면 다음 단계를 실행합니다.

  1. transportstream.[[Transport]]로 둡니다.

  2. internalStreamstream.[[InternalStream]]로 둡니다.

  3. promise를 새로운 promise로 둡니다.

  4. code를 0으로 둡니다.

  5. reasonWebTransportError이고, reason.[[StreamErrorCode]]가 null이 아니면, codereason.[[StreamErrorCode]]로 설정합니다.

  6. code가 0보다 작으면 code를 0으로 설정합니다.

  7. code가 4294967295보다 크면 code를 4294967295로 설정합니다.

    참고: code의 유효값은 0에서 4294967295까지입니다. 기저 연결이 HTTP/3를 사용하면, code[WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162]로 인코딩됩니다.

  8. Remove streamtransport.[[SendStreams]]에서 제거합니다.

  9. 다음 단계들을 병렬로 실행합니다:

    1. STOP_SENDING 전송internalStreamcode로 실행합니다.

    2. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

      참고: 위의 버퍼가 해당 이벤트 루프에 존재하면, 아래 단계가 즉시 실행될 수 있습니다.

      1. Remove streamtransport.[[ReceiveStreams]]에서 제거합니다.

      2. promise를 undefined로 해결합니다.

  10. promise를 반환합니다.

9.4. 서버로부터 오는 Reset 신호

WebTransport streamWebTransportReceiveStream stream과 연관되어 있을 때 서버로부터 RESET_STREAM 신호를 받으면, 다음 단계를 실행합니다:
  1. transportstream.[[Transport]]로 둡니다.

  2. code를 RESET_STREAM_AT 또는 WT_RESET_STREAM 프레임에 부착된 응용 프로토콜 오류 코드로 둡니다. [RELIABLE-RESET] [WEB-TRANSPORT-HTTP2]

    참고: code의 유효값은 0에서 4294967295까지입니다. 기저 연결이 HTTP/3를 사용하면, code[WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162]로 인코딩됩니다.

  3. 네트워크 작업을 큐에 넣고 transport에서 다음 단계 실행:

    1. transport.[[State]]"closed" 또는 "failed"이면, 이 단계들을 중단합니다.

    2. streamtransport.[[ReceiveStreams]]에서 제거합니다.

    3. error새로 생성된 WebTransportError로 둡니다. source 값은 "stream"이고, streamErrorCode 값은 code입니다.

    4. 에러streamerror로 발생시킵니다.

9.5. WebTransportReceiveStreamStats 사전

WebTransportReceiveStreamStats 사전은 하나의 WebTransportReceiveStream에 특화된 통계 정보를 포함합니다.

dictionary WebTransportReceiveStreamStats {
  unsigned long long bytesReceived = 0;
  unsigned long long bytesRead = 0;
};

해당 사전은 다음 속성을 가집니다:

bytesReceived, 타입 unsigned long long, 기본값 0

서버 애플리케이션이 해당 WebTransportReceiveStream에 전달하고자 한 바이트 중 지금까지 수신된 진행 상황을 나타냅니다. 확인되지 않은 첫 바이트를 제외하고, 그 이전까지의 연속된 바이트만 집계됩니다. 이 값은 오직 증가할 수 있습니다.

참고: 이는 단일 스트림에서 수신된 앱 데이터의 진행 상황만을 나타내며, 네트워크 오버헤드는 포함하지 않습니다.

bytesRead, 타입 unsigned long long, 기본값 0

애플리케이션이 해당 WebTransportReceiveStream에서 성공적으로 읽은 총 바이트 수입니다. 이 값은 오직 증가할 수 있으며, 항상 bytesReceived 값 이하입니다.

10. 인터페이스 WebTransportBidirectionalStream

[Exposed=(Window,Worker), SecureContext]
interface WebTransportBidirectionalStream {
  readonly attribute WebTransportReceiveStream readable;
  readonly attribute WebTransportSendStream writable;
};

10.1. 내부 슬롯

WebTransportBidirectionalStream 은 다음의 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[Readable]] WebTransportReceiveStream입니다.
[[Writable]] WebTransportSendStream입니다.
[[Transport]] WebTransport 객체가 해당 WebTransportBidirectionalStream를 소유합니다.

10.2. 속성

readable, 타입 WebTransportReceiveStream, readonly

getter 단계는 this[[Readable]]를 반환하는 것입니다.

writable, 타입 WebTransportSendStream, readonly

getter 단계는 this[[Writable]]를 반환하는 것입니다.

10.3. 절차

생성 절차로, WebTransportBidirectionalStream양방향 WebTransport 스트림 internalStream, WebTransport 객체 transport, sendOrder와 함께 생성하려면 다음 단계를 실행합니다.
  1. readableWebTransportReceiveStream 생성의 결과로 둡니다. internalStreamtransport를 사용합니다.

  2. writableWebTransportSendStream 생성의 결과로 둡니다. internalStream, transport, sendOrder를 사용합니다.

  3. streamnew WebTransportBidirectionalStream로 생성합니다. 다음과 같이 초기화합니다:

    [[Readable]]

    readable

    [[Writable]]

    writable

    [[Transport]]

    transport

  4. stream을 반환합니다.

11. WebTransportWriter 인터페이스

WebTransportWriterWritableStreamDefaultWriter 의 하위 클래스로, 두 가지 메서드가 추가됩니다.

WebTransportWriter 는 항상 생성 절차에 의해 생성됩니다.

[Exposed=*, SecureContext]
interface WebTransportWriter : WritableStreamDefaultWriter {
  Promise<undefined> atomicWrite(optional any chunk);
  undefined commit();
};

11.1. 메서드

atomicWrite(chunk)

atomicWrite 메서드는 전달된 chunk가 전송 시점의 흐름 제어 윈도우 내에서 전체가 전송될 수 없다면 거절됩니다. 이 동작은 흐름 제어 교착 상태에 민감한 특수 트랜잭션 기반 응용을 만족시키기 위해 설계되었습니다 ([RFC9308] Section 4.4 참고).

참고: atomicWrite 는 일부 데이터를 전송한 후에도 거절될 수 있습니다. 흐름 제어 관점에서만 원자성을 제공하며, 다른 오류가 발생할 수 있습니다. atomicWrite 는 데이터가 패킷 사이에서 분할되거나 다른 데이터와 interleaved되는 것을 방지하지 않습니다. 단지 송신자만 atomicWrite 가 흐름 제어 크레딧 부족으로 실패한 것을 알 수 있습니다.

참고: 원자적 쓰기는 비원자적 쓰기 뒤에 큐에 있을 경우 여전히 블록될 수 있습니다. 만약 원자적 쓰기가 거절되면, 그 시점 이후 큐에 있는 모든 요청도 거절됩니다. 이렇게 거절된 비원자적 쓰기는 스트림 에러를 발생시킵니다. 따라서 응용에서는 항상 atomicWrite를 await하는 것이 권장됩니다.

atomicWrite 가 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:

  1. pwrite(chunk)WritableStreamDefaultWriterchunk를 사용해 호출한 결과로 둡니다.

  2. Append pstream.[[AtomicWriteRequests]]에 추가합니다.

  3. promise가 settle 될 때 반응하는 결과를 반환하며, 다음 단계를 실행합니다:

    1. stream.[[AtomicWriteRequests]]p를 포함하면, p를 제거합니다.

    2. pr 이유로 거절되면, 거절된 promiser로 반환합니다.

    3. undefined를 반환합니다.

commit()

commit 메서드는 스트림의 [[CommittedOffset]] 값을 해당 스트림에 기록된 바이트([[BytesWritten]])로 갱신합니다. 이렇게 하면 그 바이트들이 중단되어 스트림이 리셋되더라도 피어에게 신뢰성 있게 전달됨이 보장됩니다. [RELIABLE-RESET]의 메커니즘을 사용합니다.

참고: 이는 연결 실패 상황까지 전달을 보장하지는 않으며, 스트림이 리셋될 때만 보장됩니다.

commitstream에 대해 호출되면, 유저 에이전트는 다음 단계를 실행해야 합니다:

  1. transportstream.[[Transport]]로 둡니다.

  2. stream.[[CommittedOffset]]stream.[[BytesWritten]] 값으로 설정합니다.

11.2. 절차

생성 절차로, WebTransportWriterWebTransportSendStream stream과 함께 생성하려면 다음 단계를 실행합니다:

  1. writernew WebTransportWriter로 생성합니다.

  2. new WritableStreamDefaultWriter(stream) 생성자 단계를 writer를 this로, stream을 생성자 인자로 넘겨 실행합니다.

  3. writer를 반환합니다.

12. WebTransportError 인터페이스

WebTransportErrorDOMException 의 하위 클래스입니다.

[Exposed=(Window,Worker), Serializable, SecureContext]
interface WebTransportError : DOMException {
  constructor(optional DOMString message = "", optional WebTransportErrorOptions options = {});

  readonly attribute WebTransportErrorSource source;
  readonly attribute unsigned long? streamErrorCode;
};

dictionary WebTransportErrorOptions {
  WebTransportErrorSource source = "stream";
  [Clamp] unsigned long? streamErrorCode = null;
};

enum WebTransportErrorSource {
  "stream",
  "session",
};

12.1. 내부 슬롯

WebTransportError 은 다음 내부 슬롯을 가집니다.

내부 슬롯 설명 (비규범적)
[[Source]] WebTransportErrorSource로, 이 오류의 원인을 나타냅니다.
[[StreamErrorCode]] 이 오류에 대한 응용 프로토콜 오류 코드, 또는 null.

12.2. 생성자

new WebTransportError(message, options) 생성자 단계는 다음과 같습니다:

  1. thisname"WebTransportError"로 설정합니다.

  2. thismessagemessage로 설정합니다.

  3. this의 내부 슬롯을 다음과 같이 설정합니다:

    [[Source]]

    options.source

    [[StreamErrorCode]]

    options.streamErrorCode

    참고: 이 name은 레거시 코드에 매핑되지 않으므로, thiscode 값은 0입니다.

12.3. 속성

source, 타입 WebTransportErrorSource, readonly

getter 단계는 this[[Source]]를 반환하는 것입니다.

streamErrorCode, 타입 unsigned long, readonly, nullable

getter 단계는 this[[StreamErrorCode]]를 반환하는 것입니다.

12.4. 직렬화

WebTransportError 객체는 직렬화 가능한 객체입니다. 해당 직렬화 단계(valueserialized가 주어짐)는 다음과 같습니다:

  1. DOMException 직렬화 단계valueserialized로 실행합니다.

  2. serialized.[[Source]]value.[[Source]]를 설정합니다.

  3. serialized.[[StreamErrorCode]]value.[[StreamErrorCode]]를 설정합니다.

해당 역직렬화 단계(serializedvalue가 주어짐)는 다음과 같습니다:

  1. DOMException 역직렬화 단계serializedvalue로 실행합니다.

  2. value.[[Source]]serialized.[[Source]]로 설정합니다.

  3. value.[[StreamErrorCode]]serialized.[[StreamErrorCode]]로 설정합니다.

13. 프로토콜 매핑

이 섹션은 비규범적입니다.

이 섹션에서는 [WEB-TRANSPORT-OVERVIEW]를 활용하여, 이 명세에 정의된 메서드의 기저 프로토콜 동작을 설명합니다. 버퍼링으로 인해 인과관계가 즉각적이지 않을 수 있습니다.

WebTransport 프로토콜 동작 API 효과
세션 drained await wt.draining

기저 연결이 HTTP/3를 사용하는 경우, [WEB-TRANSPORT-HTTP3]의 다음 프로토콜 동작이 적용됩니다.

WebTransportError 오류에서 application streamErrorCode 값은 httpErrorCode로 변환되며, 반대도 마찬가지입니다. 자세한 내용은 [WEB-TRANSPORT-HTTP3] Section 4.3을 참고하세요.

API 메서드 QUIC 프로토콜 동작
writable.abort(error) RESET_STREAM_AT를 httpErrorCode와 해당 [[CommittedOffset]] 오프셋(스트림 헤더 포함)으로 전송; 자세한 내용은 [RELIABLE-RESET] 참고
writable.close() STREAM FIN 비트 설정하여 전송
writable.getWriter().write(chunk)() STREAM 전송
writable.getWriter().close() STREAM FIN 비트 설정하여 전송
writable.getWriter().abort(error) RESET_STREAM_AT를 httpErrorCode와 해당 [[CommittedOffset]] 오프셋(스트림 헤더 포함)으로 전송; 자세한 내용은 [RELIABLE-RESET] 참고
readable.cancel(error) STOP_SENDING을 httpErrorCode와 함께 전송
readable.getReader().cancel(error) STOP_SENDING을 httpErrorCode와 함께 전송
wt.close(closeInfo) 세션 종료 (closeInfo 포함)
QUIC 프로토콜 동작 API 효과
httpErrorCode와 함께 STOP_SENDING 수신 에러 발생 writable (streamErrorCode 포함)
STREAM 수신 (await readable.getReader().read()).value
STREAM FIN 비트 설정 수신 (await readable.getReader().read()).done
httpErrorCode와 함께 RESET_STREAM 수신 에러 발생 readable (streamErrorCode 포함)
세션이 clean하게 종료됨 (closeInfo 포함)
(await wt.closed).closeInfo, 그리고 에러 발생 열린 스트림들
네트워크 오류
(await wt.closed) rejected, 그리고 에러 발생 열린 스트림들

참고: [QUIC]의 Section 3.2에서 논의된 대로, RESET_STREAM 또는 RESET_STREAM_AT 프레임([RELIABLE-RESET])의 수신이 애플리케이션에 항상 즉시 표시되는 것은 아닙니다. 리셋 신호는 즉시 전달되어 스트림 데이터 전달을 중단시키고, 소비되지 않은 데이터는 폐기될 수 있습니다. 그러나 즉각적 신호가 필수는 아닙니다. 특히 Reliable Size 필드가 있는 RESET_STREAM_AT 프레임의 데이터를 전달하기 위해 신호가 지연될 수 있습니다. 스트림 데이터가 모두 수신되었지만 애플리케이션이 아직 읽지 않았다면 신호가 생략될 수 있습니다. WebTransport는 스트림 헤더의 신뢰성 있는 전달을 보장하기 위해 항상 RESET_STREAM_AT 프레임을 사용합니다; 자세한 내용은 Section 4.1Section 4.2 ([WEB-TRANSPORT-HTTP3]) 참고.

HTTP/3 프로토콜 동작 API 효과
세션 drained await wt.draining

기저 연결이 HTTP/2를 사용하는 경우, [WEB-TRANSPORT-HTTP2]의 다음 프로토콜 동작이 적용됩니다. HTTP/3와 달리, 스트림 에러 코드는 HTTP 에러 코드로 변환할 필요가 없습니다.

API 메서드 HTTP/2 프로토콜 동작
writable.abort(error) WT_RESET_STREAM을 error와 함께 전송
writable.close() WT_STREAM FIN 비트 설정하여 전송
writable.getWriter().write() WT_STREAM 전송
writable.getWriter().close() WT_STREAM FIN 비트 설정하여 전송
writable.getWriter().abort(error) WT_RESET_STREAM을 error와 함께 전송
readable.cancel(error) WT_STOP_SENDING을 error와 함께 전송
readable.getReader().cancel(error) WT_STOP_SENDING을 error와 함께 전송
wt.close(closeInfo) 세션 종료 (closeInfo 포함)
HTTP/2 프로토콜 동작 API 효과
error와 함께 WT_STOP_SENDING 수신 에러 발생 writable (streamErrorCode 포함)
WT_STREAM 수신 (await readable.getReader().read()).value
WT_STREAM FIN 비트 설정 수신 (await readable.getReader().read()).done
error와 함께 WT_RESET_STREAM 수신 에러 발생 readable (streamErrorCode 포함)
세션이 clean하게 종료됨 (closeInfo 포함)
(await wt.closed).closeInfo, 그리고 에러 발생 열린 스트림들
네트워크 오류
(await wt.closed) rejected, 그리고 에러 발생 열린 스트림들
세션 drained await wt.draining

14. 프라이버시 및 보안 고려사항

이 섹션은 비규범적입니다. 새로운 동작을 지정하지 않으며, 명세의 다른 부분에 이미 존재하는 정보를 요약합니다.

14.1. 통신의 기밀성

네트워크를 관찰할 수 있는 공격자는 통신이 이루어지고 있다는 사실을 숨길 수 없습니다. 이는 공개 정보로 간주되어야 합니다.

이 문서에서 설명하는 모든 전송 프로토콜은 TLS [RFC8446] 또는 의미적으로 동등한 프로토콜을 사용하므로, TLS의 모든 보안 속성(트래픽의 기밀성 및 무결성 포함)을 제공합니다. HTTP를 통한 WebTransport는 아웃바운드 HTTP 요청과 동일한 인증서 검증 메커니즘을 사용하므로, 원격 서버 인증을 위한 동일한 공개키 인프라에 의존합니다. WebTransport에서는 인증서 검증 오류가 치명적이며, 인증서 검증을 우회할 수 있는 중간 경유(interstitial)는 제공되지 않습니다.

14.2. 상태 지속성

WebTransport는 고유 식별자나 새로운 상태 지속 방법을 자체적으로 생성하지 않으며, 기존의 지속 상태를 서버에 자동으로 노출하지도 않습니다. 예를 들어, [WEB-TRANSPORT-HTTP3][WEB-TRANSPORT-HTTP2]는 쿠키를 전송하거나 HTTP 인증 또는 캐싱 무효화 메커니즘을 지원하지 않습니다. TLS를 사용하기 때문에 TLS 세션 티켓 등 TLS의 지속 상태는 상속받으며, 이는 수동적 네트워크 관찰자에게는 보이지 않지만 서버가 동일 클라이언트의 여러 연결을 연관시키는 데 사용할 수 있습니다.

14.3. 프로토콜 보안

WebTransport는 [WEB-TRANSPORT-OVERVIEW]에서 설명된 요구사항을 부과합니다. 예:

  1. 원격 서버가 WebTransport 프로토콜을 사용 중임을 인지하고, 사용에 동의하도록 보장합니다. [WEB-TRANSPORT-HTTP3]는 ALPN [RFC7301], HTTP/3 세팅, :protocol 의사 헤더 조합을 사용합니다. [WEB-TRANSPORT-HTTP2]도 ALPN, HTTP/2 세팅, :protocol 의사 헤더를 사용합니다.

  2. 서버가 자원을 시작한 트랜스포트 세션의 origin에 따라 연결을 필터링하도록 허용합니다. 세션 설정 요청의 Origin 헤더 필드가 이 정보를 전달합니다.

프로토콜 보안 관련 고려사항은 Security Considerations 섹션([WEB-TRANSPORT-HTTP3], [WEB-TRANSPORT-HTTP2])에 기술되어 있습니다.

네트워킹 API는 일반적으로 로컬 네트워크의 사용 가능한 호스트를 스캔하는 데 사용될 수 있으므로, 지문 채취(fingerprinting) 및 기타 공격에 활용될 수 있습니다. WebTransport는 WebSocket 방식을 따릅니다: 특정 연결 오류는 WebTransport 엔드포인트임이 확인될 때까지 반환되지 않습니다. 따라서 웹 애플리케이션은 존재하지 않는 엔드포인트와 Web에서 연결을 받아들이지 않는 엔드포인트를 구분할 수 없습니다.

14.4. 인증서 해시를 통한 인증

일반적으로, 유저 에이전트는 TLS 서버 인증서의 유효성을 URL의 서버 이름에 대해 검증함으로써 TLS 연결을 인증합니다 [RFC9525]. 이는 유저 에이전트가 유지하는 신뢰 앵커로 서버 인증서를 체인 연결하는 방식입니다; 신뢰 앵커는 인증서의 서버 이름을 인증합니다. 이 시스템을 Web PKI라 부릅니다.

이 API는 웹 애플리케이션이 서버 이름 대신 특정 서버 인증서로 인증된 원격 네트워크 엔드포인트에 연결할 수 있게 합니다. 이 메커니즘은 장기 인증서 취득이 어려운 엔드포인트(예: 단명 VM, 공개 라우팅이 안 되는 호스트)와의 연결을 가능하게 합니다. 이 메커니즘이 개별 연결에 대해 Web PKI 기반 인증을 대체하므로, 두 보안 특성을 비교해야 합니다.

원격 서버가 TLS 핸드셰이크에 성공하려면 인증서의 공개키에 해당하는 개인키를 반드시 소유해야 합니다. API는 인증서를 해시값으로 식별합니다. 해시 함수가 두 번째 프리이미지 저항성을 갖는 한만 안전합니다. 이 문서에서 정의된 함수는 SHA-256뿐이며, API는 여러 알고리즘-해시 쌍 지정으로 새로운 해시 함수를 도입할 수 있습니다.

Web PKI는 서버 이름에 대한 신뢰 체인을 구축하는 것 외에도 추가 보안 메커니즘을 제공합니다. 예를 들어, 인증서 폐기 처리가 있습니다. 인증서가 단명인 경우에는 불필요하지만, 그 외에는 인증서 해시가 제공되는 방식(예: HTTP 캐시 자원)이 중요합니다. 인증서가 손상으로 교체되었다면 캐시를 무효화해야 합니다. Web PKI는 취약한 키 생성 등 문제를 방지하기 위한 추가 기능도 제공합니다. 이 명세는 구체적 지침을 제공하지 않지만, 브라우저는 구현 정의에 따라 취약한 키 인증서를 거부할 수 있습니다.

Web PKI는 인증서의 만료 기간을 강제합니다. 이는 키 손상 범위를 제한하고, 서버 운영자가 키 교체를 지원/실행하도록 유도합니다. 이러한 이유로 WebTransport도 유사한 만료 기간을 부과합니다; 인증서는 단명 또는 단기 사용이 예상되므로, 만료 기간은 2주로 제한됩니다. 2주 제한은 키 손상 결과를 최소화하기 위해 가능한 한 낮게 설정하면서, 기기 간 시계 오차와 클라이언트-서버 간 인증서 동기화 비용을 낮추기 위한 균형입니다.

WebTransport API는 애플리케이션이 여러 인증서 해시를 한 번에 지정할 수 있게 하여, 새 인증서가 롤아웃되는 기간 동안 클라이언트가 여러 인증서를 허용할 수 있게 합니다.

WebRTC의 유사 메커니즘과 달리, WebTransport의 서버 인증서 해시 API는 클라이언트 인증 수단을 제공하지 않습니다; 클라이언트가 서버 인증서를 알고 있거나 접속 방법을 아는 것만으로는 충분하지 않습니다. 필요하다면 애플리케이션이 인증을 인밴드로 직접 처리해야 합니다.

14.5. 지문 채취 및 추적

이 API는 사이트가 네트워크 활동을 생성하고, 그 효과를 세밀하게 관찰할 수 있게 합니다. 이런 방식으로 얻은 정보는 식별 정보가 될 수 있습니다.

매우 유사한 네트워킹 기능이 다른 웹 플랫폼 API(예: fetch, [webrtc])에도 있으므로, WebTransport 추가로 인한 프라이버시 악영향은 최소입니다. 이 섹션의 고려사항은 다른 네트워킹 기능에도 똑같이 적용됩니다.

네트워크 특성 측정은 네트워크를 실제로 사용하고, 그 사용의 효과를 측정해야 하며, 이 둘 모두 이 API로 가능합니다. WebTransport는 사이트가 원하는 서버로 네트워크 활동을 생성하고 효과를 관찰할 수 있게 합니다. 네트워크 경로의 안정적 속성과 동적 사용 효과 모두 관찰이 가능합니다.

네트워크 정보는 서버에 직접 네트워킹 스택을 통해, 혹은 클라이언트의 데이터 소비/전송 속도, 또는 API에서 제공하는 통계 (§ 6.13 WebTransportConnectionStats Dictionary)로 제공됩니다. 따라서 사용자 에이전트의 정보 제한만으로 프라이버시 위험을 관리할 수 없습니다.

14.5.1. 정적 관찰

사이트는 사용자 에이전트와 선택한 서버 간의 네트워크 용량 또는 왕복 시간(RTT)을 관찰할 수 있습니다. 이 정보는 다른 추적 벡터와 결합되면 식별 정보가 될 수 있습니다. RTT는 여러 측정이 여러 관찰 지점에서 이루어질 경우, 사용자 에이전트의 물리적 위치도 일부 드러낼 수 있습니다.

네트워킹은 공유되지만, 네트워크 사용은 종종 산발적이기 때문에, 사이트는 종종 경쟁이 없거나 거의 없는 네트워크 경로의 용량과 RTT를 관찰할 수 있습니다. 이러한 특성은 네트워크 위치와 병목 위치가 고정된 사용자에게는 안정적입니다.

14.5.2. 공유 네트워킹

경쟁이 있는 링크는 사이트에 사이트 간 인식을 활성화할 기회를 제공합니다. 이는 무단 추적에 활용될 수 있습니다 [UNSANCTIONED-TRACKING]. 네트워크 용량은 한정된 공유 자원이므로, 사용자 에이전트가 여러 사이트에 동시에 접근하면 각 사이트에 제시되는 신원 간의 연결이 드러날 수 있습니다.

한 사이트의 네트워킹 기능 사용은 다른 사이트에서 사용할 수 있는 용량을 감소시키며, 이는 네트워킹 API를 통해 관찰될 수 있습니다. 네트워크 사용과 지표는 동적으로 변할 수 있으므로, 모든 변화가 실시간으로 관찰 가능합니다. 이를 통해 사이트는 서로 다른 사이트의 활동이 동일 사용자에서 비롯된 것임을 더욱 확신할 수 있습니다.

사용자 에이전트는 비활성 또는 포커스가 없는 사이트에 대해 통계 (§ 6.13 WebTransportConnectionStats Dictionary)와 같은 피드백 메커니즘 접근을 제한하거나 저하시킬 수 있습니다 (HTML § 6.6 포커스). 단, 서버가 네트워크 변화 관찰을 막을 수는 없습니다.

14.5.3. 풀링된 세션

공유 네트워킹 시나리오와 유사하게, 여러 세션이 하나의 연결에 풀링될 때, 한 세션의 정보가 다른 세션의 활동에 의해 영향을 받습니다. 한 세션은 다른 세션의 데이터 전송 속도 등 활동 정보를 추론할 수 있습니다.

공유 연결 사용만으로도 서버가 세션을 연관지을 수 있습니다. 네트워크 파티션 키를 사용하면, 공유 세션으로 인해 원치 않는 사이트 간 인식이 활성화되는 것을 방지할 수 있습니다.

15. 예시

15.1. 데이터그램 버퍼 전송

이 섹션은 비규범적입니다.

데이터그램 버퍼 전송은 datagramscreateWritable 메서드와, 결과 스트림의 writer를 사용하여 달성할 수 있습니다. 아래 예시에서는 트랜스포트가 전송 준비가 되었을 때만 데이터그램을 전송합니다.

async function sendDatagrams(url, datagrams) {
  const wt = new WebTransport(url);
  const writable = wt.datagrams.createWritable();
  const writer = writable.getWriter();
  for (const bytes of datagrams) {
    await writer.ready;
    writer.write(bytes).catch(() => {});
  }
  await writer.close();
}

15.2. 고정 간격으로 데이터그램 전송

이 섹션은 비규범적입니다.

트랜스포트가 전송 준비가 되었는지 여부와 상관없이 고정 간격으로 데이터그램을 전송하려면, datagramscreateWritable 메서드와 결과 스트림의 writer를 사용하되, ready 속성을 await하지 않으면 됩니다.

// 100ms마다 데이터그램 전송
async function sendFixedRate(url, createDatagram, ms = 100) {
  const wt = new WebTransport(url);
  const writable = wt.datagrams.createWritable();
  const writer = writable.getWriter();
  const bytes = createDatagram();
  setInterval(() => writer.write(bytes).catch(() => {}), ms);
}

15.3. 데이터그램 수신

이 섹션은 비규범적입니다.

데이터그램은 transport.datagrams.readable 속성을 읽어서 받을 수 있습니다. null 값은 패킷 처리가 충분히 빠르지 않음을 나타낼 수 있습니다.

async function receiveDatagrams(url) {
  const wt = new WebTransport(url);
  for await (const datagram of wt.datagrams.readable) {
    // 데이터그램 처리
  }
}

15.4. BYOB 리더로 데이터그램 수신

이 섹션은 비규범적입니다.

datagrams바이트 스트림이므로, BYOB 리더를 얻을 수 있습니다. 이를 통해 복사를 피하고 버퍼 할당을 더 정밀하게 제어할 수 있습니다. 이 예시는 64kB 메모리 버퍼로 데이터그램을 읽습니다.

const wt = new WebTransport(url);

for await (const datagram of wt.datagrams.readable) {
  const reader = datagram.getReader({ mode: "byob" });

  let array_buffer = new ArrayBuffer(65536);
  const buffer = await readInto(array_buffer);
}

async function readInto(buffer) {
  let offset = 0;

  while (offset < buffer.byteLength) {
    const {value: view, done} = await reader.read(
        new Uint8Array(buffer, offset, buffer.byteLength - offset));
    buffer = view.buffer;
    if (done) {
      break;
    }
    offset += view.byteLength;
  }

  return buffer;
}

15.5. 스트림 전송

이 섹션은 비규범적입니다.

데이터를 단방향 스트림으로 전송하려면, createUnidirectionalStream 함수와 결과 스트림의 writer를 사용합니다.

작성된 청크 경계는 수신 시 유지되지 않을 수 있으며, 바이트가 전송 중에 합쳐질 수 있습니다. 따라서 응용에서는 자체 프레이밍을 제공하는 것이 좋습니다.

async function sendData(url, ...data) {
  const wt = new WebTransport(url);
  const writable = await wt.createUnidirectionalStream();
  const writer = writable.getWriter();
  for (const bytes of data) {
    await writer.ready;
    writer.write(bytes).catch(() => {});
  }
  await writer.close();
}

Streams 명세는 write()의 promise를 await하지 않는 것 을 권장하지 않습니다.

인코딩은 ReadableStream에서 파이프를 통해서도 할 수 있습니다. 예를 들어 TextEncoderStream 을 사용할 수 있습니다.

async function sendText(url, readableStreamOfTextData) {
  const wt = new WebTransport(url);
  const writable = await wt.createUnidirectionalStream();
  await readableStreamOfTextData
    .pipeThrough(new TextEncoderStream("utf-8"))
    .pipeTo(writable);
}

15.6. 수신 스트림 받기

이 섹션은 비규범적입니다.

수신 스트림 읽기는 incomingUnidirectionalStreams 속성을 반복하고, 각 WebTransportReceiveStream 을 반복하여 청크를 소비하면 됩니다.

청크는 송신자가 아닌, 사용자 에이전트에 의해 결정됩니다.

async function receiveData(url, processTheData) {
  const wt = new WebTransport(url);
  for await (const readable of wt.incomingUnidirectionalStreams) {
    // 각각의 스트림을 IIFE로 소비, 스트림별 에러 보고
    ((async () => {
      try {
        for await (const bytes of readable) {
          processTheData(bytes);
        }
      } catch (e) {
        console.error(e);
      }
    })());
  }
}

디코딩은 새 WritableStream으로 파이프를 통해서도 할 수 있습니다. 예를 들어 TextDecoderStream 을 사용할 수 있습니다. 이 예시는 텍스트 출력이 interleave되지 않아야 한다고 가정하여, 한 번에 하나의 스트림만 읽습니다.

async function receiveText(url, createWritableStreamForTextData) {
  const wt = new WebTransport(url);
  for await (const readable of wt.incomingUnidirectionalStreams) {
    // 출력이 interleave되지 않도록 순차적으로 소비, 스트림별 에러 보고
    try {
      await readable
       .pipeThrough(new TextDecoderStream("utf-8"))
       .pipeTo(createWritableStreamForTextData());
    } catch (e) {
      console.error(e);
    }
  }
}

15.7. BYOB 리더로 스트림 수신

이 섹션은 비규범적입니다.

WebTransportReceiveStream바이트 스트림이므로, BYOB 리더를 얻을 수 있습니다. 이를 통해 복사를 피하고 버퍼 할당을 더 정밀하게 제어할 수 있습니다. 이 예시는 1024 바이트를 하나의 메모리 버퍼로 읽습니다.

const wt = new WebTransport(url);

const reader = wt.incomingUnidirectionalStreams.getReader();
const { value: recv_stream, done } = await reader.read();
const byob_reader = recv_stream.getReader({ mode: "byob" });

let array_buffer = new ArrayBuffer(1024);
const buffer = await readInto(array_buffer);

async function readInto(buffer) {
  let offset = 0;

  while (offset < buffer.byteLength) {
    const {value: view, done} = await reader.read(
        new Uint8Array(buffer, offset, buffer.byteLength - offset));
    buffer = view.buffer;
    if (done) {
      break;
    }
    offset += view.byteLength;
  }

  return buffer;
}

15.8. 트랜잭션성 청크 스트림 전송

이 섹션은 비규범적입니다.

단방향 스트림에서 트랜잭션 데이터 조각을, 흐름 제어로 블록되지 않고 전체 전송이 가능할 때만 보내려면, getWriter 함수와 결과 writer를 사용하면 됩니다.

async function sendTransactionalData(wt, bytes) {
  const writable = await wt.createUnidirectionalStream();
  const writer = writable.getWriter();
  await writer.ready;
  try {
    await writer.atomicWrite(bytes);
  } catch (e) {
    if (e.name != "AbortError") throw e;
    // 흐름 제어 블록 방지로 거절됨
    // 비원자적 쓰기가 pending이 아니라면 writable은 에러 상태가 되지 않음
  } finally {
    writer.releaseLock();
  }
}

15.9. 서버 인증서 해시 사용

이 섹션은 비규범적입니다.

WebTransport 세션은 클라이언트의 기본 신뢰 평가 대신, 서버에 제공된 인증서의 해시값을 검사하여 신뢰성을 평가하도록 할 수 있습니다. 아래 예시에서 hashValueBufferSource 타입으로, 서버 인증서의 SHA-256 해시를 담고 있으며, 기저 연결이 이를 유효로 간주해야 합니다.

const wt = new WebTransport(url, {
  serverCertificateHashes: [
    {
      algorithm: "sha-256",
      value: hashValue,
    }
  ]
});
await wt.ready;

15.10. 전체 예시

이 섹션은 비규범적입니다.

이 예시는 closed, ready promise 활용, 클라이언트/서버의 단방향 및 양방향 스트림 열기, 데이터그램 송수신 등을 보여줍니다.

transport의 writable 속성은 datagrams 에 과거 존재했으나, 아래처럼 간단히 polyfill할 수 있습니다:
wt.datagrams.writable ||= wt.datagrams.createWritable();
// 페이지의 이벤트 로그에 항목을 추가하며, 선택적으로 지정된 CSS 클래스를 적용함.
// CSS 클래스.

let wt, streamNumber, datagramWriter;

connect.onclick = async () => {
  try {
    const url = document.getElementById('url').value;

    wt = new WebTransport(url);
    wt.datagrams.writable ||= wt.datagrams.createWritable();
    addToEventLog('연결 시작 중...');
    await wt.ready;
    addToEventLog(`${(wt.reliability == "reliable-only")? "TCP" : "UDP"} ` +
                  `연결 준비 완료.`);
    wt.closed
      .then(() => addToEventLog('연결 정상적으로 종료됨.'))
      .catch(() => addToEventLog('연결 비정상적으로 종료됨.', 'error'));

    streamNumber = 1;
    datagramWriter = wt.datagrams.writable.getWriter();

    readDatagrams();
    acceptUnidirectionalStreams();
    document.forms.sending.elements.send.disabled = false;
    document.getElementById('connect').disabled = true;
  } catch (e) {
    addToEventLog(`연결 실패. ${e}`, 'error');
  }
}

sendData.onclick = async () => {
  const form = document.forms.sending.elements;
  const data = sending.data.value;
  const bytes = new TextEncoder('utf-8').encode(data);
  try {
    switch (form.sendtype.value) {
      case 'datagram': {
        await datagramWriter.ready;
        datagramWriter.write(bytes).catch(() => {});
        addToEventLog(`데이터그램 전송: ${data}`);
        break;
      }
      case 'unidi': {
        const writable = await wt.createUnidirectionalStream();
        const writer = writable.getWriter();
        writer.write(bytes).catch(() => {});
        await writer.close();
        addToEventLog(`단방향 스트림으로 데이터 전송: ${data}`);
        break;
      }
      case 'bidi': {
        const duplexStream = await wt.createBidirectionalStream();
        const n = streamNumber++;
        readFromIncomingStream(duplexStream.readable, n);

        const writer = duplexStream.writable.getWriter();
        writer.write(bytes).catch(() => {});
        await writer.close();
        addToEventLog(`양방향 스트림 #${n}에 데이터 전송: ${data}`);
        break;
      }
    }
  } catch (e) {
    addToEventLog(`데이터 전송 중 오류: ${e}`, 'error');
  }
}

// 데이터그램을 EOF까지 이벤트 로그로 읽음
async function readDatagrams() {
  try {
    const decoder = new TextDecoderStream('utf-8');

    for await (const data of wt.datagrams.readable.pipeThrough(decoder)) {
      addToEventLog(`데이터그램 수신: ${data}`);
    }
    addToEventLog('데이터그램 읽기 완료!');
  } catch (e) {
    addToEventLog(`데이터그램 읽기 중 오류: ${e}`, 'error');
  }
}

async function acceptUnidirectionalStreams() {
  try {
    for await (const readable of wt.incomingUnidirectionalStreams) {
      const number = streamNumber++;
      addToEventLog(`새 단방향 스트림 #${number}`);
      readFromIncomingStream(readable, number);
    }
    addToEventLog('단방향 스트림 수락 완료!');
  } catch (e) {
    addToEventLog(`스트림 수락 중 오류 ${e}`, 'error');
  }
}

async function readFromIncomingStream(readable, number) {
  try {
    const decoder = new TextDecoderStream('utf-8');
    for await (const data of readable.pipeThrough(decoder)) {
      addToEventLog(`스트림 #${number}에서 데이터 수신: ${data}`);
    }
    addToEventLog(`스트림 #${number} 종료됨`);
  } catch (e) {
    addToEventLog(`스트림 #${number}에서 읽기 중 오류: ${e}`, 'error');
    addToEventLog(`    ${e.message}`);
  }
}

function addToEventLog(text, severity = 'info') {
  const log = document.getElementById('event-log');
  const previous = log.lastElementChild;
  const entry = document.createElement('li');
  entry.innerText = text;
  entry.className = `log-${severity}`;
  log.appendChild(entry);

  // 이전 로그 항목이 보이면, 새 요소로 스크롤
  if (previous &&
      previous.getBoundingClientRect().top < log.getBoundingClientRect().bottom) {
    entry.scrollIntoView();
  }
}

16. 감사의 글

편집자들은 워킹 그룹 의장들과 팀 연락 담당자인 Jan-Ivar Bruaroey, Will Law, Yves Lafon에게 그들의 지원에 감사의 뜻을 전합니다.

WebTransport 인터페이스는 QuicTransport 인터페이스를 기반으로 하며, 이는 W3C ORTC CG에서 처음 기술되었습니다. 이 명세서에 맞게 적용되었습니다.

색인

이 명세서에서 정의된 용어

참조로 정의된 용어

참고문헌

규범적 참고문헌

[CSP3]
Mike West; Antonio Sartori. 콘텐츠 보안 정책 3단계(Content Security Policy Level 3). 2025년 6월 30일. WD. URL: https://www.w3.org/TR/CSP3/
[DOM]
Anne van Kesteren. DOM 표준(DOM Standard). 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT-6.0]
Allen Wirfs-Brock. ECMA-262 6판, ECMAScript 2015 언어 명세(ECMA-262 6th Edition, The ECMAScript 2015 Language Specification). 2015년 6월. 표준. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[ENCODING]
Anne van Kesteren. 인코딩 표준(Encoding Standard). 현행 표준. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 표준(Fetch Standard). 현행 표준. URL: https://fetch.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. 고해상도 시간(High Resolution Time). 2024년 11월 7일. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML 표준(HTML Standard). 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준(Infra Standard). 현행 표준. URL: https://infra.spec.whatwg.org/
[QUIC]
Jana Iyengar; Martin Thomson. QUIC: UDP 기반 다중화 및 보안 전송(QUIC: A UDP-Based Multiplexed and Secure Transport). 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9000
[QUIC-DATAGRAM]
Tommy Pauly; Eric Kinnear; David Schinazi. QUIC의 신뢰성 없는 데이터그램 확장(An Unreliable Datagram Extension to QUIC). 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9221
[RFC2119]
S. Bradner. RFC에서 요구 수준 표시를 위한 키워드(Key words for use in RFCs to Indicate Requirement Levels). 1997년 3월. 현재 최선의 관행. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3279]
L. Bassham; W. Polk; R. Housley. 인터넷 X.509 PKI 인증서 및 CRL 프로파일의 알고리즘 및 식별자(Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile). 2002년 4월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc3279
[RFC5280]
D. Cooper; et al. 인터넷 X.509 PKI 인증서 및 CRL 프로파일(Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile). 2008년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5280
[RFC8174]
B. Leiba. RFC 2119 키워드의 대소문자 모호성(Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words). 2017년 5월. 현재 최선의 관행. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8422]
Y. Nir; S. Josefsson; M. Pegourie-Gonnard. ECC 암호군: TLS 1.2 및 이전 버전(Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier). 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8422
[RFC9002]
J. Iyengar, Ed.; I. Swett, Ed.. QUIC 손실 감지 및 혼잡 제어(QUIC Loss Detection and Congestion Control). 2021년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9002
[RFC9525]
P. Saint-Andre; R. Salz. TLS의 서비스 식별(Service Identity in TLS). 2023년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9525
[STREAMS]
Adam Rice; et al. 스트림 표준(Streams Standard). 현행 표준. URL: https://streams.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 표준(URL Standard). 현행 표준. URL: https://url.spec.whatwg.org/
[WEB-TRANSPORT-HTTP2]
Alan Frindell; et al. HTTP/2 기반 WebTransport(WebTransport over HTTP/2). 인터넷-드래프트. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http2
[WEB-TRANSPORT-HTTP3]
Alan Frindell; Eric Kinnear; Victor Vasiliev. HTTP/3 기반 WebTransport(WebTransport over HTTP/3). 인터넷-드래프트. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3
[WEB-TRANSPORT-OVERVIEW]
Victor Vasiliev. WebTransport 프로토콜 프레임워크(WebTransport Protocol Framework). 인터넷-드래프트. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-overview
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준(Web IDL Standard). 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBTRANSPORT]
Nidhi Jaju; Victor Vasiliev. WebTransport. 2025년 2월 12일. WD. URL: https://www.w3.org/TR/webtransport/

참고용 참고문헌

[RELIABLE-RESET]
Marten Seemann; 奥一穂. 부분 전송이 포함된 QUIC 스트림 리셋(QUIC Stream Resets with Partial Delivery). 인터넷-드래프트. URL: https://datatracker.ietf.org/doc/html/draft-ietf-quic-reliable-stream-reset
[RFC7301]
S. Friedl; et al. TLS 애플리케이션-계층 프로토콜 협상 확장(Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension). 2014년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7301
[RFC8446]
E. Rescorla. TLS 프로토콜 버전 1.3(The Transport Layer Security (TLS) Protocol Version 1.3). 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8446
[RFC9308]
M. Kühlewind; B. Trammell. QUIC 전송 프로토콜의 적용(Applicability of the QUIC Transport Protocol). 2022년 9월. 정보성 문서. URL: https://www.rfc-editor.org/rfc/rfc9308
[UNSANCTIONED-TRACKING]
Mark Nottingham. 무단 웹 추적(Unsanctioned Web Tracking). 2015년 7월 17일. TAG Finding. URL: https://www.w3.org/2001/tag/doc/unsanctioned-tracking/
[WEBRTC]
Cullen Jennings; et al. 브라우저 실시간 통신(WebRTC: Real-Time Communication in Browsers). 2025년 3월 13일. REC. URL: https://www.w3.org/TR/webrtc/

IDL 색인

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportDatagramsWritable : WritableStream {
  attribute WebTransportSendGroup? sendGroup;
  attribute long long sendOrder;
};

[Exposed=(Window,Worker), SecureContext]
interface WebTransportDatagramDuplexStream {
  WebTransportDatagramsWritable createWritable(
      optional WebTransportSendOptions options = {});
  readonly attribute ReadableStream readable;

  readonly attribute unsigned long maxDatagramSize;
  attribute unrestricted double? incomingMaxAge;
  attribute unrestricted double? outgoingMaxAge;
  attribute unrestricted double incomingHighWaterMark;
  attribute unrestricted double outgoingHighWaterMark;
};

[Exposed=(Window,Worker), SecureContext]
interface WebTransport {
  constructor(USVString url, optional WebTransportOptions options = {});

  Promise<WebTransportConnectionStats> getStats();
  [NewObject] Promise<ArrayBuffer> exportKeyingMaterial(BufferSource label, optional BufferSource context);
  readonly attribute Promise<undefined> ready;
  readonly attribute WebTransportReliabilityMode reliability;
  readonly attribute WebTransportCongestionControl congestionControl;
  [EnforceRange] attribute unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams;
  [EnforceRange] attribute unsigned short? anticipatedConcurrentIncomingBidirectionalStreams;
  readonly attribute DOMString protocol;

  readonly attribute Promise<WebTransportCloseInfo> closed;
  readonly attribute Promise<undefined> draining;
  undefined close(optional WebTransportCloseInfo closeInfo = {});

  readonly attribute WebTransportDatagramDuplexStream datagrams;

  Promise<WebTransportBidirectionalStream> createBidirectionalStream(
      optional WebTransportSendStreamOptions options = {});
  /* a ReadableStream of WebTransportBidirectionalStream objects */
  readonly attribute ReadableStream incomingBidirectionalStreams;

  Promise<WebTransportSendStream> createUnidirectionalStream(
      optional WebTransportSendStreamOptions options = {});
  /* a ReadableStream of WebTransportReceiveStream objects */
  readonly attribute ReadableStream incomingUnidirectionalStreams;
  WebTransportSendGroup createSendGroup();

  static readonly attribute boolean supportsReliableOnly;
};

enum WebTransportReliabilityMode {
  "pending",
  "reliable-only",
  "supports-unreliable",
};

dictionary WebTransportHash {
  DOMString algorithm;
  BufferSource value;
};

dictionary WebTransportOptions {
  boolean allowPooling = false;
  boolean requireUnreliable = false;
  sequence<WebTransportHash> serverCertificateHashes;
  WebTransportCongestionControl congestionControl = "default";
  [EnforceRange] unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams = null;
  [EnforceRange] unsigned short? anticipatedConcurrentIncomingBidirectionalStreams = null;
  sequence<DOMString> protocols = [];
};

enum WebTransportCongestionControl {
  "default",
  "throughput",
  "low-latency",
};

dictionary WebTransportCloseInfo {
  unsigned long closeCode = 0;
  USVString reason = "";
};

dictionary WebTransportSendOptions {
  WebTransportSendGroup? sendGroup = null;
  long long sendOrder = 0;
};

dictionary WebTransportSendStreamOptions : WebTransportSendOptions {
  boolean waitUntilAvailable = false;
};

dictionary WebTransportConnectionStats {
  unsigned long long bytesSent = 0;
  unsigned long long packetsSent = 0;
  unsigned long long bytesLost = 0;
  unsigned long long packetsLost = 0;
  unsigned long long bytesReceived = 0;
  unsigned long long packetsReceived = 0;
  required DOMHighResTimeStamp smoothedRtt;
  required DOMHighResTimeStamp rttVariation;
  required DOMHighResTimeStamp minRtt;
  required WebTransportDatagramStats datagrams;
  unsigned long long? estimatedSendRate = null;
  boolean atSendCapacity = false;
};

dictionary WebTransportDatagramStats {
  unsigned long long droppedIncoming = 0;
  unsigned long long expiredIncoming = 0;
  unsigned long long expiredOutgoing = 0;
  unsigned long long lostOutgoing = 0;
};

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportSendStream : WritableStream {
  attribute WebTransportSendGroup? sendGroup;
  attribute long long sendOrder;
  Promise<WebTransportSendStreamStats> getStats();
  WebTransportWriter getWriter();
};

dictionary WebTransportSendStreamStats {
  unsigned long long bytesWritten = 0;
  unsigned long long bytesSent = 0;
  unsigned long long bytesAcknowledged = 0;
};

[Exposed=(Window,Worker), SecureContext]
interface WebTransportSendGroup {
  Promise<WebTransportSendStreamStats> getStats();
};

[Exposed=(Window,Worker), SecureContext, Transferable]
interface WebTransportReceiveStream : ReadableStream {
  Promise<WebTransportReceiveStreamStats> getStats();
};

dictionary WebTransportReceiveStreamStats {
  unsigned long long bytesReceived = 0;
  unsigned long long bytesRead = 0;
};

[Exposed=(Window,Worker), SecureContext]
interface WebTransportBidirectionalStream {
  readonly attribute WebTransportReceiveStream readable;
  readonly attribute WebTransportSendStream writable;
};

[Exposed=*, SecureContext]
interface WebTransportWriter : WritableStreamDefaultWriter {
  Promise<undefined> atomicWrite(optional any chunk);
  undefined commit();
};

[Exposed=(Window,Worker), Serializable, SecureContext]
interface WebTransportError : DOMException {
  constructor(optional DOMString message = "", optional WebTransportErrorOptions options = {});

  readonly attribute WebTransportErrorSource source;
  readonly attribute unsigned long? streamErrorCode;
};

dictionary WebTransportErrorOptions {
  WebTransportErrorSource source = "stream";
  [Clamp] unsigned long? streamErrorCode = null;
};

enum WebTransportErrorSource {
  "stream",
  "session",
};

이슈 색인

이것은 워커에서도 처리되어야 합니다. 참고: #127whatwg/html#6731.

이 구성 옵션은 저지연 최적화 혼잡 제어 알고리즘이 브라우저에 구현되지 않았기 때문에 기능 위험(atrisk)으로 간주됩니다. 작성 시점 기준입니다.