WebTransport

W3C 작업 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-webtransport-20260706/
최신 공개 버전:
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)

요약

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

이 문서의 상태

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

이 문서는 WebTransport 워킹 그룹에서 Recommendation track을 사용해 워킹 드래프트로 발행되었습니다. 이 문서는 W3C 권고안이 되는 것을 목표로 합니다.

이 문서에 대한 피드백과 의견을 환영합니다. 이슈를 등록 하거나, 이 문서의 GitHub 저장소를 이용해 주세요.

워킹 드래프트로 발행되었다고 해서 W3C 및 회원의 승인이나 지지를 의미하지는 않습니다. 이 문서는 초안이며 언제든 업데이트, 교체 또는 다른 문서에 의해 폐기될 수 있습니다. 이 문서를 진행 중인 작업 외의 용도로 인용하는 것은 적절하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 그룹의 산출물과 관련하여 이루어진 공개된 특허 리스트를 관리합니다. 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 어떤 개인이 특정 특허가 필수 청구항을 포함한다고 생각하는 경우, W3C 특허 정책 6항에 따라 그 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

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

이 명세는 [WEB-TRANSPORT-OVERVIEW]를 사용하여 서버로 데이터를 보내고 받을 수 있습니다. 이는 WebSocket과 유사하게 사용할 수 있지만, 다중 스트림, 단방향 스트림, 순서가 뒤바뀐 전달, 그리고 신뢰성 있는 전송과 비신뢰성 전송을 모두 지원합니다.

참고: 이 명세에서 제공하는 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 세션 session드레이닝(draining) 상태이며, CONNECT 스트림이 서버에 의해 정상적으로 닫히도록 요청받았을 때, [WEB-TRANSPORT-OVERVIEW] 섹션 4.1에 설명되어 있습니다.

WebTransport 세션 session을 선택적 정수 code와 선택적 바이트 시퀀스 reason과 함께 종료하기(terminate) 위해서는, [WEB-TRANSPORT-OVERVIEW] 섹션 4.1을 따릅니다.

WebTransport 세션 session이 종료되었다(terminated)고 하며, 선택적으로 정수 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 아니오
수신 중단 WebTransport 스트림에서 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
송신 중단 WebTransport 스트림에서 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오

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

이벤트 정의 수신 단방향 송신 단방향 양방향
수신 중단됨 [WEB-TRANSPORT-OVERVIEW] 섹션 4.3 아니오
송신 중단됨 [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]] 내보내는 데이터그램, 타임스탬프 및 데이터그램이 전송되거나 폐기될 때 resolve되는 promise의 튜플 큐
[[Transport]] WebTransport를 소유하는 WebTransportDatagramsWritable
[[SendGroup]] 옵션의 WebTransportSendGroup 또는 null
[[SendOrder]] 옵션 전송 순서 번호, 기본값 0
생성WebTransportDatagramsWritable 을 주어진 WebTransport transportsendGroup, 그리고 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거부된 promise를 반환한다.

  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.[[OutgoingMaxBufferedDatagrams]]보다 작으면, 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합니다.

User agent는 WebTransport 객체의 [[State]] 값이 "connecting" 또는 "connected"일 때, 관련된 sendDatagrams 알고리즘을 send-order rules에 의해 결정된 일부 WebTransportDatagramsWritable 객체 집합에 대해 실행해야 한다. 알고리즘이 진행할 수 있을 때, 가능한 한 빨리 실행하는 것이 좋다.

참고: 전송의 [[State]]"connecting"일 때에도 datagram을 기록하는 것이 허용된다. datagram은 [[OutgoingDatagramsQueue]] 에 저장되며, "connected" 상태와 동일하게 discard될 수 있다. 전송의 [[State]]"connected"로 변경되면 대기 중인 datagram의 전송이 시작된다.

send-order rules 는 대체로 전송이 기존에 대기 중인 stream과 datagram의 전송, 그리고 앞으로 대기될 stream과 datagram의 전송과 섞여 진행될 수 있다는 규칙이다. 단, 다음 조건에서는 전송이 지연되어야 한다: 동일한 [[SendGroup]] 및 더 높은 [[SendOrder]] 값을 갖고, 에러 상태가 아니며 flow control로 차단되지 않은 stream과 datagram의 모든 바이트가 전송될 때까지는 대기하여야 한다.

참고: 기본 null sendGroup 역시 유효한 sendGroup이다.

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 unsigned long incomingMaxBufferedDatagrams;
  attribute unsigned long outgoingMaxBufferedDatagrams;
};

5.1. 내부 슬롯

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

내부 슬롯 설명 (비규범적)
[[Transport]] WebTransport 가 이 WebTransportDatagramDuplexStream을 소유함.
[[Readable]] 수신 datagram을 위한 ReadableStream.
[[ReadableType]] 수신 datagram에 사용되는 ReadableStreamType.
[[Writables]] 정렬된 집합WebTransportDatagramsWritable 스트림, 초기 값은 비어 있음.
[[IncomingDatagramsQueue]] 수신 datagram과 타임스탬프의 쌍을 담은 큐.
[[IncomingDatagramsPullPromise]] pullDatagrams에 의해 설정되는 promise. 수신 datagram을 기다림.
[[IncomingMaxBufferedDatagrams]] unsigned long 값으로, 수신 큐의 datagram 개수를 나타냄. 그 값을 초과하면 datagram이 큐 머리에서 버려짐.
[[IncomingDatagramsExpirationDuration]] unrestricted double 값으로, 수신 datagram의 만료 기간(밀리초)을 나타내며 또는 null.
[[OutgoingMaxBufferedDatagrams]] unsigned long 값으로, 기본 sink의 송신 큐의 datagram 개수를 나타냄. 그 값을 초과하면 backpressure가 발생함.
[[OutgoingDatagramsExpirationDuration]] unrestricted double 값으로, 송신 datagram의 만료 기간(밀리초)을 나타내며 또는 null.
[[OutgoingMaxDatagramSize]] 송신 datagram의 최대 크기를 나타내는 정수값.
최대 datagram 크기는 사용되는 프로토콜에 따라 달라집니다. HTTP/3의 경우 [WEB-TRANSPORT-HTTP3]에서는 값이 경로 MTU의 추정치와 관련되어 있습니다. 구현별로 오버헤드를 고려하고 값을 줄입니다. HTTP/2의 경우 [WEB-TRANSPORT-HTTP2]에서는 동등한 제한이 없습니다.

datagram 처리에는 일반적으로 전체 datagram을 메모리에 보관해야 하므로, 구현에서는 크기 제한이 있습니다. 미래의 프로토콜 확장은 모든 프로토콜 변형에 대해 이러한 크기 제한의 신호 기능을 가능하게 할 수 있습니다.

사용자 에이전트는 [[OutgoingMaxDatagramSize]]WebTransport 객체의 [[State]]"connecting" 또는 "connected" 일 때 갱신할 수 있음.

WebTransportDatagramDuplexStream 을 생성하려면, WebTransportDatagramDuplexStreamWebTransport transport, readable, readableType이 주어졌을 때 아래 절차를 수행한다.
  1. stream새로운 WebTransportDatagramDuplexStream 인스턴스로 만드는데, 아래와 같이 설정한다:

    [[Transport]]

    transport

    [[Readable]]

    readable

    [[ReadableType]]

    readableType

    [[Writables]]

    정렬된 집합.

    [[IncomingDatagramsQueue]]

    빈 큐

    [[IncomingDatagramsPullPromise]]

    null

    [[IncomingMaxBufferedDatagrams]]

    구현 정의값

    [[IncomingDatagramsExpirationDuration]]

    null

    [[OutgoingMaxBufferedDatagrams]]

    구현 정의값

    이 구현 정의 값은 전송 데이터의 시의성과 성능을 손상시키지 않으면서, 적절한 처리량을 확보할 수 있도록 튜닝되어야 한다.

    [[OutgoingDatagramsExpirationDuration]]

    null

    [[OutgoingMaxDatagramSize]]

    구현 정의 정수값

  2. stream을 반환한다.

5.2. 메서드

createWritable(options)

WebTransportDatagramsWritable를 생성한다. 호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis와 연결된 WebTransport 객체로 둔다.

  2. sendGroupoptionssendGroup으로 둔다.

  3. sendGroup이 null이 아니고, sendGroup.[[Transport]]this.[[Transport]]가 아니면, throw a TypeError한다.

  4. transport.[[State]]"closed" 또는 "failed"이면, throw an InvalidStateError한다.

  5. sendOrderoptionssendOrder로 둔다.

  6. transport, sendGroupsendOrderWebTransportDatagramsWritable생성한 결과를 반환한다.

5.3. 속성

readable, 타입 ReadableStream, 읽기 전용

getter 단계는 다음과 같다:

  1. this.[[Readable]]를 반환한다.

incomingMaxAge, 타입 unrestricted double, nullable

getter 단계는 다음과 같다:

  1. this.[[IncomingDatagramsExpirationDuration]]를 반환한다.

setter 단계는 value가 주어졌을 때 다음과 같다:

  1. value가 음수이거나 NaN이면, throw하고 RangeError를 발생시킨다.

  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이면, throw하고 RangeError를 발생시킨다.

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

  3. this.[[OutgoingDatagramsExpirationDuration]]value로 설정한다.

incomingMaxBufferedDatagrams, 타입 unsigned long

getter 단계는 다음과 같다:

  1. this.[[IncomingMaxBufferedDatagrams]]를 반환한다.

setter 단계는 value가 주어졌을 때 다음과 같다:

  1. value1보다 작으면, value1로 설정한다.

  2. this.[[IncomingMaxBufferedDatagrams]]value로 설정한다.

outgoingMaxBufferedDatagrams, 타입 unsigned long

getter 단계는 다음과 같다:

  1. this.[[OutgoingMaxBufferedDatagrams]]를 반환한다.

setter 단계는 value가 주어졌을 때 다음과 같다:

  1. value1보다 작으면, value1로 설정한다.

  2. this.[[OutgoingMaxBufferedDatagrams]]value로 설정한다.

5.4. 절차

pullDatagrams를 하려면, WebTransport 객체 transport가 주어졌을 때 다음 단계를 실행한다:

  1. datagramstransport.[[Datagrams]]로 설정한다.

  2. 단언: datagrams.[[IncomingDatagramsPullPromise]] 가 null이다.

  3. queuedatagrams.[[IncomingDatagramsQueue]]로 설정한다.

  4. 만약 queue가 비어 있다면:

    1. datagrams.[[IncomingDatagramsPullPromise]] 에 새로운 promise를 할당한다.

    2. datagrams.[[IncomingDatagramsPullPromise]] 를 반환한다.

  5. datagramtimestampqueue에서 디큐(queue-dequeuing) 한 결과로 설정한다.

  6. 만약 datagrams.[[ReadableType]]"bytes"라면:

    1. datagrams.[[Readable]]現在の BYOB リクエストビュー が null でない場合、次を実行する:

      1. viewdatagrams.[[Readable]]現在の BYOB リクエスト ビュー とする。

      2. viewバイト長datagram のサイズより小さい場合、 RangeError却下された promiseを返す。

      3. elementSize を、view.[[TypedArrayName]] について 型付き配列コンストラクター表 で指定される要素サイズとする。 view に [[TypedArrayName]] 内部スロットがない場合 (すなわち、それが DataView である場合)、 elementSize を 0 とする。

      4. elementSize が 1 でない場合、TypeError却下された promiseを返す。

    2. バイトからプルして、datagramdatagrams.[[Readable]] に取り込む。

  7. 그 외의 경우:

    1. chunkUint8Array 객체로 새로 생성하여 datagram을 나타내도록 한다.

    2. Enqueue(엔큐) chunktransport.[[Datagrams]].[[Readable]]에 추가한다.

  8. undefined로 resolve된 promise를 반환한다.

