1. 소개
이 섹션은 비규범적입니다.
이 명세서에서 정의된 API는 데이터 스트림을 압축 및 해제하는 데 사용됩니다. 이들은 "deflate", "deflate-raw" 그리고 "gzip" 압축 알고리즘을 지원합니다. 이들은 웹 개발자들에 의해 널리 사용되고 있습니다.
2. 인프라스트럭처
이 명세서는 Infra에 의존합니다. [INFRA]
청크는 데이터의 한 조각입니다. CompressionStream과 DecompressionStream의 경우, 출력 청크 타입은 Uint8Array입니다. 입력으로는 어떤 BufferSource
타입도 허용합니다.
스트림은 청크들의 순서가 지정된 시퀀스를 나타냅니다. ReadableStream
과 WritableStream
용어는 Streams에서 정의됩니다. [STREAMS]
압축 컨텍스트는 압축 또는 해제 알고리즘이 내부적으로 유지하는 상태입니다. 압축 컨텍스트의 내용은 사용 중인 형식, 알고리즘, 구현에 따라 달라집니다. 이 명세서의 관점에서, 이는 불투명 객체입니다. 압축 컨텍스트는 입력의 첫 바이트를 기대하는 시작 상태에 있습니다.
3. 지원되는 형식
brotli-
"Brotli 압축 데이터 형식" [RFC7932]
-
구현체는 [RFC7932] 1.4절에 따라 “준수(compliant)”해야 합니다.
-
[RFC7932]를 준수하지 않는 블록은
CompressionStream에 의해 생성되어서는 안 되며,DecompressionStream에는 오류입니다.
-
deflate-
"ZLIB 압축 데이터 형식" [RFC1950]
Note: 이 형식은 HTTP Content-Encodings와의 일관성을 위하여 “deflate”로 불립니다. 자세한 내용은 [RFC7230] 4.2.2절을 참고하세요.
-
구현체는 [RFC1950] 2.3절에 따라 “준수(compliant)”해야 합니다.
-
[RFC1950]에서 잘못된 것으로 설명된 필드 값은
CompressionStream에 의해 생성되어서는 안 되며,DecompressionStream에는 오류입니다. -
CM(Compression method) 부분의 유효한CMF필드 값은 8뿐입니다. -
FDICT플래그는 이 API에서 지원하지 않으며, 설정 시 스트림에 오류를 발생시킵니다. -
FLEVEL플래그는DecompressionStream에서 무시됩니다. -
ADLER32체크섬이 맞지 않으면DecompressionStream에서 오류입니다. -
ADLER32체크섬 이후에 추가 입력 데이터가 있다면 오류입니다.
-
deflate-raw-
"DEFLATE 알고리즘" [RFC1951]
-
구현체는 [RFC1951] 1.4절에 따라 "준수(compliant)"해야 합니다.
-
[RFC1951]을 준수하지 않는 블록은
CompressionStream에 의해 생성되어서는 안 되며,DecompressionStream에는 오류입니다. -
BFINAL플래그로 표시된 마지막 블록 이후에 추가 입력 데이터가 있다면 오류입니다.
-
gzip-
"GZIP 파일 형식" [RFC1952]
-
구현체는 [RFC1952] 2.3.1.2절에 따라 “준수(compliant)”해야 합니다.
-
[RFC1952]에서 잘못된 것으로 설명된 필드 값이
CompressionStream에 의해 생성되어서는 안 되며,DecompressionStream에는 오류입니다. -
CM(Compression Method) 필드의 유효한 값은 8뿐입니다. -
FTEXT플래그는DecompressionStream에서 무시되어야 합니다. -
FHCRC필드가 있다면, 올바르지 않을 경우 오류입니다. -
모든
FEXTRA,FNAME,FCOMMENT필드 내용은DecompressionStream에서 종료가 올바른지 확인하는 것 외에는 무시되어야 합니다. -
MTIME,XFL,OS필드의 내용은DecompressionStream에서 무시되어야 합니다. -
CRC32또는ISIZE가 압축 해제된 데이터와 일치하지 않으면 오류입니다. -
gzip스트림은 오직 하나의 “멤버(member)”만 포함할 수 있습니다. -
“멤버” 끝 이후에도 추가 입력 데이터가 있다면 오류입니다.
-
4. 인터페이스 CompressionStream
enum {CompressionFormat ,"brotli" ,"deflate" ,"deflate-raw" , }; [Exposed=*]"gzip" interface {CompressionStream constructor (CompressionFormat ); };format CompressionStream includes GenericTransformStream ;
CompressionStream
은 format과 compression context context를 가진다.
new CompressionStream(format)
단계:
-
format이
CompressionStream에서 지원되지 않는 경우,TypeError를 던진다. -
transformAlgorithm을 chunk 인자를 받아 compress and enqueue a chunk 알고리즘을 this와 chunk로 실행하는 알고리즘으로 둔다.
-
flushAlgorithm을 인자 없이 compress flush and enqueue 알고리즘을 this로 실행하는 알고리즘으로 둔다.
-
this의 transform을 new
TransformStream으로 설정한다. -
Set up this의 transform에 transformAlgorithm을 transformAlgorithm으로, flushAlgorithm을 flushAlgorithm으로 설정한다.
CompressionStream
객체 cs와 chunk를 받아 다음 단계를 실행한다:
-
chunk가
BufferSource타입이 아니면TypeError를 던진다. -
buffer가 비어 있으면 반환한다.
-
arrays를 buffer를 하나 이상의 비어 있지 않은 부분으로 나누고
Uint8Array로 변환한 결과로 둔다. -
각
Uint8Arrayarray를 arrays에서, enqueue하여 array를 cs의 transform에 넣는다.
ReadableStream
객체에서 데이터의 끝 처리를 담당하며, CompressionStream
객체 cs를 받아 다음 단계를 실행한다:
-
buffer를 빈 입력을 cs의 format과 context로, finish 플래그를 포함하여 압축한 결과로 둔다.
-
buffer가 비어 있으면 반환한다.
-
arrays를 buffer를 하나 이상의 비어 있지 않은 부분으로 나누고
Uint8Array로 변환한 결과로 둔다. -
각
Uint8Arrayarray를 arrays에서, enqueue하여 array를 cs의 transform에 넣는다.
5. 인터페이스 DecompressionStream
[Exposed=*]interface {DecompressionStream constructor (CompressionFormat ); };format DecompressionStream includes GenericTransformStream ;
DecompressionStream
은 format과 compression context
context 를 가진다.
new DecompressionStream(format)
단계:
-
format이
DecompressionStream에서 지원되지 않는 경우,TypeError를 던진다. -
transformAlgorithm을 chunk 인자를 받아 decompress and enqueue a chunk 알고리즘을 this와 chunk로 실행하는 알고리즘으로 둔다.
-
flushAlgorithm을 인자 없이 decompress flush and enqueue 알고리즘을 this로 실행하는 알고리즘으로 둔다.
-
this의 transform을 new
TransformStream으로 설정한다. -
Set up this의 transform에 transformAlgorithm을 transformAlgorithm으로, flushAlgorithm을 flushAlgorithm으로 설정한다.
DecompressionStream
객체 ds와 chunk를 받아 다음 단계를 실행한다:
-
chunk가
BufferSource타입이 아니면TypeError를 던진다. -
buffer를 chunk를 ds의 format과 context로 디컴프레싱한 결과로 둔다. 결과가 오류라면
TypeError를 던진다. -
buffer가 비어 있으면 반환한다.
-
arrays를 buffer를 하나 이상의 비어 있지 않은 부분으로 나누고
Uint8Array로 변환한 결과로 둔다. -
각
Uint8Arrayarray를 arrays에서, enqueue하여 array를 ds의 transform에 넣는다. -
압축 입력의 끝에 도달했고, ds의 context 가 chunk를 완전히 소모하지 않았다면,
TypeError를 던진다.
ReadableStream
객체에서 데이터의 끝 처리를 담당하며, DecompressionStream
객체 ds를 받아 다음 단계를 실행한다:
-
buffer를 빈 입력을 ds의 format과 context로, finish 플래그를 포함하여 디컴프레싱한 결과로 둔다.
-
buffer가 비어 있지 않다면:
-
arrays를 buffer를 하나 이상의 비어 있지 않은 부분으로 나누고
Uint8Array로 변환한 결과로 둔다. -
각
Uint8Arrayarray를 arrays에서, enqueue하여 array를 ds의 transform에 넣는다.
-
-
압축 입력의 끝에 도달하지 않았다면
TypeError를 던진다.
6. 프라이버시 및 보안 고려사항
이 API는 웹 플랫폼에 새로운 권한을 추가하지 않습니다.
그러나 공격자가 데이터의 길이를 알 수 있는 상황에서는 웹 개발자가 주의를 기울여야 합니다. 이 경우, 공격자가 데이터의 내용을 추측할 수 있습니다.
7. 예시
7.1. 스트림을 Gzip 압축
7.2. ArrayBuffer를 Uint8Array로 Deflate 압축
async function compressArrayBuffer( input) { const cs= new CompressionStream( 'deflate' ); const writer= cs. writable. getWriter(); writer. write( input); writer. close(); const output= []; let totalSize= 0 ; for ( const chunkof cs. readable) { output. push( value); totalSize+= value. byteLength; } const concatenated= new Uint8Array( totalSize); let offset= 0 ; for ( const arrayof output) { concatenated. set( array, offset); offset+= array. byteLength; } return concatenated; }
7.3. Blob을 Blob으로 Gzip 압축 해제
function decompressBlob( blob) { const ds= new DecompressionStream( 'gzip' ); const decompressionStream= blob. stream(). pipeThrough( ds); return new Response( decompressionStream). blob(); }
감사의 글
Canon Mukai, Domenic Denicola, Yutaka Hirano에게 감사드립니다.이 표준은 Adam Rice (Google, ricea@chromium.org)가 작성했습니다.
지적 재산권
저작권 © WHATWG (Apple, Google, Mozilla, Microsoft). 이 저작물은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스 하에 이용할 수 있습니다. 일부가 소스 코드에 통합된 경우, 해당 부분은 BSD 3-절 라이선스 하에 소스 코드로 이용할 수 있습니다.
이 문서는 현행 표준입니다. 특허 검토 버전에 관심이 있는 분은 현행 표준 검토 초안을 참조하세요.