WebTransport

W3C 작업 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-webtransport-20260325/
최신 공개 버전:
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 객체가 아니라면, 거부된 promise와 함께 TypeError를 반환한다.

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

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

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

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

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

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

  9. writable.[[OutgoingDatagramsQueue]]의 길이가 datagrams.[[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()

WebTransportDatagramsWritable을(를) 생성합니다.

createWritable() 메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
  1. transportthis에 연관된 WebTransport 객체로 설정합니다.

  2. 만약 transport.[[State]]"closed" 또는 "failed"이면, throw InvalidStateError를 발생시킵니다.

  3. sendGroupoptionssendGroup으로 설정합니다.

  4. 만약 sendGroup이 null이 아니고, sendGroup.[[Transport]]this.[[Transport]]와 다르면, throw InvalidStateError를 발생시킵니다.

  5. sendOrderoptionssendOrder로 설정합니다.

  6. transport, sendGroup, sendOrder생성WebTransportDatagramsWritable을(를) 반환합니다.

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 요청 뷰(current BYOB request view)가 null이 아니라면:

      1. viewdatagrams.[[Readable]]현재 BYOB 요청 뷰로 설정한다.

      2. view바이트 길이(byte length)datagram 크기보다 작다면, 거부된 promise와 함께 RangeError를 반환한다.

      3. elementSizeTypedArray 생성자 테이블에서 view.[[TypedArrayName]]에 해당하는 요소 크기로 설정한다. 만약 view에 [[TypedArrayName]] 내부 슬롯이 없으면(DataView인 경우), elementSize를 0으로 한다.

      4. elementSize가 1이 아니라면, 거부된 promise와 함께 TypeError를 반환한다.

    2. 바이트로부터 Pull을 호출하여 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, optional BufferSource context);
  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() 생성자가 호출되면, UA는 아래 단계를 따라야 한다:
  1. baseURLthis관련 설정 객체API 기본 URL로 한다.

  2. urlURL 레코드로 하며, 파싱 결과 urlbaseURL을 이용한다.

  3. 만약 url이 failure라면, 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"가 아니고, 사용자 에이전트가 congestionControl에 최적화된 혼잡 제어 알고리즘을 지원하지 않는 경우 [RFC9002] Section 7에 따라, 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]]

    비어있는 정렬된 집합(ordered set)

    [[ReceiveStreams]]

    비어있는 정렬된 집합(ordered set)

    [[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]]생성 결과로, WebTransportDatagramDuplexStream, transport, incomingDatagrams, datagramsReadableType로서 설정한다.

  20. pullDatagramsAlgorithmpullDatagramstransport에 대해 실행하는 동작으로 한다.

    Note: datagrams에서는 64 kibibytes 버퍼 사용이 권장된다. WebTransport datagram 프레임의 실질적인 최대 크기는 QUIC의 datagram 최대 프레임 크기에 따라 상한이 64 kibibyte이다. (See [QUIC-DATAGRAM] Section 3) 이는 datagram이 버퍼보다 커서 스트림이 에러나는 상황을 예방한다.

  21. datagramsReadableType"bytes"인 경우, 바이트 읽기 지원으로 설정 incomingDatagramspullAlgorithmpullDatagramsAlgorithm으로, highWaterMark 를 0으로 설정. 그 외에는 설정pullAlgorithmpullDatagramsAlgorithm으로, highWaterMark를 0으로 설정.

  22. pullBidirectionalStreamAlgorithmpullBidirectionalStreamtransport에 대해 실행하는 동작으로 한다.

  23. 설정 transport.[[IncomingBidirectionalStreams]]pullAlgorithmpullBidirectionalStreamAlgorithm으로, highWaterMark를 0으로 설정.

  24. pullUnidirectionalStreamAlgorithmpullUnidirectionalStreamtransport에 대해 실행하는 동작으로 한다.

  25. 설정 transport.[[IncomingUnidirectionalStreams]]pullAlgorithmpullUnidirectionalStreamAlgorithm으로, highWaterMark를 0으로 설정.

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

  27. originclientorigin으로 한다.

  28. request를 새로운 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"이다.

    Note: 리다이렉트는 따라가지 않는다. 리다이렉션으로 인한 네트워크 에러는 의도적으로 다른 네트워크 에러와 구분되지 않는다. 크로스-오리진 환경에서는 일반적으로 CORS로 차단되는 정보를 드러낼 수 있다. same-origin에서도 핸드셰이크를 정보 전달 경로로 남용할 우려가 있다.

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

  30. headers를 새로운 Headers 객체로 하며, 채워진 options["headers"] 값을 사용한다.

  31. requestHeaders를 새로운 Headers 객체로 하며 헤더 목록(header list)requestheader list, guard는 "request"이다.

  32. headersheader list의 각 header마다:

    1. ascii 소문자 header이름(name)이 "wt-available-protocols"이면, TypeError를 던진다.

    2. append headerrequestHeaders에 추가한다.

    Note: 헤더는 Fetch의 forbidden request-header 제한을 받는다.

  33. protocols가 비어있지 않다면, 구조화 필드 값(set a structured field value)을 (WT-Available-Protocols, 구조화 헤더 리스트protocols 구조화 헤더 문자열(string) 항목이 순서대로 포함됨)로 requestheader list에 설정한다.

  34. Fetch request를 실행하며, useParallelQueue는 true, processResponseresponse가 주어질 때 다음 단계로 설정:

    1. WebTransport fetch response 처리responsetransport로 실행한다.

  35. transport를 반환한다.

WebTransport 연결 얻기 알고리즘: network partition key networkPartitionKey, request request를 받으면:
  1. transportWebTransport로, request에 대응하는 객체로 설정한다.

  2. urlrequestcurrent URL로 설정한다.

  3. newConnectiontransport.[[NewConnection]] 값으로 설정한다.

  4. requireUnreliabletransport.[[RequireUnreliable]] 값으로 설정한다.

  5. webTransportHashesrequestWebTransport-hash list 값들로 설정한다.

  6. connectionobtaining a connection 알고리즘을 networkPartitionKey, url, false, newConnection, requireUnreliable, webTransportHashes로 실행한 결과로 설정한다.

  7. connection이 failure면, failure 반환.

  8. connection에서 첫 SETTINGS 프레임을 받을 때까지 대기, settings를 SETTINGS 프레임을 나타내는 딕셔너리로 설정.

  9. settingsSETTINGS_ENABLE_CONNECT_PROTOCOL (0x08, Section 3 of [RFC8441] (HTTP/2); 0x08, Section 3 of [RFC9220] (HTTP/3)) 값이 1이 아니라면, failure 반환.

  10. settings가 서버의 WebTransport 지원을 나타내지 않으면, failure 반환. [WEB-TRANSPORT-OVERVIEW] Section 4.1.

    참고: SETTINGS_WT_MAX_SESSIONS는 IETF에서 변경될 수 있으며 SETTINGS_ENABLE_WEBTRANSPORT로 바뀔 수도 있음.

  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 세션을 종료합니다.

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

  1. transportthis로 설정합니다.

  2. transport.[[State]] 값이 "closed" 또는 "failed"이면 단계 종료.

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

    1. error를 새 WebTransportError로 만듭니다. source 값을 "session"으로 설정합니다.

    2. Cleanup transporterror로 실행합니다.

    3. 단계 종료.

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

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

  6. reasonStringcode unit prefix의 최대 길이로, closeInfo.reason 값에서 UTF-8 인코딩 길이가 1024를 넘지 않도록 구함.

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

  8. 병렬로 terminatesession, code, reason과 함께 수행합니다.

    참고: 이 단계는 전송 중단 또는 수신 중단WebTransport 스트림에 대해 함께 처리하며, transport.[[SendStreams]][[ReceiveStreams]]에 적용됩니다.

  9. Cleanup transportAbortErrorcloseInfo로 수행.

getStats()

WebTransport하위 연결 에 대한 통계 정보를 비동기로 조회합니다.

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

  1. transportthis로 설정합니다.

  2. p를 새 promise로 설정합니다.

  3. transport.[[State]] 값이 "failed"라면 reject pInvalidStateError와 함께 반환하고 단계 종료.

  4. 아래 단계를 병렬로 수행합니다:

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

    2. transport.[[State]] 값이 "failed"면, queue a network tasktransport로 실행한 후 reject pInvalidStateError로 반환하고 단계 종료합니다.

    3. transport.[[State]] 값이 "closed"면, queue a network tasktransport로 실행한 후 resolve p를 해당 연결의 최신 통계 정보로 반환합니다. 구체적인 수집 시점은 구현 정의입니다.

    4. gatheredStatslist로, 연결의 하위 연결에 맞는 통계 정보를 수집해 WebTransportConnectionStatsWebTransportDatagramStats 구조체의 딕셔너리 멤버에 정확하게 채울 수 있도록 준비합니다.

    5. queue a network tasktransport로 실행하여 아래 단계를 수행합니다:

      1. stats WebTransportConnectionStats 객체로 설정.

      2. datagramStats WebTransportDatagramStats 객체로 설정.

      3. stats["datagrams"] 값을 datagramStats로 설정합니다.

      4. 사용자 에이전트가 노출을 원하는 statsdatagramStats의 각 멤버에 대해, setgatheredStats의 해당 entry로 설정합니다.

      5. Resolve pstats로 해제합니다.

  5. p를 반환합니다.

exportKeyingMaterial(BufferSource label, optional BufferSource context)

WebTransport 의 TLS 세션에서 고유하게 연관된 TLS Keying Material Exporter 로부터 키 재료를 내보냅니다. 하위 연결을 사용합니다.

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

  1. transportthis로 한다.

  2. labelLengthlabel.바이트 길이로 한다.

  3. labelLength가 255보다 크면, 거부된 promise와 함께 RangeError를 반환한다.

  4. contextLength를 0으로 한다.

  5. context가 주어졌다면, contextLengthcontext.바이트 길이로 한다.

  6. contextLength가 255보다 크면, 거부된 promise와 함께 RangeError를 반환한다.

  7. p를 새로운 promise로 한다.

  8. 아래의 단계를 병렬로 실행하되, 아래 조건에서 중단(abort)된다: transport[[State]]"closed" 또는 "failed"가 되면, 네트워크 작업(queue a network task)transport에 대해 큐잉하여 reject p + InvalidStateError:

    1. keyingMaterial Uint8Array 로 하며, TLS key exporter를 호출해서 생성한다. (자세한 내용은 [WEB-TRANSPORT-OVERVIEW] Section 4.1 을 참고), labelLength, label, contextLength, 그리고 context가 있으면 함께 넘긴다.

    2. 네트워크 작업을 큐잉(queue a network task) 하여 transport와 함께 presolve하고 keyingMaterial을 넘긴다.

  9. p를 반환한다.

createBidirectionalStream()

송신용 양방향 스트림을 위한 WebTransportBidirectionalStream 객체를 생성합니다. 스트림이 단순 생성되었다고 해서 즉시 피어가 인지하게 되는 것은 아닙니다. 데이터를 실제로 보내기 전까지는 서버도 스트림의 존재를 알지 못할 수 있습니다.

참고: 스트림에 실제 데이터가 보내지기 전까지 서버는 스트림의 존재를 반드시 인지하지 않습니다.

createBidirectionalStream 호출 시 사용자 에이전트는 다음 단계를 수행해야 합니다:
  1. this.[[State]] 값이 "closed" 또는 "failed"이면, rejected promiseInvalidStateError로 반환합니다.

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

  3. sendGroup이 null이 아니고, sendGroup.[[Transport]] 값이 this가 아니면, throw InvalidStateError 발생.

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

  5. waitUntilAvailableoptionswaitUntilAvailable로 설정.

  6. p를 새 promise로 설정합니다.

  7. transportthis로 설정합니다.

  8. 아래 단계를 병렬로 수행. 단 abort when transport[[State]] 값이 "closed" 또는 "failed"가 되면, queue a network tasktransport로 실행, reject pInvalidStateError로 처리:

    1. streamIdtransport.[[Session]]에 대해 유효하고 고유한 스트림 ID로 새로 만듭니다. [QUIC] Section 19.11 참고. 고갈로 인해 즉시 사용 불가능하다면 waitUntilAvailable이 true면 대기, false면, queue a network tasktransport로 실행해 reject pQuotaExceededError (requested/quota 모두 null).

    2. internalStream양방향 스트림 생성 알고리즘을, transport.[[Session]]streamId를 넘겨 실행한 결과로 설정합니다.

    3. queue a network tasktransport로 실행해 다음을 수행:

      1. transport.[[State]] 값이 "closed" 또는 "failed"면, reject pInvalidStateError와 함께 반환, 단계 종료.

      2. streamWebTransportBidirectionalStream 생성 알고리즘 결과로, internalStream, transport, sendGroup, sendOrder를 넘겨 실행했습니다.

      3. Resolve pstream으로 처리.

  9. p를 반환합니다.

createUnidirectionalStream()

송신용 단방향 스트림을 위한 WebTransportSendStream 객체를 생성합니다. 스트림이 단순 생성되었다고 해서 즉시 서버가 인지하게 되는 것은 아닙니다. 데이터가 실제로 보내지기 전까지는 서버도 스트림의 존재를 알지 못할 수 있습니다.

참고: 데이터가 실제로 보내지기 전까지 서버는 스트림의 존재를 반드시 인지하지 않습니다.

createUnidirectionalStream() 호출 시 사용자 에이전트는 다음 단계를 수행해야 합니다:
  1. this.[[State]] 값이 "closed" 또는 "failed"이면, rejected promiseInvalidStateError로 반환합니다.

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

  3. sendGroup이 null이 아니고, sendGroup.[[Transport]] 값이 this가 아니면, throw InvalidStateError 발생.

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

  5. waitUntilAvailableoptionswaitUntilAvailable로 설정.

  6. p를 새 promise로 설정합니다.

  7. transportthis로 설정합니다.

  8. 아래 단계를 병렬로 수행. 단 abort when transport[[State]] 값이 "closed" 또는 "failed"가 되면, queue a network tasktransport로 실행, reject pInvalidStateError로 처리:

    1. streamIdtransport.[[Session]]에 대해 유효하고 고유한 스트림 ID로 새로 만듭니다. [QUIC] Section 19.11 참고. 고갈로 즉시 사용 불가면 waitUntilAvailable이 true면 대기, false면, queue a network tasktransport로 실행하여 reject pQuotaExceededError로 처리.

    2. internalStream단방향 스트림 생성 알고리즘 결과로, transport.[[Session]]streamId를 넘겨 실행합니다.

    3. queue a network tasktransport로 실행해 다음을 수행:

      1. transport.[[State]] 값이 "closed" 또는 "failed"면, reject pInvalidStateError로 반환, 단계 종료.

      2. streamWebTransportSendStream 생성 알고리즘 결과로, internalStream, transport, sendGroup, sendOrder를 넘겨 실행합니다.

      3. Resolve pstream으로 처리.

  9. p를 반환합니다.

createSendGroup()

WebTransportSendGroup 을 생성합니다.

createSendGroup() 메서드가 호출되면, 사용자 에이전트는 다음 단계를 수행해야 합니다:
  1. this.[[State]] 값이 "closed" 또는 "failed"throw InvalidStateError를 발생시킵니다.

  2. WebTransportSendGroup 생성 알고리즘 결과로, this를 넘겨 실행한 결과를 반환합니다.

6.5. 절차

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

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

  3. outgoingDatagramWritablestransport.[[Datagrams]].[[Writables]]로 설정.

  4. incomingDatagramstransport.[[Datagrams]].[[Readable]]로 설정.

  5. readytransport.[[Ready]]로 설정.

  6. closedtransport.[[Closed]]로 설정.

  7. incomingBidirectionalStreamstransport.[[IncomingBidirectionalStreams]]로 설정.

  8. incomingUnidirectionalStreamstransport.[[IncomingUnidirectionalStreams]]로 설정.

  9. transport.[[SendStreams]] 를 빈 set으로 설정.

  10. transport.[[ReceiveStreams]] 를 빈 set으로 설정.

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

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

  13. closeInfo가 주어지면, transport.[[State]]"closed"로, 아니면 transport.[[State]]"failed"로 설정.

  14. For each stream in sendStreams에 대해 다음 수행:

    1. stream.[[PendingOperation]] 가 null이 아니면 stream.[[PendingOperation]]error로 reject.

    2. Error streamerror로 처리.

  15. For each stream in receiveStreams: error streamerror로 처리.

    Note: 스크립트 작성자가 Promise resolve에서 동기적으로 코드를 주입할 수 있기 때문에, 여기서 transport의 값은 예측할 수 없이 변할 수도 있어, 이후로는 transport를 조작하지 않는다. 이 동작을 호출하는 로직에서도 마찬가지 주의가 필요하다.

  16. closeInfo가 주어지면 다음을 실행:

    1. Resolve closedcloseInfo를 할당.

    2. Assert: readysettled임을 보장.

    3. Close incomingBidirectionalStreams를 처리.

    4. Close incomingUnidirectionalStreams를 처리.

    5. writable in outgoingDatagramWritables에 대해 close writable 처리.

    6. Close incomingDatagrams을 처리.

  17. 그 외에는,

    1. Reject closederror로.

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

    3. Reject readyerror로.

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

    5. Error incomingBidirectionalStreamserror로.

    6. Error incomingUnidirectionalStreamserror로.

    7. writable in outgoingDatagramWritables에 대해 error writableerror로 처리.

    8. Error incomingDatagramserror로.

queue a network taskWebTransport transport와 일련의 단계 steps로 실행하려면 다음을 수행:

  1. Queue a global tasknetwork task source에 넣고, transportrelevant global object에서 steps를 실행.

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

WebTransport transport와 연결된 WebTransport session종료될 때, 선택적으로 codereasonBytes와 함께 다음 단계를 실행한다:
  1. Queue a network tasktransport에 대해 다음 단계 실행:

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

    2. error를 새로 생성한 WebTransportError로, source"session"로 한다.

    3. closeInfonew WebTransportCloseInfo로 생성한다.

    4. code가 주어진 경우, closeInfocloseCodecode를 설정한다.

    5. reasonBytes가 주어진 경우, closeInforeasonreasonBytesUTF-8 해독값을 할당한다.

      Note: reasonBytes에는 언어나 방향 정보가 없다. First-strong 규칙으로 표시 방향을 추론할 수 있다.

    6. Cleanup transporterrorcloseInfo와 함께 처리한다.

WebTransport transportunderlying connection에 연결 오류가 발생할 때 다음 단계를 실행:
  1. Queue a network tasktransport로 다음 단계 실행:

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

    2. error를 새로 생성한 WebTransportError로, source"session"로 한다.

    3. Cleanup transporterror와 함께 처리한다.

6.7. 컨텍스트 정리 절차

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

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

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

    2. 병렬로(In parallel), terminate를 수행하여 transport.[[Session]]을 종료한다.

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

      1. error를 새로 생성된 WebTransportError로 두되, 그 source"session"으로 한다.

      2. Cleanuptransporterror로 수행한다.

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

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

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

WebTransport 객체의 [[State]]"connecting"일 때는, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 어떤 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태이거나, ready, draining, closed 프로미스가 관찰 중인 경우에는 garbage collection 대상이 되어서는 안 된다.

WebTransport 객체의 [[State]]"connected"일 때는, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 어떤 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태이거나, draining 또는 closed 프로미스가 관찰 중인 경우에는 garbage collection 대상이 되어서는 안 된다.

WebTransport 객체의 [[State]]"draining"일 때는, [[IncomingBidirectionalStreams]], [[IncomingUnidirectionalStreams]], 어떤 WebTransportReceiveStream, 또는 [[Datagrams]].[[Readable]]locked 상태이거나, closed 프로미스가 관찰 중인 경우에는 garbage collection 대상이 되어서는 안 된다.

establishedWebTransport session이 있고 네트워크 전송 대기 중인 데이터가 있는 WebTransport 객체(여기에는 [[Datagrams]].[[OutgoingDatagramsQueue]] 에 포함된 데이터그램이 포함됨)는 garbage collection 대상이 되어서는 안 된다.

WebTransport 객체가 garbage collection의 대상이 되었는데 underlying connection 이 아직 열려 있는 경우, 사용자 에이전트는 반드시 Application Error Code 0 및 Application Error Message ""로 WebTransport session을 종료 해야 한다.

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를 반환한다.

custom certificate requirements는 다음과 같다: 인증서는 [RFC5280]에 정의된 X.509v3 인증서여야 하며, Subject Public Key 필드에서 사용되는 키는 allowed public key algorithms 중 하나여야 하고, 현재 시간은 [RFC5280]의 섹션 4.1.2.5에 정의된 인증서의 유효 기간 내에 있어야 하며 유효 기간의 총 길이는 2주를 초과해서는 안 된다. 사용자 에이전트는 인증서에 대해 추가적인 implementation-defined 요구사항을 부과할 수 있다.

Subject Public Key Info 필드(그리고 그 결과로 TLS CertificateVerify 메시지)에서 사용되는 allowed public key algorithms의 정확한 목록은 implementation-defined이다. 그러나 상호 운용 가능한 기본값을 제공하기 위해 secp256r1 (NIST P-256) named group([RFC3279], Section 2.3.5; [RFC8422])을 사용하는 ECDSA를 포함해야 한다. 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 호출의 프로미스는 이행(settled)되지 않습니다. 기저 연결에 스트림을 생성할 충분한 플로우 컨트롤 크레딧이 생기거나, 연결에서 더 이상 송신 스트림을 생성할 수 없는 상태가 될 때까지 대기합니다. false일 때는, 호출 시 플로우 컨트롤 윈도우가 없다면 프로미스가 reject됩니다.

6.13. WebTransportConnectionStats 딕셔너리

WebTransportConnectionStats 딕셔너리는 WebTransport 세션하위 연결과 관련된 WebTransport 특화 통계 정보를 포함합니다.

참고: pooling이 사용되는 경우, 동일 WebTransport 세션이 같은 connection에 pool될 때 모든 세션이 동일 정보를 받습니다, 즉, 같은 세션network partition key를 공유할 때 정보가 공개됩니다.

참고: 사용 불가능한 통계 정보는 존재하지 않음 상태로 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 보다 작지만, 패킷 손실로 인해 영구적으로 더 적을 수도 있습니다.

bytesAcknowledged (WebTransportConnectionStats) 는 구현 가능성 문제로 워킹 그룹이 위험요소로 지정했습니다.
packetsSent, 타입 unsigned long long

하위 연결 에서 전송한 패킷 개수입니다. 손실된 것으로 판단된 패킷도 포함합니다.

bytesLost, 타입 unsigned long long

하위 연결 에서 손실된 바이트 수입니다(단조 증가하지 않음, 손실된 패킷이 이후에 수신될 수 있음). UDP 또는 다른 외부 프레이밍은 포함하지 않습니다.

packetsLost, 타입 unsigned long long

하위 연결 에서 손실된 패킷 수입니다(단조 증가하지 않음, 손실된 패킷이 이후에 수신될 수 있음).

bytesReceived, 타입 unsigned long long

하위 연결 에서 수신된 전체 바이트 수입니다. 스트림의 중복 데이터 포함. UDP 또는 다른 외부 프레이밍은 제외합니다.

packetsReceived, 타입 unsigned long long

하위 연결 에서 수신된 전체 패킷 수입니다. 처리 불가능한 패킷도 포함합니다.

smoothedRtt, 타입 DOMHighResTimeStamp

[RFC9002] Section 5.3에 정의된 연결에서 현재 관찰된 스무딩 RTT(round-trip time) 값입니다.

rttVariation, 타입 DOMHighResTimeStamp

[RFC9002] Section 5.3에 정의된 연결에서 관찰된 RTT 샘플의 평균 변동값입니다.

minRtt, 타입 DOMHighResTimeStamp

[RFC9002] Section 5.2에 정의된 전체 연결에서 관찰된 최소 RTT(round-trip time) 값입니다.

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

사용자 에이전트가 큐에 있는 데이터를 초당 비트 단위로 전송할 것으로 추정되는 속도입니다. 이 속도는 동일 WebTransport 세션 을 공유하는 모든 스트림 및 datagram에 적용됩니다. 혼잡 제어 알고리즘(예: congestionControl로 선택 가능)이 계산합니다. 이 추정값은 프레이밍 오버헤드는 제외하며 애플리케이션 페이로드 전송 속도를 나타냅니다. 에이전트에 현 시점에서 추정값이 없으면 null이어야 합니다. 이전 결과에서 null이 아니었더라도 null일 수 있습니다.

atSendCapacity, 타입 boolean, 기본값 false

false이면 estimatedSendRate 값이 애플리케이션 제한(application limited)을 의미할 수 있습니다, 즉 애플리케이션이 혼잡 제어기가 허용하는 것보다 훨씬 적은 데이터를 보냄을 뜻합니다. 혼잡 제어기가 애플리케이션 제한 상황에서 네트워크 용량을 부정확하게 추정할 수도 있습니다.

true이면 애플리케이션이 네트워크 최대 용량으로 데이터를 보내고 있고, estimatedSendRate 가 애플리케이션이 사용할 수 있는 네트워크 용량을 반영합니다.

atSendCapacitytrue일 때 estimatedSendRate 값은 ceiling(최대치)를 의미합니다. 애플리케이션 전송 속도가 지속되는 한 estimatedSendRate 가 네트워크 상태에 맞게 적응합니다. 단, estimatedSendRatenull일 수도 있음, atSendCapacity 값이 true여도 마찬가지입니다.

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, 널 허용

getter 단계:

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

setter 단계(value 주어질 때):

  1. value가 null이 아니고 value.[[Transport]] 값이 this.[[Transport]] 값이 아니라면, throw InvalidStateError를 발생시킵니다.

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

sendOrder, 타입 long long

getter 단계:

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

setter 단계(value 주어질 때):

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

7.2. 메서드

getStats()

WebTransportSendStream의 성능에 대한 통계를 수집하여 비동기적으로 보고한다.

getStats가 호출되면, 유저 에이전트는 다음 단계들을 수행해야 한다:

  1. p를 새로운 promise로 둔다.

  2. 아래 단계들을 병렬로 실행한다:

    1. gatheredStats목록(list)으로, 이 this WebTransportSendStream에 특화된 통계를 WebTransportSendStreamStats딕셔너리 멤버들을 정확히 채울 수 있게 수집한다.

    2. 네트워크 작업을 큐잉하여 transport에 다음을 실행한다:

      1. stats새로운 WebTransportSendStreamStats 객체로 둔다.

      2. 유저 에이전트가 노출하려는 stats멤버 member마다, 해당 membergatheredStats의 관련 엔트리(entry)로 설정한다.

      3. Promise를 resolve하여 pstats를 넘긴다.

  3. p를 반환한다.

getWriter()

스트림에 대한 WebTransportWriter를 생성한다.

getWriter 가 호출되면, WebTransportWriter 생성 결과를 this와 함께 반환한다.

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을 반환한다.

write 알고리즘에서 chunkWebTransportSendStream stream에 쓰려면 아래 단계 수행:
  1. transportstream.[[Transport]]로 둔다.

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

  3. promise를 새로운 promise로 둔다.

  4. bytes바이트 시퀀스에서 chunk가 나타내는 복사본으로 둔다.

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

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

  7. inFlightWriteRequeststream.inFlightWriteRequest로 둔다.

  8. atomic을 다음 조건에서 true로 한다: stream.[[AtomicWriteRequests]]inFlightWriteRequest를 포함하거나 stream.[[InsideSynchronousAtomicWrite]] 가 true. 그렇지 않으면 false.

  9. 아래 단계를 병렬로 실행한다:

    1. atomic이 true이고, 현재 흐름 제어(flow control) 윈도우가 bytes 전체를 전송하기에 부족하면, 나머지 단계를 중단하고 네트워크 작업을 큐잉하여 transport에서 다음 하위 단계를 실행:

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

      2. Abort all atomic write requestsstream에 실행한다.

    2. 그 외에는, send bytesstream.[[InternalStream]]에 전송하고 operation이 완료될 때까지 기다린다. 이 전송은 송신 순서 규칙(send-order rules)을 따라야 한다.

      유저 에이전트는 전송 성능 향상을 위해 버퍼를 둘 수 있다. 이런 버퍼는 상한이 정해져 있어야 하며, WebTransportSendStream의 사용자가 backpressure(역압)를 얻을 수 있도록 한다.

      여기서 stream.[[SendOrder]]병렬로 접근한다. 유저 에이전트는 송신 중 이러한 값의 실시간 업데이트에 응답해야 한다(SHOULD). 세부 동작은 구현 정의(implementation-defined)이다.

      Note: 재전송의 순서는 구현 정의(implementation-defined)이지만, 유저 에이전트는 [[SendOrder]] 값이 더 큰 데이터의 재전송을 우선하려고 권장됨.

      이 송신은 흐름 제어 또는 에러가 아닌 경우 starvation이 일어나면 안 된다(MUST NOT starve).

      유저 에이전트는 starvation되지 않은 모든 스트림에 대해 bandwidth를 공정하게 배분해야 한다(SHOULD).

      Note: 여기서 말하는 공정성(fairness)의 정의는 구현 정의이다.

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

      Note: 여기서 promise를 reject하지 않는 이유는 네트워크 오류 처리를 별도 단계에서 수행하여, 그 단계에서 stream.[[PendingOperation]]를 reject하기 때문이다.

    4. 그 외에는, 네트워크 작업을 큐잉하여 transport에 다음 단계 실행:

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

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

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

      4. Promise를 resolve하여 promise에 undefined를 넘긴다.

  10. promise를 반환한다.

Note: 이 알고리즘에서 반환되는 promise(또는, write(chunk)) 의 fulfill은 반드시 청크가 서버에서 ack되었음을 의미하지 않는다. 실제로는 청크가 버퍼에 추가되었음을 의미할 수 있다. 청크가 서버에 도달했는지 확실히 하려면, 서버는 애플리케이션 수준의 ack 메시지를 보내야 한다.

close WebTransportSendStream stream을 닫으려면, 다음 단계를 수행한다:
  1. transportstream.[[Transport]]를 할당한다.

  2. promise에 새로운 promise를 할당한다.

  3. streamtransport.[[SendStreams]]에서 제거한다.

  4. stream.[[PendingOperation]]promise를 할당한다.

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

    1. Send FIN을 stream.[[InternalStream]]에 전송하고, 완료될 때까지 기다린다.

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

    3. 네트워크 작업 큐에서 transport에 대해 아래 단계를 수행한다:

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

      2. Resolve promise를 undefined로 완료한다.

  6. promise를 반환한다.

abort WebTransportSendStream stream을(를) reason과 함께 중단하려면, 다음 단계를 수행한다:
  1. transportstream.[[Transport]]를 할당한다.

  2. promise에 새로운 promise를 할당한다.

  3. code에 0을 할당한다.

  4. streamtransport.[[SendStreams]]에서 제거한다.

  5. reasonWebTransportError이고, reason.[[StreamErrorCode]] 가 null이 아니면, codereason.[[StreamErrorCode]] 값을 할당한다.

  6. code < 0이면, code에 0을 할당한다.

  7. code가 4294967295를 초과하면, code에 4294967295를 할당한다.

  8. committedOffsetstream.[[CommittedOffset]]을 할당한다.

    Note: code의 유효 범위는 0~4294967295이다. 기본 연결 이 HTTP/3을 사용하는 경우, 이 코드는 [WEB-TRANSPORT-HTTP3] 에서 정의한 [0x52e4a40fa8db, 0x52e5ac983162] 범위로 인코딩된다.

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

    1. 중단stream.[[InternalStream]]codecommittedOffset을 인자로 호출한다.

    2. 네트워크 작업 큐에서 transportpromise를 undefined로 해결한다.

  10. promise를 반환한다.

모든 원자적(atomic) 쓰기 요청 중단WebTransportSendStream stream에 대해 실행하려면 다음 단계를 수행:
  1. writeRequestsstream.writeRequests로 한다.

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

  3. writeRequestsrequestsToAbort에 없는 promise를 포함하고 있다면, streamAbortError 에러를 발생시키고, 이 단계를 중단한다.

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

  5. requestsToAbort의 각 promise마다, promiseAbortError로 reject 한다.

  6. 병렬로, requestsToAbort의 각 promise마다, 해당 promise와 연관된 바이트의 전송(sending)을 중단한다.

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

WebTransport 스트림WebTransportSendStream stream과 연관되어 있고, 서버로부터 receiving aborted 신호를 받으면, 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 한다.

  2. codereceiving aborted 신호에 부착된 애플리케이션 프로토콜 오류 코드로 한다.

    Note: code의 유효 값 범위는 0~4294967295까지이다. underlying connection이 HTTP/3을 사용 중이면, 이 코드는 [WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 값으로 인코딩된다.

  3. 네트워크 작업을 큐잉하여 transport에서 다음을 실행한다:

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

    2. Remove streamtransport.[[SendStreams]]에서 제거한다.

    3. error를 새로 생성된 Exception WebTransportError 로 두며, source"stream", streamErrorCodecode 로 한다.

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

    5. Error 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()

WebTransportSendStream들을 grouped 한 sendGroup 아래에서 집계된 통계를 모아 비동기적으로 보고한다.

getStats가 호출되면, 유저 에이전트는 다음 절차를 따라야 한다:

  1. p를 새로운 promise로 한다.

  2. streams를 모든 WebTransportSendStream[[SendGroup]]this인 것들로 모은다.

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

    1. gatheredStats를, streams 내 모든 스트림의 집계된 통계로 WebTransportSendStreamStats 사전 멤버를 정확히 채우는 데 필요한 목록(list)으로 한다.

    2. 네트워크 작업을 큐잉하여 transport에서 아래 단계를 실행:

      1. stats새로운 WebTransportSendStreamStats 객체로 정의한다.

      2. 유저 에이전트가 노출하려는 stats의 각 멤버(member) member에 대해서, 해당 member 값을 gatheredStats의 해당 엔트리(entry)로 설정한다.

      3. promise를 resolve하여 pstats를 넘긴다.

  4. p를 반환한다.

8.2. 내부 슬롯

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

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

8.3. 절차

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

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

    [[Transport]]

    transport

  2. sendGroup을 반환한다.

9. 인터페이스 WebTransportReceiveStream

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

이 객체는 ReadableStream 타입의 Uint8Array 데이터로, 서버에서 수신한 데이터를 읽어서 소비할 수 있습니다. 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의 성능에 대한 통계를 수집하여 비동기적으로 보고한다.

getStats가 호출되면, 유저 에이전트는 다음 단계들을 수행해야 한다:

  1. p를 새로운 promise로 둔다.

  2. 아래 단계들을 병렬로 실행한다:

    1. gatheredStats목록(list)으로, 이 this WebTransportReceiveStream 에 특화된 통계를 WebTransportReceiveStreamStats딕셔너리 멤버들을 정확히 채울 수 있게 수집한다.

    2. 네트워크 작업을 큐잉하여 transport에서 다음 단계를 실행한다:

      1. stats새로운 WebTransportReceiveStreamStats 객체로 둔다.

      2. 유저 에이전트가 노출하려는 stats멤버 member마다, 해당 membergatheredStats의 관련 엔트리(entry)로 설정한다.

      3. Promise를 resolve하여 pstats를 넘긴다.

  3. p를 반환한다.

9.2. 내부 슬롯

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

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

9.3. 절차

WebTransportReceiveStream WebTransportReceiveStream 을(를) 수신 단방향 또는 양방향 WebTransport 스트림 internalStreamWebTransport transport와 함께 생성하려면, 다음 단계를 실행한다:

  1. stream새로운 WebTransportReceiveStream으로, 아래와 같이 생성한다:

    [[InternalStream]]

    internalStream

    [[Transport]]

    transport

  2. pullAlgorithm바이트를 pull하는 동작(액션)으로 설정한다.

  3. cancelAlgorithmcancelstreamreason으로 호출하는 동작(액션)으로 설정한다.

  4. 바이트 읽기 지원으로 set up streampullAlgorithmpullAlgorithm으로 지정하고, cancelAlgorithmcancelAlgorithm으로 설정한다.

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

  6. stream을 반환한다.

WebTransportReceiveStream WebTransportReceiveStream stream에서 바이트를 pull하려면, 다음 단계를 실행한다.

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

  2. internalStreamstream.[[InternalStream]]로 한다.

  3. promise를 새로운 promise로 설정한다.

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

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

    1. offsetstreamcurrent BYOB request view.[[ByteOffset]]로 한다.

    2. maxBytesstreamcurrent BYOB request view바이트 길이로 한다.

    3. bufferstreamcurrent BYOB request viewunderlying buffer로 설정한다.

  6. 그 외에는:

    1. offset을 0으로 한다.

    2. maxBytes구현 정의(implementation-defined) 크기로 한다.

    3. buffer새로운 ArrayBuffer로 하고, 크기는 maxBytes로 한다. 만약 ArrayBuffer 할당에 실패하면, 거부된 promise와 함께 RangeError를 반환한다.

  7. 아래 단계를 병렬로 실행한다:

    1. Writeread된 바이트를 internalStream에서 buffer(offset offset 위치)에 최대 maxBytes만큼 쓴다. 최소 1 바이트라도 읽거나 FIN을 받기 전까지 대기한다. read는 읽힌 바이트 수, hasReceivedFIN은 FIN을 받았는지의 여부로 설정한다.

      유저 에이전트는 성능향상을 위해 내부 버퍼를 둘 수 있다. 이 버퍼는 상한이 정해져 있어야 하며, 서버에 backpressure 정보를 전달할 수 있어야 한다.

      Note: 이 동작은 buffer 전체를 다 채우지 않고 반환될 수 있다.

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

      Note: 여기서 promise를 reject하지 않는 이유는 네트워크 오류 처리를 별도 단계에서 수행하고, 그 단계에서 stream에 에러를 발생시키므로, pull을 기다리는 read 요청이 자동으로 reject된다.

    3. 네트워크 작업을 큐잉하여 transport에 다음 단계 실행:

      Note: 위의 버퍼가 이 프로시저가 실행 중인 event loop 내부에 있다면, 이후 단계는 즉시 실행될 수 있다.

      1. read > 0이면:

        1. viewUint8Array로 새로 생성하며, 인자로 buffer, offset, read를 넘긴다.

        2. Enqueue viewstream에 넣는다.

      2. hasReceivedFIN이 true라면:

        1. streamtransport.[[ReceiveStreams]]에서 제거한다.

        2. Close stream을 호출한다.

      3. Promise를 resolve하여 promise에 undefined를 넘긴다.

  8. promise를 반환한다.

cancel WebTransportReceiveStream streamreason과 함께 취소하려면, 아래 단계를 실행한다.

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

  2. internalStreamstream.[[InternalStream]]로 한다.

  3. promise를 새로운 promise로 둔다.

  4. code를 0으로 한다.

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

  6. code가 0보다 작으면 0으로 설정한다.

  7. code가 4294967295보다 크면 4294967295로 설정한다.

    Note: code의 유효 값 범위는 0~4294967295까지이다. underlying connection이 HTTP/3을 사용 중이면, 이 코드는 [WEB-TRANSPORT-HTTP3]에 따라 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 값으로 인코딩된다.

  8. streamtransport.[[SendStreams]]에서 제거한다.

  9. 아래 단계를 병렬로 실행한다:

    1. abort receivinginternalStreamcode와 함께 호출한다.

    2. 네트워크 작업을 큐잉하여 transport에 다음 단계 실행:

      Note: 위 버퍼가 이 프로시저가 실행 중인 event loop에 있다면, 이하 단계가 즉시 실행될 수 있다.

      1. streamtransport.[[ReceiveStreams]]에서 제거한다.

      2. Promise를 resolve하여 promise에 undefined를 넘긴다.

  10. promise를 반환한다.

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

WebTransport 스트림WebTransportReceiveStream stream과 연관되어 있고, 서버로부터 sending aborted 신호를 받으면 다음 단계를 실행한다:
  1. transportstream.[[Transport]]로 한다.

  2. codesending aborted 신호에 부착된 애플리케이션 프로토콜 오류 코드로 한다.

    Note: code의 유효 값 범위는 0~4294967295이다. underlying connection이 HTTP/3을 사용 중이면, 이 코드는 [0x52e4a40fa8db, 0x52e5ac983162] 범위의 값으로 인코딩된다. (자세한 내용은 [WEB-TRANSPORT-HTTP3] 참고)

  3. 네트워크 작업을 큐잉하여 transport에 다음을 실행한다:

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

    2. streamtransport.[[ReceiveStreams]]에서 제거한다.

    3. error를 새로 생성된 예외 WebTransportError로 두고, 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, 읽기 전용

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

writable, 타입 WebTransportSendStream, 읽기 전용

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).

Note: atomicWrite 는 일부 데이터를 전송한 뒤에도 reject 될 수 있다. 흐름 제어에 대한 원자성은 보장하지만, 다른 에러는 발생할 수 있다. atomicWrite 는 데이터가 패킷 사이에 분할되거나 다른 데이터와 interleave되는 것을 막지 않는다. 흐름 제어 credit 부족으로 인해 atomicWrite 가 실패할 경우, 그 사실을 알 수 있는 건 송신자 뿐이다.

Note: atomic write 역시 non-atomic write가 대기열에 앞서 있을 경우 블록될 수 있다. atomic write가 거부되면, 그 시점에 대기열에 있는 모든 요청도 같이 reject된다. 이 방식으로 reject된 non-atomic write 는 스트림 에러를 발생시킨다. 따라서 애플리케이션에서는 atomic write를 항상 await하도록 권장된다.

atomicWrite(chunk) 가 호출되면, 유저 에이전트는 다음 단계를 수행해야 한다:

  1. streamthis.stream 으로 둔다.

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

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

  4. pchunk 쓰기(write) 결과로 둔다.

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

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

  7. promise settled reaction 으로, p에 대해 아래 단계를 실행한 결과를 반환한다:

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

    2. pr을 reason으로 reject되었으면, 거부된 promise와 함께 r을 반환한다.

    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. SetUpWritableStreamDefaultWriter(writer, stream)를 수행한다.

  3. writer를 반환한다.

12. WebTransportError 인터페이스

WebTransportErrorDOMException 의 하위 클래스입니다.

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

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

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

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

12.1. 내부 슬롯

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

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

12.2. 생성자

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

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

  2. thismessagemessage로 설정합니다.

  3. this의 내부 슬롯을 아래와 같이 설정합니다:

    [[Source]]

    options.source

    [[StreamErrorCode]]

    options.streamErrorCode

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

12.3. 속성

source, 타입 WebTransportErrorSource, 읽기 전용

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

streamErrorCode, 타입 unsigned long, 읽기 전용, 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, [webrtc])에도 있으므로, WebTransport 추가로 인한 프라이버시 악영향은 최소입니다. 이 섹션의 고려사항은 다른 네트워킹 기능에도 똑같이 적용됩니다.

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

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