receiveDatagrams 알고리즘은, WebTransport 객체 transport를 받아 다음 단계를 수행한다:

  1. timestamp를 현재 시점의 타임스탬프로 설정한다.

  2. queuedatagrams.[[IncomingDatagramsQueue]]로 설정한다.

  3. durationdatagrams.[[IncomingDatagramsExpirationDuration]]로 설정한다.

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

  5. sessiontransport.[[Session]]로 설정한다.

  6. session받을 수 있는 datagram이 있다면 반복한다:

    1. datagramsession에서 datagram 수신의 결과로 얻는다.

    2. timestamp를 현재 시점의 타임스탬프로 설정한다.

    3. chunkdatagramtimestamp의 쌍으로 만든다.

    4. Enqueue chunkqueue에 넣는다.

  7. toBeRemovedqueue 길이에서 datagrams.[[IncomingMaxBufferedDatagrams]] 값을 빼서 계산한다.

  8. toBeRemoved가 양수면, queue에서 dequeuetoBeRemoved번(내림 처리) 반복한다.

  9. queue가 비어 있지 않은 동안 반복한다:

    1. bytestimestampqueue의 첫 번째 요소에서 얻는다.

    2. timestamp로부터 duration 밀리초가 지나면 queue에서 dequeue한다.

    3. 그 외에는 break로 반복문을 종료한다.

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

    1. bytestimestampqueue에서 dequeue한다.

    2. promisedatagrams.[[IncomingDatagramsPullPromise]]가 가리키는 값으로 설정한다.

    3. datagrams.[[IncomingDatagramsPullPromise]] 값을 null로 설정한다.

    4. 네트워크 작업 큐에 추가 알고리즘을 transport와 함께 실행하고 아래 단계를 수행한다:

      1. chunkUint8Array 객체로 새로 만들고 bytes를 나타내도록 한다.

      2. Enqueue chunkdatagrams.[[Readable]]에 넣는다.

      3. promise 해제promise와 undefined로 수행한다.

User agent는 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<Uint8Array> exportKeyingMaterial(BufferSource label, BufferSource context, unsigned long outputLength);
  readonly attribute Promise<undefined> ready;
  readonly attribute WebTransportReliabilityMode reliability;
  readonly attribute WebTransportCongestionControl congestionControl;
  attribute [EnforceRange] unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams;
  attribute [EnforceRange] unsigned short? anticipatedConcurrentIncomingBidirectionalStreams;
  [SameObject] readonly attribute Headers? responseHeaders;
  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 session설정됨 상태가 되면 fulfill되고, 설정 과정 이 실패하면 reject되는 promise.
[[Reliability]] 첫 홉이 신뢰성 없는(UDP) 전송을 지원하는지, 아니면 신뢰성 있는(TCP fallback) 전송만 가능한지 나타내는 WebTransportReliabilityMode. 연결이 설정되기 전에는 "pending" 상태.
[[CongestionControl]] 애플리케이션이 처리량 또는 저지연 최적화 혼잡 제어 알고리즘을 요청했고, user agent가 이를 만족시켰는지 나타내는 WebTransportCongestionControl. 또는 "default".
[[AnticipatedConcurrentIncomingUnidirectionalStreams]] 애플리케이션이 서버가 생성할 것으로 예상하는 동시에 열린 수신 단방향 스트림 개수 또는 null.
[[AnticipatedConcurrentIncomingBidirectionalStreams]] 애플리케이션이 서버가 생성할 것으로 예상하는 양방향 스트림의 개수 또는 null.
[[ResponseHeaders]] Headers 객체 또는 null. 초기 값은 null.
[[Protocol]] 서버가 선택한 애플리케이션 레벨 프로토콜을 나타내는 문자열(있다면). 초기 값은 빈 문자열.
[[Closed]] 연관된 WebTransport 객체가 정상적으로 종료되면 fulfill, 비정상 또는 초기화 실패시 reject되는 promise.
[[Draining]] 연관된 WebTransport sessiondraining 상태가 되면 fulfill되는 promise.
[[Datagrams]] WebTransportDatagramDuplexStream 객체.
[[Session]] WebTransport 객체에 대한 WebTransport session 또는 null.
[[NewConnection]] "no" 또는 "yes-and-dedicated".
[[RequireUnreliable]] UDP가 필수인지 여부를 나타내는 boolean 값.

6.2. 생성자

WebTransport() 생성자가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. baseURLthis관련 설정 객체API 기준 URL로 둔다.

  2. urlbaseURLurl파싱한 결과인 URL 레코드로 둔다.

  3. url이 실패이면, throw하여 SyntaxError 예외를 발생시킨다.

  4. url스킴https가 아니면, throw하여 SyntaxError 예외를 발생시킨다.

  5. url프래그먼트가 null이 아니면, throw하여 SyntaxError 예외를 발생시킨다.

  6. newConnectionoptionsallowPooling이 true이면 "no"로, 그렇지 않으면 "yes-and-dedicated"로 둔다.

  7. serverCertificateHashesoptionsserverCertificateHashes로 둔다.

  8. newConnection이 "no"이고 serverCertificateHashes비어 있지 않으면, throw하여 NotSupportedError 예외를 발생시킨다.

  9. requireUnreliableoptionsrequireUnreliable로 둔다.

  10. congestionControloptionscongestionControl로 둔다.

  11. congestionControl"default"가 아니고, 사용자 에이전트가 [RFC9002] Section 7에서 허용한 대로 congestionControl에 최적화된 혼잡 제어 알고리즘을 지원하지 않는 경우, congestionControl"default"로 설정한다.

  12. protocolsoptionsprotocols로 둔다.

  13. protocols 안의 값 중 어느 것이라도 한 번 넘게 나타나거나, WebTransport 프로토콜에서 정의한 협상된 애플리케이션 프로토콜의 값을 구성하는 요소에 대한 요구 사항과 일치하지 않거나, 동형 인코딩된 길이가 0이거나 512를 초과하면, throw하여 SyntaxError 예외를 발생시킨다. [WEB-TRANSPORT-OVERVIEW] Section 3.1.

  14. anticipatedConcurrentIncomingUnidirectionalStreamsoptionsanticipatedConcurrentIncomingUnidirectionalStreams로 둔다.

  15. anticipatedConcurrentIncomingBidirectionalStreamsoptionsanticipatedConcurrentIncomingBidirectionalStreams로 둔다.

  16. datagramsReadableTypeoptionsdatagramsReadableType으로 둔다.

  17. incomingDatagrams ReadableStream으로 둔다.

  18. transport를 다음을 가진, 새로 구성된 WebTransport 객체로 둔다:

    [[SendStreams]]

    순서 있는 집합

    [[ReceiveStreams]]

    순서 있는 집합

    [[IncomingBidirectionalStreams]]

    ReadableStream

    [[IncomingUnidirectionalStreams]]

    ReadableStream

    [[State]]

    "connecting"

    [[Ready]]

    새 promise

    [[Reliability]]

    "pending"

    [[CongestionControl]]

    congestionControl

    [[AnticipatedConcurrentIncomingUnidirectionalStreams]]

    anticipatedConcurrentIncomingUnidirectionalStreams

    [[AnticipatedConcurrentIncomingBidirectionalStreams]]

    anticipatedConcurrentIncomingBidirectionalStreams

    [[ResponseHeaders]]

    null

    [[Protocol]]

    빈 문자열

    [[Closed]]

    새 promise

    [[Draining]]

    새 promise

    [[Datagrams]]

    undefined

    [[Session]]

    null

    [[NewConnection]]

    newConnection

    [[RequireUnreliable]]

    requireUnreliable

  19. transport.[[Datagrams]]transport, incomingDatagramsdatagramsReadableType과 함께 WebTransportDatagramDuplexStream생성한 결과로 설정한다.

  20. pullDatagramsAlgorithmtransport와 함께 pullDatagrams를 실행하는 동작으로 둔다.

    참고: 데이터그램에는 64 키비바이트 버퍼를 사용하는 것이 권장된다. 유효한 최대 WebTransport 데이터그램 프레임 크기의 상한이 QUIC 최대 데이터그램 프레임 크기이고, 그 크기는 64 키비바이트로 권장되기 때문이다 ([QUIC-DATAGRAM] Section 3 참조). 이렇게 하면 데이터그램이 버퍼보다 커서 스트림에 오류가 발생하지 않도록 보장한다.

  21. datagramsReadableType"bytes"이면, 바이트 읽기 지원으로 설정하고, incomingDatagramspullAlgorithmpullDatagramsAlgorithm로 설정하고, highWaterMark를 0으로 설정하여 구성한다. 그렇지 않으면, 설정하여 incomingDatagramspullAlgorithmpullDatagramsAlgorithm로 설정하고, highWaterMark를 0으로 설정하여 구성한다.

  22. pullBidirectionalStreamAlgorithmtransport와 함께 pullBidirectionalStream을 실행하는 동작으로 둔다.

  23. transport.[[IncomingBidirectionalStreams]]설정하되, pullAlgorithmpullBidirectionalStreamAlgorithm로 설정하고, highWaterMark를 0으로 설정한다.

  24. pullUnidirectionalStreamAlgorithmtransport와 함께 pullUnidirectionalStream을 실행하는 동작으로 둔다.

  25. transport.[[IncomingUnidirectionalStreams]]설정하되, pullAlgorithmpullUnidirectionalStreamAlgorithm로 설정하고, highWaterMark를 0으로 설정한다.

  26. clienttransport관련 설정 객체로 둔다.

  27. originclientorigin으로 둔다.

  28. request새 요청으로 둔다. 이 요청의 URLurl, clientclient, service-workers mode는 "none", referrer는 "no-referrer", mode는 "webtransport", credentials mode는 "omit", cache mode는 "no-store", policy containerclientpolicy container, destination은 "", originorigin, WebTransport-hash listserverCertificateHashes, 그리고 redirect mode는 "error"이다.

    참고: 리디렉션은 따르지 않는다. 리디렉션으로 인한 네트워크 오류는 의도적으로 다른 네트워크 오류와 구별할 수 없다. 교차 출처 컨텍스트에서는 이것이 일반적으로 CORS에 의해 차단될 정보를 드러낼 수 있다. 동일 출처 컨텍스트에서는 애플리케이션이 핸드셰이크를 정보 전달 벡터로 남용하도록 유도할 수 있다.

  29. requestmethod를 "CONNECT"로 설정하고, method와 연결된 :protocol pseudo-header"webtransport"로 설정한다.

  30. headersHeaders 객체로 둔다. 이는 options["headers"]로 채워진 새 객체이다.

  31. requestHeaders를 새 Headers 객체로 둔다. 이 객체의 header listrequestheader list이고, guard는 "request"이다.

  32. headersheader list의 각 header에 대해:

    1. headernameascii lowercase한 값이 "wt-available-protocols"이면, TypeError를 throw한다.

    2. headerrequestHeadersappend한다.

    참고: Headers는 Fetch의 금지된 요청-header 제한을 받는다.

  33. protocols가 비어 있지 않으면, (WT-Available-Protocols, protocols 안의 structured header string 항목들을 순서대로 멤버로 가지는 structured header list)로 구조화된 필드 값을 설정한다. 이는 requestheader list 안에 설정된다.

  34. requestFetch하되, useParallelQueue를 true로 설정하고, processResponseresponse가 주어졌을 때 다음 단계들로 설정한다:

    1. responsetransportWebTransport fetch 응답 처리를 수행한다.

  35. transport를 반환한다.

네트워크 파티션 키 networkPartitionKeyrequest request가 주어졌을 때, WebTransport 연결 얻기는 다음과 같이 한다:
  1. transportrequest와 연결된 WebTransport 객체로 둔다.

  2. urlrequest현재 URL로 둔다.

  3. newConnectiontransport.[[NewConnection]]으로 둔다.

  4. requireUnreliabletransport.[[RequireUnreliable]]로 둔다.

  5. webTransportHashesrequestWebTransport-hash list 안의 값들로 둔다.

  6. connectionnetworkPartitionKey, url, false, newConnection, requireUnreliablewebTransportHashes연결 얻기를 수행한 결과로 둔다.

  7. connection이 실패이면, 실패를 반환한다.

  8. connection이 첫 번째 SETTINGS 프레임을 수신할 때까지 기다리고, settings를 SETTINGS 프레임을 나타내는 딕셔너리로 둔다.

  9. settings가 값 1의 SETTINGS_ENABLE_CONNECT_PROTOCOL을 포함하지 않으면 (HTTP/2에 대해서는 0x08, Section 3 of [RFC8441] 참조; HTTP/3에 대해서는 0x08, Section 3 of [RFC9220] 참조), 실패를 반환한다.

  10. settings가 WebTransport에 대한 서버 지원을 나타내지 않으면, 실패를 반환한다. [WEB-TRANSPORT-OVERVIEW] Section 4.1.

  11. connection을 반환한다.

WebTransport fetch response 처리 알고리즘: response response, WebTransport transport를 받아 다음 단계를 수행한다:
  1. responsenetwork error면, 남은 단계 중단, queue a network tasktransport로 실행하여 아래 단계 수행:

    1. transport.[[State]]"closed""failed"면 중단.

    2. error를 새 WebTransportError로 만들고, source 값을 "session"으로 한다.

    3. Cleanup transporterror로 수행.

  2. connectionresponse에 대응하는 underlying connection으로 설정.

  3. 서버의 response를 사용해 [WEB-TRANSPORT-OVERVIEW] Section 4.1 의 제한에 따라 WebTransport session 설정connection에 수행하고, session을 결과 WebTransport session으로 설정. 결과 underlying transport stream을 session의 CONNECT stream이라 한다.

    참고: 이 단계에서 [QUIC-DATAGRAM]의 transport parameter 교환도 완료.

  4. 이 전 단계가 실패하면 나머지 중단, queue a network tasktransport로 실행하여 아래 단계를 수행:

    1. transport.[[State]]"closed" 또는 "failed"면 중단.

    2. error를 새 WebTransportError로 만들고, source"session"으로 설정.

    3. Cleanup transporterror로 수행.

  5. UA가 둘 이상의 혼잡 제어 알고리즘을 지원한다면, transport[[CongestionControl]] 값에 맞는 것을 connection 데이터 송신에 선택한다.

  6. queue a network tasktransport로 실행하여 아래 단계 수행:

    1. Assert: this[[Datagrams]][[OutgoingMaxDatagramSize]]가 정수임을 확인.

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

      1. 병렬로, terminate session로 수행.

      2. 중단.

    3. transport.[[State]] 값을 "connected"로 설정.

    4. transport.[[Session]] 값을 session으로 설정.

    5. responseHeadersresponseheader list의 복사본으로 설정.

    6. 삭제 "wt-protocol"를 responseHeaders에서 제거.

    7. transport.[[ResponseHeaders]] 값을 새 Headers 객체로 설정하고, header listresponseHeaders, guard는 "immutable"로 한다.

    8. transport.[[Protocol]] 값을 negotiated application protocol이 있으면 그 문자열 값으로, 없으면 ""로 설정 ([WEB-TRANSPORT-OVERVIEW] Section 3.1 참고).

    9. connection이 HTTP/3 연결이면, transport.[[Reliability]] 값을 "supports-unreliable"로 설정.

    10. connection이 HTTP/2 연결이면 ([WEB-TRANSPORT-HTTP2]), transport[[Reliability]] 값을 "reliable-only"로 설정.

    11. Resolve transport.[[Ready]] 값을 undefined로 해제한다.

pullBidirectionalStream 알고리즘: WebTransport 객체 transport를 받아 아래 단계 실행.
  1. transport.[[State]]"connecting"이면, transport.[[Ready]] 가 fulfill될 때 아래 절차를 수행:

    1. pullBidirectionalStreamtransport로 수행한 결과 반환.

  2. transport.[[State]]"connected"가 아니면, rejected promiseInvalidStateError로 반환.

  3. sessiontransport.[[Session]]으로 설정한다.

  4. p를 새 promise로 설정.

  5. 병렬로 아래 단계를 실행:

    1. session수신 대기 가능한 양방향 스트림 생길 때까지 대기.

    2. internalStream양방향 스트림 수신에서 session으로 받음.

    3. queue a network tasktransport로 실행하여 아래 단계를 수행:

      1. streamWebTransportBidirectionalStream 생성으로, internalStreamtransport를 전달하여 만든 결과로 설정.

      2. Enqueue streamtransport.[[IncomingBidirectionalStreams]]에 넣는다.

      3. Resolve p 값을 undefined로 해제.

  6. p를 반환한다.

pullUnidirectionalStream 알고리즘: WebTransport 객체 transport를 받아 아래 단계 실행.
  1. transport.[[State]]"connecting"이면, transport.[[Ready]] 가 fulfill될 때 아래 절차를 수행:

    1. pullUnidirectionalStreamtransport로 수행한 결과 반환.

  2. transport.[[State]]"connected"가 아니면, rejected promiseInvalidStateError로 반환.

  3. sessiontransport.[[Session]]로 설정한다.

  4. p를 새 promise로 설정.

  5. 병렬로 아래 단계를 실행:

    1. session수신 대기 가능한 단방향 스트림 생길 때까지 대기.

    2. internalStream단방향 스트림 수신에서 session으로 받음.

    3. queue a network tasktransport로 실행하여 아래 단계를 수행:

      1. streamWebTransportReceiveStream 생성으로, internalStreamtransport를 전달하여 만든 결과로 설정.

      2. Enqueue streamtransport.[[IncomingUnidirectionalStreams]]에 넣는다.

      3. Resolve p 값을 undefined로 해제.

  6. p를 반환한다.

6.3. 속성

ready, Promise<undefined> 타입, readonly

얻을 때 this[[Ready]]를 반환해야 한다.

closed, Promise<WebTransportCloseInfo> 타입, readonly

얻을 때 this[[Closed]]를 반환해야 한다.

draining, Promise<undefined> 타입, readonly

얻을 때 this[[Draining]]를 반환해야 한다.

datagrams, WebTransportDatagramDuplexStream 타입, readonly

이 세션을 통해 데이터그램을 송수신하는 단일 duplex 스트림. datagrams 속성의 getter 단계는 다음과 같다:

  1. this[[Datagrams]]를 반환.

incomingBidirectionalStreams, ReadableStream 타입, readonly

서버로부터 수신된 ReadableStreamWebTransportBidirectionalStream들의 목록을 반환함.

Note: 수신 스트림에 이미 데이터가 있는지는 서버 동작에 따라 다를 수 있음.

incomingBidirectionalStreams 속성 getter 단계:

  1. this[[IncomingBidirectionalStreams]]를 반환.

incomingUnidirectionalStreams, ReadableStream 타입, readonly

서버로부터 수신된 각 ReadableStream의 단방향 스트림 WebTransportReceiveStream로 이루어짐.

Note: 수신 스트림에 이미 데이터가 있는지는 서버 동작에 따라 다를 수 있음.

incomingUnidirectionalStreams 속성 getter 단계:

  1. this.[[IncomingUnidirectionalStreams]]를 반환.

reliability, WebTransportReliabilityMode 타입, readonly

연결이 신뢰성 없는(UDP) 전송을 지원하는지 또는 신뢰성 있는(TCP fallback) 전송만 지원하는지 여부. 연결이 설정될 때까지 "pending"을 반환. getter 단계는 this[[Reliability]]를 반환함.

congestionControl, WebTransportCongestionControl 타입, readonly

생성자에서 요청했고 사용자 에이전트가 충족시켜준 경우 처리량 최적화 또는 저지연 최적화 혼잡 제어 알고리즘에 대한 애플리케이션의 선호도. 요청했으나 충족되지 않은 경우 "default". getter 단계는 this[[CongestionControl]]를 반환.

supportsReliableOnly, boolean 타입, readonly

사용자 에이전트가 오직 신뢰할 수 있는 WebTransport 세션만 지원하는 연결을 지원하면 true, 아니면 false.

anticipatedConcurrentIncomingUnidirectionalStreams, unsigned short 타입, nullable

애플리케이션이 서버가 개설할 것으로 예상하는 동시에 열린 수신 단방향 스트림 수를 명시적으로 지정할 수 있음. null이 아니면, 사용자 에이전트는 서버와의 협상에서 [[AnticipatedConcurrentIncomingUnidirectionalStreams]]를 고려하여 향후 왕복시간을 줄이기 위해 노력해야 함.

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

setter 단계는 value가 주어질 경우 this[[AnticipatedConcurrentIncomingUnidirectionalStreams]]value를 할당.

anticipatedConcurrentIncomingBidirectionalStreams, unsigned short 타입, nullable

애플리케이션이 서버가 개설할 것으로 예상하는 동시에 열린 양방향 스트림 수를 명시적으로 지정할 수 있음. null이 아니면 사용자 에이전트는 서버와의 협상에서 [[AnticipatedConcurrentIncomingBidirectionalStreams]]를 고려해야 함.

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

setter 단계는 value가 주어질 경우 this[[AnticipatedConcurrentIncomingBidirectionalStreams]]value를 할당.

Note: anticipatedConcurrentIncomingUnidirectionalStreams 또는 anticipatedConcurrentIncomingBidirectionalStreams를 설정해도 애플리케이션이 예상한 수 만큼 스트림을 반드시 수신할 것이라는 보장은 없음.

responseHeaders, 타입 Headers, 읽기 전용, 널 허용

WebTransport 세션이 설정된 후, 서버가 설정한 어플리케이션 레벨 응답 헤더를 보관(있을 경우)합니다. 초기값은 null. getter 단계는 this[[ResponseHeaders]] 값을 반환합니다.

protocol, 타입 DOMString, 읽기 전용

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

6.4. 메서드

close(closeInfo)

WebTransport 객체와 연결된 WebTransport 세션을 종료한다. 호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis로 둔다.

  2. transport.[[State]]"closed" 또는 "failed"이면, 이 단계들을 중단한다.

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

    1. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"session"이다.

    2. errortransportCleanup한다.

    3. 이 단계들을 중단한다.

  4. sessiontransport.[[Session]]으로 둔다.

  5. codecloseInfo.closeCode로 둔다.

  6. reasonStringcloseInfo.reason의 최대 코드 단위 접두사로 두며, 그 UTF-8 인코딩된 접두사의 길이는 1024를 초과하지 않는다.

  7. reasonreasonStringUTF-8 인코딩한 것으로 둔다.

  8. 병렬로, codereason으로 session종료한다.

    참고: 이는 또한 transport.[[SendStreams]][[ReceiveStreams]]에 포함된 WebTransport 스트림에서 송신을 중단하거나 수신을 중단한다.

  9. AbortErrorcloseInfotransportCleanup한다.

getStats()

WebTransport기저 연결에 대한 통계를 수집하고 그 결과를 비동기적으로 보고한다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis로 둔다.

  2. p를 새 promise로 둔다.

  3. transport.[[State]]"failed"이면, pInvalidStateErrorreject하고 이 단계들을 중단한다.

  4. 다음 단계들을 병렬로 실행한다:

    1. transport.[[State]]"connecting"이면, 그것이 변경될 때까지 기다린다.

    2. transport.[[State]]"failed"이면, transport와 함께 네트워크 작업을 큐에 넣어 pInvalidStateErrorreject한 뒤 이 단계들을 중단한다.

    3. transport.[[State]]"closed"이면, transport와 함께 네트워크 작업을 큐에 넣어 연결에 대해 사용 가능한 가장 최근 통계로 presolve한 뒤 이 단계들을 중단한다. 해당 통계가 수집되는 정확한 시점은 구현 정의이다.

    4. gatheredStatsWebTransportConnectionStatsWebTransportDatagramStats사전 멤버를 정확히 채우는 데 필요한 기저 연결에 특정한 통계의 목록으로 둔다.

    5. transport.[[NewConnection]]이 "no"이면, gatheredStats에서 풀링된 연결 통계로 표시되지 않은 모든 통계를 제거한다.

    6. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. statsWebTransportConnectionStats 객체로 둔다.

      2. datagramStatsWebTransportDatagramStats 객체로 둔다.

      3. stats["datagrams"]을 datagramStats로 설정한다.

      4. 사용자 에이전트가 노출하려는 statsdatagramStats의 각 멤버 member에 대해, membergatheredStats의 해당 항목으로 설정한다.

      5. statspResolve한다.

  5. p를 반환한다.