14.5.1. 정적 관찰

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

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

14.5.2. 공유 네트워킹

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

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

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

14.5.3. 풀링된 세션

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

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

15. 예시

15.1. 데이터그램 버퍼 전송

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

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

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

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

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

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

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

15.3. 데이터그램 수신

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

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

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

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

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

datagrams읽을 수 있는 바이트 스트림이므로, BYOB(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. 콘텐츠 보안 정책 레벨 3(Content Security Policy Level 3). 2026년 3월 11일. WD. URL: https://www.w3.org/TR/CSP3/
[DOM]
Anne van Kesteren. DOM 표준(DOM Standard). Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세서(ECMAScript Language Specification). URL: https://tc39.es/ecma262/multipage/
[ECMASCRIPT-6.0]
Allen Wirfs-Brock. ECMA-262 6th Edition, ECMAScript 2015 언어 명세서. 2015년 6월. 표준. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[ENCODING]
Anne van Kesteren. 인코딩 표준(Encoding Standard). Living Standard. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 표준(Fetch Standard). Living Standard. URL: https://fetch.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. 고정밀 시간(High Resolution Time). 2026년 3월 24일. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML 표준(HTML Standard). Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준(Infra Standard). Living Standard. URL: https://infra.spec.whatwg.org/
[QUIC]
Jana Iyengar; Martin Thomson. QUIC: UDP 기반 다중화 및 보안 전송(QUIC: A UDP-Based Multiplexed and Secure Transport). Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9000
[QUIC-DATAGRAM]
Tommy Pauly; Eric Kinnear; David Schinazi. QUIC에 대한 신뢰성 없는 데이터그램 확장(An Unreliable Datagram Extension to QUIC). Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9221
[RFC2119]
S. Bradner. RFC 내 요구 사항 수준 표시를 위한 키워드(Key words for use in RFCs to Indicate Requirement Levels). 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3279]
L. Bassham; W. Polk; R. Housley. 인터넷 X.509 공개키 인프라 인증서 및 폐기 목록(CRL) 프로파일용 알고리즘 및 식별자(Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile). 2002년 4월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc3279
[RFC5280]
D. Cooper; et al. 인터넷 X.509 공개키 인프라 인증서 및 폐기 목록(CRL) 프로파일(Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile). 2008년 5월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5280
[RFC8174]
B. Leiba. RFC 2119 키워드에서 대문자/소문자의 모호성(Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words). 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8422]
Y. Nir; S. Josefsson; M. Pegourie-Gonnard. 전송 계층 보안(TLS) 버전 1.2 및 이전용 타원 곡선 암호(ECC) 암호군(Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier). 2018년 8월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8422
[RFC8441]
P. McManus. HTTP/2로 WebSockets 부트스트랩(Bootstrapping WebSockets with HTTP/2). 2018년 9월. Proposed Standard. URL: https://httpwg.org/specs/rfc8441.html
[RFC9002]
J. Iyengar, Ed.; I. Swett, Ed.. QUIC 손실 탐지 및 혼잡 제어(QUIC Loss Detection and Congestion Control). 2021년 5월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9002
[RFC9220]
R. Hamilton. HTTP/3로 WebSockets 부트스트랩(Bootstrapping WebSockets with HTTP/3). 2022년 6월. Proposed Standard. URL: https://httpwg.org/specs/rfc9220.html
[RFC9525]
P. Saint-Andre; R. Salz. TLS에서의 서비스 식별(Service Identity in TLS). 2023년 11월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9525
[STREAMS]
Adam Rice; et al. Streams 표준(Streams Standard). Living Standard. URL: https://streams.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 표준(URL Standard). Living Standard. URL: https://url.spec.whatwg.org/
[WEB-TRANSPORT-HTTP2]
Alan Frindell; et al. HTTP/2 기반 WebTransport(WebTransport over HTTP/2). Internet-Draft. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http2
[WEB-TRANSPORT-HTTP3]
Alan Frindell; Eric Kinnear; Victor Vasiliev. HTTP/3 기반 WebTransport(WebTransport over HTTP/3). Internet-Draft. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3
[WEB-TRANSPORT-OVERVIEW]
Victor Vasiliev. WebTransport 프로토콜 프레임워크(WebTransport Protocol Framework). Internet-Draft. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-overview
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준(Web IDL Standard). Living Standard. URL: https://webidl.spec.whatwg.org/