exportKeyingMaterial(BufferSource label, BufferSource context, unsigned long outputLength)

WebTransport기저 연결과 고유하게 연결된 TLS 세션에 대한 TLS Keying Material Exporter에서 키 자료를 내보낸다. 호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. labelLengthlabel.바이트 길이로 둔다.

  2. labelLength가 255보다 크면, RangeError거부된 promise를 반환한다.

  3. contextLengthcontext.바이트 길이로 둔다.

  4. contextLength가 255보다 크면, RangeError거부된 promise를 반환한다.

  5. outputLength가 0이거나 구현 정의 값—​이 값은 최소 4096이어야(must) 한다—​보다 크면, RangeError거부된 promise를 반환한다.

  6. this.[[State]]"closed" 또는 "failed"이면, InvalidStateError거부된 promise를 반환한다.

  7. transportthis로 둔다.

  8. p를 새 promise로 둔다.

  9. 다음 단계들을 병렬로 실행하되, transport[[State]]"closed" 또는 "failed"가 되면 중단하고, 대신 transport와 함께 네트워크 작업을 큐에 넣어 pInvalidStateErrorreject한다:

    1. keyingMaterial[WEB-TRANSPORT-OVERVIEW] Section 4.1에 정의된 대로, label, contextoutputLength와 함께 TLS 키 내보내기를 호출하여 생성된 Uint8Array로 둔다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 pkeyingMaterialresolve한다.

  10. p를 반환한다.

createBidirectionalStream(options)

나가는 양방향 스트림을 위한 WebTransportBidirectionalStream 객체를 생성한다. 스트림을 단순히 생성하는 것만으로는 데이터 전송에 사용되기 전까지 피어에게 즉시 보이지 않는다는 점에 유의한다.

참고: 서버가 스트림에서 데이터가 전송되기 전까지 해당 스트림을 인식할 것이라는 기대는 없다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. sendGroupoptionssendGroup으로 둔다.

  2. sendGroup이 null이 아니고, sendGroup.[[Transport]]this가 아니면, TypeError거부된 promise를 반환한다.

  3. this.[[State]]"closed" 또는 "failed"이면, InvalidStateError거부된 promise를 반환한다.

  4. sendOrderoptionssendOrder로 둔다.

  5. waitUntilAvailableoptionswaitUntilAvailable로 둔다.

  6. p를 새 promise로 둔다.

  7. transportthis로 둔다.

  8. 다음 단계들을 병렬로 실행하되, transport[[State]]"closed" 또는 "failed"가 되면 중단하고, 대신 transport와 함께 네트워크 작업을 큐에 넣어 pInvalidStateErrorreject한다:

    1. streamId[QUIC] Section 19.11에 정의된 대로, transport.[[Session]]에 대해 유효하고 고유한 새 스트림 ID로 둔다. 고갈로 인해 하나를 즉시 사용할 수 없으면, waitUntilAvailable이 true인 경우 사용할 수 있게 될 때까지 기다리거나, waitUntilAvailable이 false인 경우, transport와 함께 네트워크 작업을 큐에 넣어 preject한 뒤 이 단계들을 중단한다. 이때 prequestedquota가 모두 null인 QuotaExceededError로 reject된다.

    2. internalStreamtransport.[[Session]]streamId양방향 스트림을 생성한 결과로 둔다.

    3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. transport.[[State]]"closed" 또는 "failed"이면, pInvalidStateErrorreject하고 이 단계들을 중단한다.

      2. streaminternalStream, transport, sendGroupsendOrderWebTransportBidirectionalStream생성한 결과로 둔다.

      3. stream으로 pResolve한다.

  9. p를 반환한다.

createUnidirectionalStream(options)

나가는 단방향 스트림을 위한 WebTransportSendStream을 생성한다. 스트림을 단순히 생성하는 것만으로는 데이터 전송에 사용되기 전까지 서버에게 즉시 보이지 않는다는 점에 유의한다.

참고: 서버가 스트림에서 데이터가 전송되기 전까지 해당 스트림을 인식할 것이라는 기대는 없다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. sendGroupoptionssendGroup으로 둔다.

  2. sendGroup이 null이 아니고, sendGroup.[[Transport]]this가 아니면, TypeError거부된 promise를 반환한다.

  3. this.[[State]]"closed" 또는 "failed"이면, InvalidStateError거부된 promise를 반환한다.

  4. sendOrderoptionssendOrder로 둔다.

  5. waitUntilAvailableoptionswaitUntilAvailable로 둔다.

  6. p를 새 promise로 둔다.

  7. transportthis로 둔다.

  8. 다음 단계들을 병렬로 실행하되, transport[[State]]"closed" 또는 "failed"가 되면 중단하고, 대신 transport와 함께 네트워크 작업을 큐에 넣어 pInvalidStateErrorreject한다:

    1. streamId[QUIC] Section 19.11에 정의된 대로, transport.[[Session]]에 대해 유효하고 고유한 새 스트림 ID로 둔다. 고갈로 인해 하나를 즉시 사용할 수 없으면, waitUntilAvailable이 true인 경우 사용할 수 있게 될 때까지 기다리거나, waitUntilAvailable이 false인 경우, transport와 함께 네트워크 작업을 큐에 넣어 preject한 뒤 이 단계들을 중단한다. 이때 pQuotaExceededError로 reject된다.

    2. internalStreamtransport.[[Session]]streamId나가는 단방향 스트림을 생성한 결과로 둔다.

    3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. transport.[[State]]"closed" 또는 "failed"이면, pInvalidStateErrorreject하고 이 단계들을 중단한다.

      2. streaminternalStream, transport, sendGroup, 및 sendOrderWebTransportSendStream생성한 결과로 둔다.

      3. stream으로 pResolve한다.

  9. p를 반환한다.

createSendGroup()

WebTransportSendGroup을 생성한다.

createSendGroup() 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 실행한다:
  1. this.[[State]]"closed" 또는 "failed"이면, throw an InvalidStateError.

  2. thisWebTransportSendGroup생성한 결과를 반환한다.

6.5. 절차

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]]를 빈 집합으로 설정한다.

  10. transport.[[ReceiveStreams]]를 빈 집합으로 설정한다.

  11. transport.[[Datagrams]].[[OutgoingDatagramsQueue]]를 빈 로 설정한다.

  12. transport.[[Datagrams]].[[IncomingDatagramsQueue]]를 빈 로 설정한다.

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

  14. sendStreams의 각 stream에 대해 반복하여, 다음 단계를 실행한다:

    1. stream.[[PendingOperation]]이 null이 아니면, stream.[[PendingOperation]]error로 거부한다.

    2. streamerror에러 처리한다.

  15. receiveStreams의 각 stream에 대해 반복하여, streamerror에러 처리한다.

    참고: 스크립트 작성자는 Promise 해석 중에 동기적으로 실행되는 코드를 삽입할 수 있다. 따라서 여기부터는 transport를 건드리지 않는다. 스크립트에 의해 예측할 수 없는 방식으로 변경될 수 있기 때문이다. 이는 이 절차를 호출하는 로직에도 적용된다.

  16. closeInfo가 주어졌으면:

    1. closedcloseInfoResolve한다.

    2. Assert: readysettled 상태이다.

    3. incomingBidirectionalStreams닫는다.

    4. incomingUnidirectionalStreams닫는다.

    5. outgoingDatagramWritables의 각 writable에 대해, writable닫는다.

    6. incomingDatagrams닫는다.

  17. 그렇지 않으면:

    1. closederrorReject한다.

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

    3. readyerrorReject한다.

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

    5. incomingBidirectionalStreamserror에러 처리한다.

    6. incomingUnidirectionalStreamserror에러 처리한다.

    7. outgoingDatagramWritables의 각 writable에 대해, writableerror에러 처리한다.

    8. incomingDatagramserror에러 처리한다.

WebTransport transport 및 일련의 단계 steps네트워크 작업을 큐에 넣으려면, 다음 단계를 실행한다:

  1. steps를 실행하기 위해 transport관련 전역 객체와 함께 네트워킹 작업 소스에서 전역 작업을 큐에 넣는다.

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

WebTransport transport와 연결된 WebTransport 세션이 선택적으로 codereasonBytes와 함께 종료될 때마다, 다음 단계를 실행한다:
  1. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

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

    2. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"session"이다.

    3. closeInfoWebTransportCloseInfo 객체로 둔다.

    4. code가 주어졌으면, closeInfocloseCodecode로 설정한다.

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

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

    6. errorcloseInfotransportCleanup한다.

WebTransport transport기저 연결에 연결 오류가 발생할 때마다, 다음 단계를 실행한다:
  1. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

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

    2. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"session"이다.

    3. errortransportCleanup한다.

6.7. 컨텍스트 정리 절차

이 명세서는 context cleanup steps를 다음과 같이 정의한다. 단, WebTransport transport가 주어진다:

  1. transport.[[State]]"connected"이면, 다음을 수행한다:

    1. transport.[[State]]"failed"로 설정한다.

    2. 병렬로, transport.[[Session]]종료한다.

    3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

      1. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"session"이다.

      2. errortransportCleanup한다.

  2. transport.[[State]]"connecting"이면, transport.[[State]]"failed"로 설정한다.

    이는 workers에서도 수행되어야 한다. 다음을 참조하라: #127whatwg/html#6731.

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

WebTransport 객체의 [[State]]"connecting"인 경우, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 임의의 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]잠겨 있거나, 또는 ready, draining, 또는 closed promise가 관찰 중이면 가비지 수집되어서는 안 된다.

WebTransport 객체의 [[State]]"connected"인 경우, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 임의의 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]잠겨 있거나, 또는 draining 또는 closed promise가 관찰 중이면 가비지 수집되어서는 안 된다.

WebTransport 객체의 [[State]]"draining"인 경우, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 임의의 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]잠겨 있거나, 또는 closed promise가 관찰 중이면 가비지 수집되어서는 안 된다.

확립된 WebTransport 세션을 가진 WebTransport 객체가 [[Datagrams]].[[OutgoingDatagramsQueue]]의 데이터그램을 포함하여 네트워크로 전송되도록 큐에 들어간 데이터를 가지고 있으면, 가비지 수집되어서는 안 된다.

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

6.9. 구성(Configuration)

dictionary WebTransportHash {
  required DOMString algorithm;
  required BufferSource value;
};

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

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

WebTransportOptionsWebTransport 세션 이 어떻게 생성되고 사용되는지 결정하는 파라미터의 딕셔너리입니다.

allowPooling, 타입 boolean, 기본값 false

true로 설정하면 WebTransport 세션이 pool될 수 있음, 즉, 하위 연결 이 다른 WebTransport 세션과 공유될 수 있습니다.

requireUnreliable, 타입 boolean, 기본값 false

true로 설정하면, WebTransport 세션은 HTTP/3 connection이 불가능할 경우 HTTP/2 connection에서는 생성될 수 없습니다.

headers, 타입 HeadersInit, 기본값 {}

옵션으로 Headers 객체, 객체 리터럴, 혹은 두 개 아이템을 가진 배열의 배열로 requestheader list를 설정. WebTransport 세션 생성 시 사용합니다.

serverCertificateHashes, 타입 sequence<WebTransportHash>, 기본값 []

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

지원되며 비어있지 않을 경우, 사용자 에이전트는 서버 인증서가 인증서 해시 검증에 성공해야 신뢰해야 합니다. serverCertificateHashes사용자 인증서 요구사항을 모두 만족해야 합니다. 사용자 에이전트는 알려지지 않은 algorithm 해시를 무시해야 합니다. 비어있으면, 일반 fetch 작업에서 사용하는 인증서 검증 절차를 사용합니다.

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

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

옵션으로 애플리케이션에서 처리량이나 저지연에 맞는 혼잡 제어 알고리즘 사용 희망을 지정할 수 있습니다. 이는 사용자 에이전트에 대한 힌트일 뿐입니다.

이 옵션은 브라우저에서 저지연 최적화된 혼잡 제어 알고리즘의 구현 부족으로 인해 위험(feature at risk)으로 간주됩니다.

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

옵션으로 애플리케이션이 동시에 서버로부터 생성될 것으로 예상하는 단방향 수신 스트림 수를 지정할 수 있습니다. 사용자 에이전트는 서버에서 최소 100개의 단방향 수신 스트림 생성을 허용해야 합니다. null이 아니면, 사용자 에이전트는 서버 협상에서 라운드 트립 감소를 시도해야 합니다. [[AnticipatedConcurrentIncomingUnidirectionalStreams]] 값을 고려해서.

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

옵션으로 애플리케이션이 동시에 서버로부터 생성될 것으로 예상하는 양방향 스트림 수를 지정할 수 있습니다. 사용자 에이전트는 서버에서 최소 100개의 양방향 스트림 생성을 허용해야 합니다. null이 아니면, 사용자 에이전트는 서버 협상에서 라운드 트립 감소를 시도해야 하며, [[AnticipatedConcurrentIncomingBidirectionalStreams]] 값을 고려해야 합니다.

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

애플리케이션 레벨의 프로토콜 이름 배열을 옵션으로 제공할 수 있습니다. 서버가 원하는 프로토콜을 선택 및 클라이언트에 전달할 수 있습니다(선택사항). 제공된 프로토콜이 적합하지 않을 경우 서버가 요청을 거부할 수도 있습니다.

datagramsReadableType, 타입 ReadableStreamType

옵션으로, 애플리케이션이 수신 datagram에 대해 readable byte stream을 사용하고 싶으면 지정할 수 있습니다. 그 외에는 기본 readable stream이 사용됩니다.

참고: readable stream 은 datagram 의미론과 호환되지만, readable byte stream 은 그렇지 않습니다. datagram은 0 바이트 이상 메시지(순서 보장 없음)가 각각 도착할 수 있으며, 비순서화된 바이트 시퀀스가 아닙니다. 빈 datagram은 손실되고, min 을 쓰면 메시지 구분이 사라집니다.

compute a certificate hash를 수행하기 위해, certificate가 주어졌을 때 다음 단계를 수행한다:

  1. certcertificate로 두되, [RFC5280]에 정의된 Certificate 메시지의 DER 인코딩으로 표현한다.

  2. cert의 SHA-256 해시를 계산하고 계산된 값을 반환한다.

verify a certificate hash를 수행하기 위해, certificate chain과 해시 배열 hashes가 주어졌을 때, 다음 단계를 수행한다:

  1. certificatecertificate chain의 첫 번째 인증서(리프 인증서)로 둔다.

  2. referenceHashcomputing a certificate hashcertificate로 수행한 결과로 둔다.

  3. hashes의 각 해시 hash에 대해:

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

      1. hashValuehash.value 가 나타내는 바이트 시퀀스로 둔다.

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

  4. false를 반환한다.

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

Subject Public Key Info 필드에서 사용되는 허용된 공개 키 알고리즘의 정확한 목록은 (그 결과 TLS CertificateVerify 메시지에서도) 구현 정의이다. 그러나 상호 운용 가능한 기본값을 제공하기 위해 secp256r1 (NIST P-256) 명명된 그룹을 사용하는 ECDSA([RFC3279], Section 2.3.5; [RFC8422])를 포함해야 한다. RSA 키를 포함해서는 안 된다 ([RFC3279], Section 2.3.1).

6.10. WebTransportCloseInfo 딕셔너리

WebTransportCloseInfo 딕셔너리는 WebTransport 세션종료할 때 오류 코드와 사유를 설정하는 데 사용되는 정보를 포함한다.

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

딕셔너리는 다음 속성을 가져야 한다:

closeCode, 타입은 unsigned long이며, 기본값은 0

피어에게 전달되는 오류 코드.

reason, 타입은 USVString이며, 기본값은 ""

WebTransport를 닫는 사유.

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 호출이 반환한 promise는 스트림을 생성하기에 충분한 흐름 제어 크레딧을 기저 연결이 갖게 되거나, 연결이 더 이상 나가는 스트림을 만들 수 없는 상태에 도달할 때까지 settled되지 않는다. false이면, 호출 시점에 사용 가능한 흐름 제어 윈도우가 없을 경우 promise는 rejected된다.

6.13. WebTransportConnectionStats 딕셔너리

WebTransportConnectionStats 딕셔너리는 WebTransport 세션기저 연결에 대한 정보를 포함한다. WebTransportConnectionStats의 멤버 중 풀링된 연결 통계로 표시되지 않은 것은 풀링 대상인 기저 연결에 대해 존재하지 않는다.

참고: 풀링이 허용되면, 풀링된 연결 통계만 드러나며, 같은 연결에 풀링된 여러 WebTransport 세션은 모두 같은 정보를 받는다. 즉, 같은 네트워크 파티션 키를 보유한 풀링된 세션 사이에 정보가 공개된다.

참고: 사용할 수 없는 통계는 모두 WebTransportConnectionStats 딕셔너리에서 존재하지 않는다.

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

딕셔너리는 다음 속성을 가져야 한다:

bytesSent, 타입은 unsigned long long

기저 연결을 통해 전송된 페이로드 바이트 수. 모든 프레이밍 오버헤드나 재전송은 제외한다.

bytesSentOverhead, 타입은 unsigned long long

기저 연결에서 bytesSent 수의 페이로드 바이트를 전송할 때의 프레이밍 및 재전송 오버헤드(바이트 단위).

bytesAcknowledged, 타입은 unsigned long long

기저 연결에서 QUIC의 ACK 메커니즘을 사용하여 서버가 수신했다고 확인한 페이로드 바이트 수. 모든 프레이밍은 제외한다.

참고: 일반적으로 bytesSent보다 뒤처지지만, 패킷 손실로 인해 영구적으로 더 작을 수 있다.

bytesAcknowledgedWebTransportConnectionStats에서 구현 가능성에 대한 우려로 인해 작업 그룹에 의해 위험 기능으로 식별되었다.
packetsSent, 타입은 unsigned long long

기저 연결에서 전송된 패킷 수. 손실된 것으로 판정된 패킷도 포함한다.

bytesLost, 타입은 unsigned long long

기저 연결에서 손실된 바이트 수(단조 증가하지 않는다. 손실로 선언된 패킷이 이후에 수신될 수 있기 때문이다). UDP 또는 그 밖의 외부 프레이밍은 포함하지 않는다.

packetsLost, 타입은 unsigned long long

기저 연결에서 손실된 패킷 수(단조 증가하지 않는다. 손실로 선언된 패킷이 이후에 수신될 수 있기 때문이다).

bytesReceived, 타입은 unsigned long long

기저 연결에서 수신된 총 바이트 수. 스트림의 중복 데이터를 포함한다. UDP 또는 그 밖의 외부 프레이밍은 포함하지 않는다.

packetsReceived, 타입은 unsigned long long

기저 연결에서 수신된 총 패킷 수. 처리할 수 없었던 패킷도 포함한다.

smoothedRtt, 타입은 DOMHighResTimeStamp

현재 연결에서 관측되는 평활화 왕복 시간(RTT). [RFC9002] Section 5.3에 정의된 대로이다. 이는 풀링된 연결 통계이다.

rttVariation, 타입은 DOMHighResTimeStamp

현재 연결에서 관측되는 왕복 시간 샘플의 평균 변동. [RFC9002] Section 5.3에 정의된 대로이다. 이는 풀링된 연결 통계이다.

minRtt, 타입은 DOMHighResTimeStamp

전체 연결에서 관측된 최소 왕복 시간. [RFC9002] Section 5.2에 정의된 대로이다. 이는 풀링된 연결 통계이다.

estimatedSendRate, 타입은 unsigned long long이며, nullable이고, 기본값은 null

큐에 들어간 데이터가 사용자 에이전트에 의해 전송될 것으로 추정되는 속도(초당 비트 단위). 이 속도는 WebTransport 세션을 공유하는 모든 스트림과 데이터그램에 적용되며, 혼잡 제어 알고리즘(congestionControl에 의해 선택될 수도 있음)에 의해 계산된다. 이 추정치는 모든 프레이밍 오버헤드를 제외하며, 애플리케이션 페이로드가 전송될 수 있는 속도를 나타낸다. 사용자 에이전트가 현재 추정치를 가지고 있지 않으면, 멤버는 null 값이어야 한다. 이전 결과에서 null이 아니었더라도 이 멤버는 null일 수 있다. 이는 풀링된 연결 통계이다.

atSendCapacity, 타입은 boolean이며, 기본값은 false

false 값은 estimatedSendRate가 애플리케이션 제한 상태일 수 있음을 나타낸다. 즉 애플리케이션이 혼잡 컨트롤러가 허용하는 것보다 훨씬 적은 데이터를 보내고 있다는 뜻이다. 혼잡 컨트롤러는 애플리케이션 제한 상태인 동안 사용 가능한 네트워크 용량에 대한 낮은 품질의 추정치를 생성할 수 있다.

true 값은 애플리케이션이 네트워크 용량으로 데이터를 보내고 있으며, estimatedSendRate가 애플리케이션에 사용 가능한 네트워크 용량을 반영함을 나타낸다.

atSendCapacitytrue이면, estimatedSendRate는 상한을 반영한다. 애플리케이션 전송 속도가 유지되는 한, estimatedSendRate는 네트워크 조건에 적응한다. 그러나 estimatedSendRateatSendCapacity가 true인 동안에도 null일 수 있다.
이는 풀링된 연결 통계이다.

6.14. WebTransportDatagramStats 딕셔너리

WebTransportDatagramStats 사전은 underlying connection을 통한 데이터그램 전송 통계를 포함한다.

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

이 사전에는 다음 속성이 포함되어야 한다:

droppedIncoming, 타입 unsigned long long

애플리케이션이 datagramsreadable 에서 새 데이터그램이 수신 큐를 초과하기 전에 읽지 않아 드롭된 수신 데이터그램 수

expiredIncoming, 타입 unsigned long long

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

expiredOutgoing, 타입 unsigned long long

전송 대기 중 outgoingMaxAge 보다 오래되어 전송되기 전에 드롭된 데이터그램 수

lostOutgoing, 타입 unsigned long long

전송된 데이터그램 중 [RFC9002] Section 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]]을 반환한다.

value가 주어졌을 때 setter 단계는 다음과 같다:

  1. value가 non-null이고, value.[[Transport]]this.[[Transport]]가 아니면, throw an InvalidStateError.

  2. this.[[SendGroup]]value로 설정한다.

sendOrder, 타입은 long long이다

getter 단계는 다음과 같다:

  1. this[[SendOrder]]를 반환한다.

value가 주어졌을 때 setter 단계는 다음과 같다:

  1. this.[[SendOrder]]value로 설정한다.

7.2. 메서드

getStats()

WebTransportSendStream의 성능에 특정한 통계를 수집하고, 그 결과를 비동기적으로 보고한다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis.[[Transport]]로 둔다.

  2. p를 새 promise로 둔다.

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

    1. gatheredStatsWebTransportSendStreamStats사전 멤버를 정확히 채우는 데 필요한, this WebTransportSendStream에 특정한 통계의 목록으로 둔다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. statsWebTransportSendStreamStats 객체로 둔다.

      2. 사용자 에이전트가 노출하려는 stats의 각 멤버 member에 대해, membergatheredStats의 해당 항목으로 설정한다.

      3. statspResolve한다.

  4. p를 반환한다.