참고용 참고문헌

[RELIABLE-RESET]
Marten Seemann; 奥一穂. 부분 전송이 포함된 QUIC 스트림 리셋(QUIC Stream Resets with Partial Delivery). 인터넷-드래프트. URL: https://datatracker.ietf.org/doc/html/draft-ietf-quic-reliable-stream-reset
[RFC7301]
S. Friedl; et al. TLS 애플리케이션-계층 프로토콜 협상 확장(Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension). 2014년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7301
[RFC8446]
E. Rescorla. TLS 프로토콜 버전 1.3(The Transport Layer Security (TLS) Protocol Version 1.3). 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8446
[RFC9308]
M. Kühlewind; B. Trammell. QUIC 전송 프로토콜의 적용(Applicability of the QUIC Transport Protocol). 2022년 9월. 정보성 문서. URL: https://www.rfc-editor.org/rfc/rfc9308
[UNSANCTIONED-TRACKING]
Mark Nottingham. 무단 웹 추적(Unsanctioned Web Tracking). 2015년 7월 17일. TAG Finding. URL: https://www.w3.org/2001/tag/doc/unsanctioned-tracking/
[WEBRTC]
Cullen Jennings; et al. 브라우저 실시간 통신(WebRTC: Real-Time Communication in Browsers). 2025년 3월 13일. REC. URL: https://www.w3.org/TR/webrtc/

IDL 색인

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

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

  readonly attribute unsigned long maxDatagramSize;
  attribute unrestricted double? incomingMaxAge;
  attribute unrestricted double? outgoingMaxAge;
  attribute 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, optional BufferSource context);
  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) 항목으로 지정되었습니다.