getWriter()

this 스트림을 위한 WebTransportWriter를 생성한다.

getWriter가 호출되면, thisWebTransportWriter생성한 결과를 반환한다.

7.3. 내부 슬롯

WebTransportSendStream 객체는 다음과 같은 내부 슬롯을 가진다.

내부 슬롯 설명 (비규범적)
[[InternalStream]] 송신 단방향 또는 양방향 WebTransport 스트림.
[[PendingOperation]] 대기 중인 write 또는 close 연산을 나타내는 promise, 또는 null.
[[Transport]] WebTransport를 소유하는 WebTransportSendStream.
[[SendGroup]] 옵션의 WebTransportSendGroup, 또는 null.
[[SendOrder]] 옵션의 송신 순서 번호, 기본값은 0.
[[AtomicWriteRequests]] 정렬된 집합(ordered set)의 promise 들로, 내부 sink에서 처리 대기 중인 atomic write 요청 서브셋을 추적한다.
[[InsideSynchronousAtomicWrite]] atomicWrite 메서드의 동기적 부분에서만 true인 불리언.
[[BytesWritten]] 이 스트림에 기록된 바이트 수.
[[CommittedOffset]] 스트림에서, 송신 중단(aborted sending) 상태여도 피어에 전달될 바이트 수를 기록하는 오프셋; [RELIABLE-RESET] 참고.

7.4. 절차

생성하려면, WebTransportSendStream단방향 송신 또는 양방향 WebTransport 스트림 internalStream, WebTransport transport, sendGroup, sendOrder를 받으면 아래 단계를 수행한다:

  1. stream새로운 WebTransportSendStream으로 생성하며 설정값은 다음과 같다:

    [[InternalStream]]

    internalStream

    [[PendingOperation]]

    null

    [[Transport]]

    transport

    [[SendGroup]]

    sendGroup

    [[SendOrder]]

    sendOrder

    [[AtomicWriteRequests]]

    비어있는 정렬된 집합 promise

    [[InsideSynchronousAtomicWrite]]

    false

    [[BytesWritten]]

    0

    [[CommittedOffset]]

    0

  2. writeAlgorithm쓰기 동작으로 설정, chunkstream에 쓴다.

  3. closeAlgorithm닫기 동작으로 설정, stream을 닫는다.

  4. abortAlgorithm중단 동작으로 설정, reason을 받아 stream을 중단한다.

  5. 설정stream에 적용, writeAlgorithmwriteAlgorithm, closeAlgorithmcloseAlgorithm, abortAlgorithmabortAlgorithm로 설정한다.

  6. abortSignalstream의 [[controller]].[[abortController]].[[signal]]로 설정한다.

  7. AddabortSignal에 아래 단계로 추가한다.

    1. pendingOperationstream.[[PendingOperation]] 값으로 설정한다.

    2. pendingOperation이 null이면 단계 중단.

    3. stream.[[PendingOperation]] 값을 null로 설정.

    4. reasonabortSignal중단 사유 값으로 설정.

    5. promisestream 중단 동작의 결과로 설정, reason을 인자로 전달.

    6. 약속 이행 시 promise가 완료되면, reject pendingOperationreason으로 거절한다.

  8. Appendstream에 대해 수행하여 transport.[[SendStreams]]에 추가한다.

  9. stream을 반환한다.

WebTransportSendStream streamchunk쓰기 위해서는, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 둔다.

  2. chunkBufferSource가 아니면, TypeError거부된 promise를 반환한다.

  3. promise를 새 promise로 둔다.

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

  5. bytes길이가 0이면, promise를 undefined로 resolve하고 promise를 반환한다.

  6. stream.[[PendingOperation]]promise로 설정한다.

  7. inFlightWriteRequeststream.inFlightWriteRequest로 둔다.

  8. stream.[[AtomicWriteRequests]]inFlightWriteRequest포함하거나 stream.[[InsideSynchronousAtomicWrite]]가 true이면 atomic을 true로 두고, 그렇지 않으면 false로 둔다.

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

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

      1. stream.[[PendingOperation]]을 null로 설정한다.

      2. stream에서 모든 원자적 쓰기 요청을 중단한다.

    2. 그렇지 않으면, stream.[[InternalStream]]에서 bytes보내고 작업이 완료될 때까지 기다린다. 이 전송은 send-order 규칙을 MUST 따른다.

      사용자 에이전트는 전송 성능을 향상시키기 위한 버퍼를 가질 수 있다. 이러한 버퍼는 WebTransportSendStream의 사용자에게 배압 정보를 전달하기 위해 고정된 상한을 가지는 것이 좋다.

      여기서는 stream.[[SendOrder]]병렬로 접근한다. 사용자 에이전트는 전송 중 이러한 값의 실시간 업데이트에 응답하는 것이 좋지만, 세부 사항은 구현 정의이다.

      참고: 재전송의 순서는 구현 정의이지만, 사용자 에이전트는 더 높은 [[SendOrder]] 값을 가진 데이터의 재전송을 우선시할 것을 강하게 권장한다.

      이 전송은 흐름 제어 이유 또는 오류를 제외하고, 다른 경우에는 MUST NOT starve되어야 한다.

      사용자 에이전트는 starve되지 않은 모든 스트림 간에 대역폭을 공정하게 나누는 것이 좋다.

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

    3. 이전 단계가 네트워크 오류로 인해 실패했다면, 남은 단계를 중단한다.

      참고: 여기서는 promise를 reject하지 않는다. 네트워크 오류는 다른 곳에서 처리하며, 그 단계들이 stream.[[PendingOperation]]을 reject하기 때문이다.

    4. 그렇지 않으면, transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

      1. stream.[[PendingOperation]]을 null로 설정한다.

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

      3. stream.[[AtomicWriteRequests]]inFlightWriteRequest포함하면, inFlightWriteRequest제거한다.

      4. promise를 undefined로 Resolve한다.

  10. promise를 반환한다.

참고: 이 알고리즘(또는 write(chunk))에서 반환된 promise의 이행이 반드시 청크가 서버 [QUIC]에 의해 ack되었음을 의미하지는 않는다. 이는 청크가 버퍼에 추가되었다는 의미일 수 있다. 청크가 서버에 도착했는지 확인하려면, 서버가 애플리케이션 수준의 확인 메시지를 보내야 한다.

WebTransportSendStream stream닫기 위해서는, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 둔다.

  2. promise를 새 promise로 둔다.

  3. transport.[[SendStreams]]에서 stream제거한다.

  4. stream.[[PendingOperation]]promise로 설정한다.

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

    1. stream.[[InternalStream]]에서 FIN을 보내고 작업이 완료될 때까지 기다린다.

    2. stream.[[InternalStream]]이 "all data committed" 상태에 들어갈 때까지 기다린다. [QUIC]

    3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

      1. stream.[[PendingOperation]]을 null로 설정한다.

      2. promise를 undefined로 Resolve한다.

  6. promise를 반환한다.

WebTransportSendStream streamreason으로 중단하려면, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 둔다.

  2. promise를 새 promise로 둔다.

  3. code를 0으로 둔다.

  4. transport.[[SendStreams]]에서 stream제거한다.

  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을 사용하는 경우, 코드는 [WEB-TRANSPORT-HTTP3]에 설명된 것처럼 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 숫자로 인코딩된다.

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

    1. stream.[[InternalStream]]에서 codecommittedOffset송신을 중단한다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 promise를 undefined로 resolve한다.

  10. promise를 반환한다.

WebTransportSendStream stream에서 모든 원자적 쓰기 요청을 중단하려면, 다음 단계를 실행한다:
  1. writeRequestsstream.writeRequests로 둔다.

  2. requestsToAbortstream.[[AtomicWriteRequests]]로 둔다.

  3. writeRequestsrequestsToAbort에 없는 promise를 포함하면, streamAbortError에러 처리하고, 이 단계들을 중단한다.

  4. stream.[[AtomicWriteRequests]]비운다.

  5. requestsToAbort의 각 promise에 대해 반복하여, promiseAbortErrorreject한다.

  6. 병렬로, requestsToAbort의 각 promise에 대해 반복하여, promise와 연결된 바이트의 송신을 중단한다.

7.5. 서버로부터 수신 중단 신호 받기

WebTransportSendStream stream과 연결된 WebTransport 스트림이 서버로부터 수신 중단됨 신호를 받으면, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 둔다.

  2. code수신 중단됨 신호에 첨부된 애플리케이션 프로토콜 오류 코드로 둔다.

    참고: code의 유효한 값은 0부터 4294967295까지이다. 기저 연결이 HTTP/3을 사용하는 경우, 코드는 [WEB-TRANSPORT-HTTP3]에 설명된 것처럼 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 숫자로 인코딩된다.

  3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

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

    2. transport.[[SendStreams]]에서 stream제거한다.

    3. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"stream"이고 streamErrorCodecode이다.

    4. stream.[[PendingOperation]]이 null이 아니면, stream.[[PendingOperation]]error로 reject한다.

    5. streamerror에러 처리한다.

7.6. WebTransportSendStreamStats 사전

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

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

이 사전에는 다음 속성이 포함되어야 한다:

bytesWritten, 타입 unsigned long long

애플리케이션이 이 WebTransportSendStream 에 성공적으로 기록한 총 바이트 수. 이 숫자는 증가만 한다.

bytesSent, 타입 unsigned long long

애플리케이션이 이 WebTransportSendStream 에 쓴 바이트 중 최소 한 번 이상 전송된 바이트 수 표시. 이 값은 증가만 하며 항상 bytesWritten 이하이다.

Note: 이것은 단일 스트림에서의 앱 데이터 전송 진행률일 뿐이며 네트워크 오버헤드는 포함하지 않는다.

bytesAcknowledged, 타입 unsigned long long

애플리케이션이 이 WebTransportSendStream 에 쓴 바이트 중 QUIC의 ACK 메커니즘에 의해 서버가 수신 확인을 한(acknowledged) 순차 바이트 수. 첫 번째 미acknowledged 바이트 전까지의 모든 바이트만 포함. 이 숫자는 증가만 하며 bytesSent 이하이다.

Note: 연결이 HTTP/2일 때는 이 값이 bytesSent 과 일치한다.

8. 인터페이스 WebTransportSendGroup

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

WebTransportSendStreamWebTransportDatagramsWritable는 생성 시점이나 sendGroup 속성 할당을 통해, 언제든지 최대 하나의 WebTransportSendGroup 또는 null sendGroup그룹될 수 있습니다. 기본적으로 WebTransportSendStreamWebTransportDatagramsWritablenull sendGroup에 할당됩니다.

사용자 에이전트는 WebTransportSendGroupWebTransportSendStream 전송 대역폭 할당 시 동등하게 취급합니다. 각 WebTransportSendGroupsendOrder 번호의 평가를 위한 별도의 숫자 공간(numberspace)을 설정합니다.

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

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

8.1. 메서드

getStats()

this sendGroup 아래에 그룹화된 모든 WebTransportSendStream의 통계를 집계하고, 그 결과를 비동기적으로 보고한다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis.[[Transport]]로 둔다.

  2. p를 새 promise로 둔다.

  3. streams[[SendGroup]]this인 모든 WebTransportSendStream으로 둔다.

  4. 다음 단계들을 병렬로 실행한다:

    1. gatheredStatsWebTransportSendStreamStats사전 멤버를 정확히 채우는 데 필요한, streams의 모든 스트림에서 나온 집계된 통계의 목록으로 둔다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. statsWebTransportSendStreamStats 객체로 둔다.

      2. 사용자 에이전트가 노출하려는 stats의 각 멤버 member에 대해, membergatheredStats의 해당 항목으로 설정한다.

      3. statspResolve한다.

  5. p를 반환한다.

8.2. 내부 슬롯

WebTransportSendGroup 객체는 다음과 같은 내부 슬롯을 가진다.

내부 슬롯 설명 (비규범적)
[[Transport]] WebTransport 객체가 소유하고 있는 WebTransportSendGroup.

8.3. 절차

생성을 하려면, WebTransportSendGroupWebTransport transport와 함께, 다음 단계를 실행한다:

  1. sendGroupnew WebTransportSendGroup으로, 다음과 같이 생성한다:

    [[Transport]]

    transport

  2. sendGroup을 반환한다.

9. 인터페이스 WebTransportReceiveStream

WebTransportReceiveStreamReadableStream 으로, 수신 단방향 또는 양방향 WebTransport 스트림을 통해 서버로부터 데이터를 스트리밍 받을 수 있는 기능을 제공합니다.

이 객체는 ReadableStream 타입의 Uint8Array 데이터로, 서버에서 수신한 데이터를 읽어서 소비할 수 있습니다. WebTransportReceiveStreamreadable byte stream이기 때문에 소비자는 BYOB reader기본 리더(default reader) 모두 사용할 수 있습니다.

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

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

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

9.1. 메서드

getStats()

WebTransportReceiveStream의 성능에 특정한 통계를 수집하고, 그 결과를 비동기적으로 보고한다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. transportthis.[[Transport]]로 둔다.

  2. p를 새 promise로 둔다.

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

    1. gatheredStatsWebTransportReceiveStreamStats사전 멤버를 정확히 채우는 데 필요한, this WebTransportReceiveStream에 특정한 통계의 목록으로 둔다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      1. statsWebTransportReceiveStreamStats 객체로 둔다.

      2. 사용자 에이전트가 노출하려는 stats의 각 멤버 member에 대해, membergatheredStats의 해당 항목으로 설정한다.

      3. statspResolve한다.

  4. p를 반환한다.

9.2. 내부 슬롯

WebTransportReceiveStream 객체는 다음과 같은 내부 슬롯을 가지고 있습니다.

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

9.3. 절차

들어오는 단방향 또는 양방향 WebTransport 스트림 internalStreamWebTransport transportWebTransportReceiveStream생성하려면, 다음 단계를 실행한다:

  1. stream을 다음을 가진 WebTransportReceiveStream 객체로 둔다:

    [[InternalStream]]

    internalStream

    [[Transport]]

    transport

  2. pullAlgorithmstream에서 바이트를 가져오는 동작으로 둔다.

  3. cancelAlgorithmreason이 주어졌을 때 reason으로 stream취소하는 동작으로 둔다.

  4. 바이트 읽기 지원으로 설정stream에 수행하며, pullAlgorithmpullAlgorithm으로 설정하고 cancelAlgorithmcancelAlgorithm으로 설정한다.

  5. streamtransport.[[ReceiveStreams]]추가한다.

  6. stream을 반환한다.

WebTransportReceiveStream stream에서 바이트를 가져오려면, 다음 단계를 실행한다.

  1. transportstream.[[Transport]]로 둔다.

  2. internalStreamstream.[[InternalStream]]으로 둔다.

  3. promise를 새 promise로 둔다.

  4. buffer, offset, maxBytes를 null로 둔다.

  5. stream에 대한 stream현재 BYOB 요청 뷰가 null이 아니면:

    1. offsetstream현재 BYOB 요청 뷰.[[ByteOffset]]으로 설정한다.

    2. maxBytesstream현재 BYOB 요청 뷰바이트 길이로 설정한다.

    3. bufferstream현재 BYOB 요청 뷰기저 버퍼로 설정한다.

  6. 그렇지 않으면:

    1. offset을 0으로 설정한다.

    2. maxBytes구현 정의 크기로 설정한다.

    3. buffermaxBytes 크기를 가진 ArrayBuffer 객체로 설정한다. ArrayBuffer 할당에 실패하면, RangeError거부된 promise를 반환한다.

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

    1. internalStream에서 읽힌 바이트를 offset 오프셋으로 buffer에, 최대 maxBytes 바이트까지 쓴다. 적어도 하나의 바이트가 읽히거나 FIN이 수신될 때까지 기다린다. read를 읽힌 바이트 수로 두고, hasReceivedFIN을 FIN이 동반되었는지 여부로 둔다.

      사용자 에이전트는 전송 성능을 향상시키기 위한 버퍼를 가질 수 있다. 이러한 버퍼는 서버에 배압 정보를 전달하기 위해 고정된 상한을 가지는 것이 좋다.

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

    2. 이전 단계가 실패했다면, 남은 단계를 중단한다.

      참고: 여기서는 promise를 reject하지 않는다. 네트워크 오류는 다른 곳에서 처리하며, 그 단계들은 stream에러 처리하여, 이 pull을 기다리는 모든 읽기 요청을 reject하기 때문이다.

    3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계들을 실행한다:

      참고: 위에서 설명한 버퍼를 이 절차가 실행 중인 이벤트 루프에서 사용할 수 있으면, 다음 단계들은 즉시 실행될 수 있다.

      1. read > 0이면:

        1. viewbuffer, offsetread로 된 새 Uint8Array로 설정한다.

        2. viewstreamenqueue한다.

      2. hasReceivedFIN이 true이면:

        1. transport.[[ReceiveStreams]]에서 stream제거한다.

        2. stream닫는다.

      3. promise를 undefined로 Resolve한다.

  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을 사용하는 경우, 코드는 [WEB-TRANSPORT-HTTP3]에 설명된 것처럼 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 숫자로 인코딩된다.

  8. transport.[[SendStreams]]에서 stream제거한다.

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

    1. internalStream에서 code수신을 중단한다.

    2. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

      참고: 위에서 설명한 버퍼를 이 절차가 실행 중인 이벤트 루프에서 사용할 수 있으면, 다음 단계들은 즉시 실행될 수 있다.

      1. transport.[[ReceiveStreams]]에서 stream제거한다.

      2. promise를 undefined로 Resolve한다.

  10. promise를 반환한다.

9.4. 서버로부터 송신 중단 신호 받기

WebTransportReceiveStream stream과 연결된 WebTransport 스트림이 서버로부터 송신 중단됨 신호를 받으면, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 둔다.

  2. code송신 중단됨 신호에 첨부된 애플리케이션 프로토콜 오류 코드로 둔다.

    참고: code의 유효한 값은 0부터 4294967295까지이다. 기저 연결이 HTTP/3을 사용하는 경우, 코드는 [WEB-TRANSPORT-HTTP3]에 설명된 것처럼 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 숫자로 인코딩된다.

  3. transport와 함께 네트워크 작업을 큐에 넣어 다음 단계를 실행한다:

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

    2. transport.[[ReceiveStreams]]에서 stream제거한다.

    3. errorWebTransportError로 새로 생성된 객체로 두며, 그 객체의 source"stream"이고 streamErrorCodecode이다.

    4. streamerror에러 처리한다.

9.5. WebTransportReceiveStreamStats 사전

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

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

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

bytesReceived, 타입 unsigned long long

WebTransportReceiveStream을(를) 위해 서버 애플리케이션이 전송한 바이트 중 지금까지 수신된 바이트의 진행 상황을 나타낸다. 누락된 첫 바이트 전까지의 순차 바이트만 포함하며, 이 숫자는 증가만 한다.

Note: 이는 단일 스트림에서 받은 앱 데이터의 진행률만 나타내며, 네트워크 오버헤드는 포함하지 않는다.

bytesRead, 타입 unsigned long long

애플리케이션이 이 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 WebTransportBidirectionalStream 을(를) 양방향(bidirectional) WebTransport 스트림 internalStream, WebTransport 객체 transport, sendOrder와 함께 생성하려면 다음 단계를 실행한다.
  1. readableWebTransportReceiveStream 생성 결과로 두되, 인자는 internalStreamtransport를 넘긴다.

  2. writableWebTransportSendStream 생성 결과로 두되, 인자는 internalStream, transport, sendOrder를 넘긴다.

  3. stream새로운 WebTransportBidirectionalStream으로 하고, 다음 슬롯들로 초기화한다:

    [[Readable]]

    readable

    [[Writable]]

    writable

    [[Transport]]

    transport

  4. stream을 반환한다.

11. WebTransportWriter 인터페이스

WebTransportWriterWritableStreamDefaultWriter 의 서브클래스로, 두 개의 메서드가 추가된다.

WebTransportWriter 는 항상 생성(create) 절차에 의해 생성된다.

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

11.1. 메서드

atomicWrite(chunk)

atomicWrite 메서드는 전달된 chunk를 전송 시점의 현재 흐름 제어 윈도우 내에서 전체로 보낼 수 없으면 reject한다. 이 동작은 흐름 제어 교착 상태에 민감한 특수한 트랜잭션 애플리케이션을 만족시키도록 설계되었다([RFC9308] Section 4.4).

참고: atomicWrite는 일부 데이터를 보낸 뒤에도 reject될 수 있다. 흐름 제어와 관련해서는 원자성을 제공하지만, 다른 오류가 발생할 수 있다. atomicWrite는 데이터가 패킷 사이에서 나뉘거나 다른 데이터와 인터리브되는 것을 막지 않는다. 사용 가능한 흐름 제어 크레딧 부족으로 인해 atomicWrite가 실패했는지는 송신자만 알 수 있다.

참고: 원자적 쓰기는 비원자적 쓰기 뒤에 큐에 있으면 여전히 block될 수 있다. 원자적 쓰기가 reject되면, 그 시점에 그 뒤에 큐에 있던 모든 것도 함께 reject된다. 이 방식으로 reject된 모든 비원자적 쓰기는 스트림을 error 처리한다. 따라서 애플리케이션은 항상 원자적 쓰기를 await하는 것이 권장된다.

호출되면 사용자 에이전트는 MUST 다음 단계를 실행한다:

  1. streamthis.stream으로 둔다.

  2. stream이 undefined이면, TypeError거부된 promise를 반환한다.

  3. stream.[[InsideSynchronousAtomicWrite]]를 true로 설정한다.

  4. pchunkthis쓰는 결과로 둔다.

  5. stream.[[InsideSynchronousAtomicWrite]]를 false로 설정한다.

  6. pstream.[[AtomicWriteRequests]]추가한다.

  7. p에 다음 단계들로 반응한 결과를 반환한다:

    1. stream.[[AtomicWriteRequests]]p포함하면, p제거한다.

    2. p가 이유 r로 reject되었으면, r거부된 promise를 반환한다.

    3. undefined를 반환한다.

commit()

commit 메서드는 스트림의 [[CommittedOffset]] 을 해당 스트림에 기록된 바이트 수([[BytesWritten]]) 로 갱신한다. 이로써 abort 이후에도 해당 바이트는 abort 되어 송신 중단된 경우에도 피어에 확실히 전달됨을 보장한다. 이 동작은 [RELIABLE-RESET]의 메커니즘을 사용한다.

Note: 연결 자체가 끊어진 경우에는 전달의 보증은 되지 않으며, 스트림이 송신 중단(aborted) 되었을 때만 해당한다.

commitstream에 대해 호출되면, 유저 에이전트는 다음 단계를 수행한다:

  1. stream.[[CommittedOffset]]stream.[[BytesWritten]] 값으로 설정한다.

11.2. 절차

WebTransportWriter 생성을 하려면, WebTransportWriterWebTransportSendStream stream을 넘겨 다음 단계를 수행한다:

  1. writer새로운 WebTransportWriter로 둔다.

  2. stream에 대해 writer설정한다.

  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

    참고: 이 이름은 레거시 코드와 매핑되지 않으므로 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 효과
세션이 draining 상태로 시작됨 await wt.draining

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

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

API 메서드 QUIC 프로토콜 동작
writable.abort(error) STREAM의 전송 중단(aborts sending), httpErrorCode와 [[CommittedOffset]] (해당 stream 에 대한 값) 및 stream header 포함; [RELIABLE-RESET] 참고
writable.close() FIN 비트가 설정된 STREAM 전송
writable.getWriter().write(chunk)() STREAM 전송
writable.getWriter().close() FIN 비트가 설정된 STREAM 전송
writable.getWriter().abort(error) STREAM의 전송 중단(aborts sending), httpErrorCode와 [[CommittedOffset]] (해당 stream 에 대한 값) 및 stream header 포함; [RELIABLE-RESET] 참고
readable.cancel(error) STREAM 수신 중단(aborts receiving), httpErrorCode와 함께
readable.getReader().cancel(error) STREAM 수신 중단(aborts receiving), httpErrorCode와 함께
wt.close(closeInfo) 세션 종료(terminate), closeInfo와 함께
QUIC 프로토콜 동작 API 효과
httpErrorCode와 함께 STOP_SENDING 수신 에러(errors) writable , streamErrorCode
STREAM 수신(received) (await readable.getReader().read()).value
FIN 비트가 설정된 STREAM 수신 (await readable.getReader().read()).done
httpErrorCode와 함께 RESET_STREAM 수신 에러(errors) readable , streamErrorCode
세션이 clean하게 종료(terminated), closeInfo와 함께
(await wt.closed).closeInfo, 및 열린 스트림에 에러
네트워크 오류
(await wt.closed) rejected, 열린 스트림에 에러

참고: [QUIC] RFC9000 3.2장에서 논의된 바와 같이, RESET_STREAM 프레임이나 RESET_STREAM_AT 프레임([RELIABLE-RESET])의 수신은 항상 애플리케이션에 바로 표시되는 것은 아닙니다. 리셋 수신 신호는 즉시 전달될 수 있으며, 스트림 데이터 전달이 중단되고 소비되지 않은 데이터는 폐기될 수 있습니다. 하지만 즉시 신호 전달이 반드시 필요한 것은 아닙니다. 특히 RESET_STREAM_AT 프레임의 Reliable Size 필드에 표시된 데이터 전달을 허용하기 위해 신호가 지연될 수 있습니다. 스트림 데이터가 완전히 수신되었지만 애플리케이션에서 아직 읽지 않은 경우에는 송신 중단 신호가 생략될 수 있습니다. WebTransport는 항상 스트림 헤더의 신뢰성 전달을 보장하기 위해 RESET_STREAM_AT 프레임을 사용합니다; 자세한 내용은 HTTP/3 4.1장HTTP/3 4.2장 그리고 [WEB-TRANSPORT-HTTP3] 참고.

HTTP/3 프로토콜 동작 API 효과
세션이 draining 상태로 시작됨 await wt.draining

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

API 메서드 HTTP/2 프로토콜 동작
writable.abort(error) WT_STREAM 전송 중단(aborts sending), error와 함께
writable.close() FIN 비트가 설정된 WT_STREAM 전송
writable.getWriter().write() WT_STREAM 전송
writable.getWriter().close() FIN 비트가 설정된 WT_STREAM 전송
writable.getWriter().abort(error) WT_STREAM 전송 중단(aborts sending), error와 함께
readable.cancel(error) WT_STREAM 수신 중단(aborts receiving), error와 함께
readable.getReader().cancel(error) WT_STREAM 수신 중단(aborts receiving), error와 함께
wt.close(closeInfo) 세션 종료(terminates), closeInfo와 함께
HTTP/2 프로토콜 동작 API 효과
error와 함께 WT_STOP_SENDING 수신 에러(errors) writable , streamErrorCode
WT_STREAM 수신(received) (await readable.getReader().read()).value
FIN 비트가 설정된 WT_STREAM 수신 (await readable.getReader().read()).done
error와 함께 WT_RESET_STREAM 수신 에러(errors) readable , streamErrorCode
세션이 clean하게 종료(terminated), closeInfo와 함께
(await wt.closed).closeInfo, 및 열린 스트림에 에러
네트워크 오류
(await wt.closed) rejected, 열린 스트림에 에러
세션이 draining 시작 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 프로토콜이 사용 중임을 인지하도록 하고, 원격 서버가 WebTransport 프로토콜 사용에 동의함을 확인한다. [WEB-TRANSPORT-HTTP3]는 ALPN [RFC7301], HTTP/3 설정, 그리고 WebTransport 프로토콜을 식별하기 위한 :protocol pseudo-header의 조합을 사용한다. [WEB-TRANSPORT-HTTP2]는 ALPN, HTTP/2 설정, 그리고 WebTransport 프로토콜을 식별하기 위한 :protocol pseudo-header의 조합을 사용한다.

  2. 전송 세션을 시작한 리소스의 오리진에 기반하여 서버가 연결을 필터링할 수 있도록 허용한다. 세션 설정 요청의 Origin 헤더 필드가 이 정보를 담는다.

프로토콜 보안 관련 고려사항은 보안 고려사항(Security Considerations) 섹션에서 설명되어 있습니다. [WEB-TRANSPORT-OVERVIEW] 섹션 6, [WEB-TRANSPORT-HTTP3] 섹션 8, 그리고 [WEB-TRANSPORT-HTTP2] 섹션 9에서 확인할 수 있습니다.

네트워킹 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()WebSocket)에서도 제공된다는 점을 인식하는 것이 중요하다. 따라서 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(Bring Your Own Buffer 리더)를 사용할 수 있습니다. BYOB 리더를 사용하면 버퍼 할당을 더욱 정밀하게 제어할 수 있어 복사를 방지할 수 있습니다. 이 예제에서는 64 kibibytes 메모리 버퍼에 데이터그램을 읽어옵니다.

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읽기 가능한 바이트 스트림(readable byte streams)이므로, BYOB 리더(reader)를 사용할 수 있습니다. BYOB 리더를 사용하면 버퍼 할당을 더 정밀하게 제어할 수 있어 복사 과정을 피할 수 있습니다. 아래 예제는 WebTransportReceiveStream에서 처음 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. Content Security Policy Level 3. 2026년 5월 5일. WD. URL: https://www.w3.org/TR/CSP3/
[CSS2]
Bert Bos; 외. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) 명세. 2011년 6월 7일. REC. URL: https://www.w3.org/TR/CSS2/
[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT-6.0]
Allen Wirfs-Brock. ECMA-262 6판, ECMAScript 2015 언어 명세. 2015년 6월. 표준. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[ENCODING]
Anne van Kesteren. Encoding 표준. 현행 표준. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 표준. 현행 표준. URL: https://fetch.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. 고해상도 시간. 2026년 3월 24일. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; 외. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[QUIC]
Jana Iyengar; Martin Thomson. QUIC: UDP 기반 다중화 보안 전송. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9000
[QUIC-DATAGRAM]
Tommy Pauly; Eric Kinnear; David Schinazi. QUIC에 대한 신뢰할 수 없는 데이터그램 확장. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9221
[RFC2119]
S. Bradner. RFC에서 요구 수준을 나타내기 위해 사용하는 핵심 단어. 1997년 3월. 현재 최선 관행. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3279]
L. Bassham; W. Polk; R. Housley. 인터넷 X.509 공개 키 기반구조 인증서 및 인증서 폐기 목록(CRL) 프로파일을 위한 알고리즘과 식별자. 2002년 5월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc3279/
[RFC5280]
D. Cooper; 외. 인터넷 X.509 공개 키 기반구조 인증서 및 인증서 폐기 목록(CRL) 프로파일. 2008년 5월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc5280/
[RFC8174]
B. Leiba. RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. 2017년 5월. 현재 최선 관행. URL: https://www.rfc-editor.org/info/rfc8174/
[RFC8422]
Y. Nir; S. Josefsson; M. Pegourie-Gonnard. TLS 버전 1.2 및 이전 버전을 위한 타원 곡선 암호화(ECC) 암호 스위트. 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc8422/
[RFC8441]
P. McManus. HTTP/2로 WebSocket 부트스트래핑. 2018년 9월. 제안 표준. URL: https://httpwg.org/specs/rfc8441.html
[RFC9002]
J. Iyengar, Ed.; I. Swett, Ed.. QUIC 손실 감지 및 혼잡 제어. 2021년 5월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc9002/
[RFC9220]
R. Hamilton. HTTP/3로 WebSocket 부트스트래핑. 2022년 6월. 제안 표준. URL: https://httpwg.org/specs/rfc9220.html
[RFC9525]
P. Saint-Andre; R. Salz. TLS에서의 서비스 신원. 2023년 11월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc9525/
[STREAMS]
Adam Rice; 외. Streams 표준. 현행 표준. URL: https://streams.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 표준. 현행 표준. URL: https://url.spec.whatwg.org/
[WEB-TRANSPORT-HTTP2]
Alan Frindell; 외. HTTP/2를 통한 WebTransport. 인터넷 초안. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http2
[WEB-TRANSPORT-HTTP3]
Alan Frindell; Eric Kinnear; Victor Vasiliev. HTTP/3를 통한 WebTransport. 인터넷 초안. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3
[WEB-TRANSPORT-OVERVIEW]
Victor Vasiliev. WebTransport 프로토콜 프레임워크. 인터넷 초안. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-overview
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBSOCKETS]
Adam Rice. WebSockets 표준. 현행 표준. URL: https://websockets.spec.whatwg.org/

참고용 참고문헌

[RELIABLE-RESET]
Marten Seemann; 奥一穂. 부분 전달을 수반하는 QUIC 스트림 리셋. 인터넷 초안. URL: https://datatracker.ietf.org/doc/html/draft-ietf-quic-reliable-stream-reset
[RFC7301]
S. Friedl; 외. 전송 계층 보안(TLS) 애플리케이션 계층 프로토콜 협상 확장. 2014년 7월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc7301/
[RFC8446]
E. Rescorla. 전송 계층 보안(TLS) 프로토콜 버전 1.3. 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc8446/
[RFC9308]
M. Kühlewind; B. Trammell. QUIC 전송 프로토콜의 적용 가능성. 2022년 9월. 정보 제공. URL: https://www.rfc-editor.org/info/rfc9308/
[UNSANCTIONED-TRACKING]
Mark Nottingham. 승인되지 않은 웹 추적. 2015년 7월 17일. TAG Finding. URL: https://www.w3.org/2001/tag/doc/unsanctioned-tracking/

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 unsigned long incomingMaxBufferedDatagrams;
  attribute unsigned long outgoingMaxBufferedDatagrams;
};

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

  Promise<WebTransportConnectionStats> getStats();
  [NewObject] Promise<Uint8Array> exportKeyingMaterial(BufferSource label, BufferSource context, unsigned long outputLength);
  readonly attribute Promise<undefined> ready;
  readonly attribute WebTransportReliabilityMode reliability;
  readonly attribute WebTransportCongestionControl congestionControl;
  attribute [EnforceRange] unsigned short? anticipatedConcurrentIncomingUnidirectionalStreams;
  attribute [EnforceRange] unsigned short? anticipatedConcurrentIncomingBidirectionalStreams;
  [SameObject] readonly attribute Headers? responseHeaders;
  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 {
  required DOMString algorithm;
  required BufferSource value;
};

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

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;
  unsigned long long bytesSentOverhead;
  unsigned long long bytesAcknowledged;
  unsigned long long packetsSent;
  unsigned long long bytesLost;
  unsigned long long packetsLost;
  unsigned long long bytesReceived;
  unsigned long long packetsReceived;
  DOMHighResTimeStamp smoothedRtt;
  DOMHighResTimeStamp rttVariation;
  DOMHighResTimeStamp minRtt;
  required WebTransportDatagramStats datagrams;
  unsigned long long? estimatedSendRate = null;
  boolean atSendCapacity = false;
};

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

[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;
  unsigned long long bytesSent;
  unsigned long long bytesAcknowledged;
};

[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;
  unsigned long long bytesRead;
};

[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)으로 간주됩니다. 작성 시점 기준입니다.

bytesAcknowledged on WebTransportConnectionStats 는 구현 가능성 문제로 워킹 그룹에 의해 위험(feature at risk) 항목으로 지정되었습니다.