압축

현행 표준 — 마지막 업데이트

참여하기:
GitHub whatwg/compression (새 이슈, 열린 이슈)
Matrix에서 채팅하기
커밋:
GitHub whatwg/compression/commits
이 커밋 기준 스냅샷
@compressionapi
테스트:
web-platform-tests compression/ (진행 중 작업)
번역 (비규범적):
简体中文
日本語
한국어

요약

이 문서는 이진 데이터 스트림을 압축하고 해제하는 JavaScript API 집합을 정의합니다.

1. 소개

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

이 명세서에서 정의된 API는 데이터 스트림을 압축 및 해제하는 데 사용됩니다. 이들은 "deflate", "deflate-raw" 그리고 "gzip" 압축 알고리즘을 지원합니다. 이들은 웹 개발자들에 의해 널리 사용되고 있습니다.

2. 인프라스트럭처

이 명세서는 Infra에 의존합니다. [INFRA]

청크는 데이터의 한 조각입니다. CompressionStream과 DecompressionStream의 경우, 출력 청크 타입은 Uint8Array입니다. 입력으로는 어떤 BufferSource 타입도 허용합니다.

스트림은 청크들의 순서가 지정된 시퀀스를 나타냅니다. ReadableStreamWritableStream 용어는 Streams에서 정의됩니다. [STREAMS]

압축 컨텍스트는 압축 또는 해제 알고리즘이 내부적으로 유지하는 상태입니다. 압축 컨텍스트의 내용은 사용 중인 형식, 알고리즘, 구현에 따라 달라집니다. 이 명세서의 관점에서, 이는 불투명 객체입니다. 압축 컨텍스트는 입력의 첫 바이트를 기대하는 시작 상태에 있습니다.

3. 지원되는 형식

brotli

"Brotli 압축 데이터 형식" [RFC7932]

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",
  "gzip",
};

[Exposed=*]
interface CompressionStream {
  constructor(CompressionFormat format);
};
CompressionStream includes GenericTransformStream;

CompressionStreamformatcompression context context를 가진다.

new CompressionStream(format) 단계:
  1. formatCompressionStream에서 지원되지 않는 경우, TypeError를 던진다.

  2. thisformatformat으로 설정한다.

  3. transformAlgorithmchunk 인자를 받아 compress and enqueue a chunk 알고리즘을 thischunk로 실행하는 알고리즘으로 둔다.

  4. flushAlgorithm을 인자 없이 compress flush and enqueue 알고리즘을 this로 실행하는 알고리즘으로 둔다.

  5. thistransformnew TransformStream으로 설정한다.

  6. Set up thistransformtransformAlgorithmtransformAlgorithm으로, flushAlgorithmflushAlgorithm으로 설정한다.

compress and enqueue a chunk 알고리즘은 CompressionStream 객체 cschunk를 받아 다음 단계를 실행한다:
  1. chunkBufferSource 타입이 아니면 TypeError를 던진다.

  2. bufferchunkcsformatcontext로 압축한 결과로 둔다.

  3. buffer가 비어 있으면 반환한다.

  4. arraysbuffer를 하나 이상의 비어 있지 않은 부분으로 나누고 Uint8Array로 변환한 결과로 둔다.

  5. Uint8Array arrayarrays에서, enqueue하여 arraycstransform에 넣는다.

compress flush and enqueue 알고리즘은 입력 ReadableStream 객체에서 데이터의 끝 처리를 담당하며, CompressionStream 객체 cs를 받아 다음 단계를 실행한다:
  1. buffer를 빈 입력을 csformatcontext로, finish 플래그를 포함하여 압축한 결과로 둔다.

  2. buffer가 비어 있으면 반환한다.

  3. arraysbuffer를 하나 이상의 비어 있지 않은 부분으로 나누고 Uint8Array로 변환한 결과로 둔다.

  4. Uint8Array arrayarrays에서, enqueue하여 arraycstransform에 넣는다.

5. 인터페이스 DecompressionStream

[Exposed=*]
interface DecompressionStream {
  constructor(CompressionFormat format);
};
DecompressionStream includes GenericTransformStream;

DecompressionStreamformatcompression context context 를 가진다.

new DecompressionStream(format) 단계:
  1. formatDecompressionStream에서 지원되지 않는 경우, TypeError를 던진다.

  2. thisformatformat으로 설정한다.

  3. transformAlgorithmchunk 인자를 받아 decompress and enqueue a chunk 알고리즘을 thischunk로 실행하는 알고리즘으로 둔다.

  4. flushAlgorithm을 인자 없이 decompress flush and enqueue 알고리즘을 this로 실행하는 알고리즘으로 둔다.

  5. thistransformnew TransformStream으로 설정한다.

  6. Set up thistransformtransformAlgorithmtransformAlgorithm으로, flushAlgorithmflushAlgorithm으로 설정한다.

decompress and enqueue a chunk 알고리즘은 DecompressionStream 객체 dschunk를 받아 다음 단계를 실행한다:
  1. chunkBufferSource 타입이 아니면 TypeError를 던진다.

  2. bufferchunkdsformatcontext로 디컴프레싱한 결과로 둔다. 결과가 오류라면 TypeError를 던진다.

  3. buffer가 비어 있으면 반환한다.

  4. arraysbuffer를 하나 이상의 비어 있지 않은 부분으로 나누고 Uint8Array로 변환한 결과로 둔다.

  5. Uint8Array arrayarrays에서, enqueue하여 arraydstransform에 넣는다.

  6. 압축 입력의 끝에 도달했고, dscontextchunk를 완전히 소모하지 않았다면, TypeError를 던진다.

decompress flush and enqueue 알고리즘은 입력 ReadableStream 객체에서 데이터의 끝 처리를 담당하며, DecompressionStream 객체 ds를 받아 다음 단계를 실행한다:
  1. buffer를 빈 입력을 dsformatcontext로, finish 플래그를 포함하여 디컴프레싱한 결과로 둔다.

  2. buffer가 비어 있지 않다면:

    1. arraysbuffer를 하나 이상의 비어 있지 않은 부분으로 나누고 Uint8Array로 변환한 결과로 둔다.

    2. Uint8Array arrayarrays에서, enqueue하여 arraydstransform에 넣는다.

  3. 압축 입력의 끝에 도달하지 않았다면 TypeError를 던진다.

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

이 API는 웹 플랫폼에 새로운 권한을 추가하지 않습니다.

그러나 공격자가 데이터의 길이를 알 수 있는 상황에서는 웹 개발자가 주의를 기울여야 합니다. 이 경우, 공격자가 데이터의 내용을 추측할 수 있습니다.

7. 예시

7.1. 스트림을 Gzip 압축

const compressedReadableStream
    = inputReadableStream.pipeThrough(new CompressionStream('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 chunk of cs.readable) {
    output.push(value);
    totalSize += value.byteLength;
  }

  const concatenated = new Uint8Array(totalSize);
  let offset = 0;
  for (const array of 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)가 작성했습니다.

지적 재산권

이 현행 표준은 W3C WICG에서 처음 개발되었으며, W3C 소프트웨어 및 문서 라이선스 하에 제공되었습니다.

저작권 © WHATWG (Apple, Google, Mozilla, Microsoft). 이 저작물은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스 하에 이용할 수 있습니다. 일부가 소스 코드에 통합된 경우, 해당 부분은 BSD 3-절 라이선스 하에 소스 코드로 이용할 수 있습니다.

이 문서는 현행 표준입니다. 특허 검토 버전에 관심이 있는 분은 현행 표준 검토 초안을 참조하세요.

색인

이 명세서에서 정의한 용어

참조로 정의된 용어

참고 문헌

규범적 참고문헌

[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC1950]
P. Deutsch; J-L. Gailly. ZLIB 압축 데이터 형식 명세 3.3판. 1996년 5월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc1950
[RFC1951]
P. Deutsch. DEFLATE 압축 데이터 형식 명세 1.3판. 1996년 5월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc1951
[RFC1952]
P. Deutsch. GZIP 파일 포맷 명세 4.3판. 1996년 5월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc1952
[RFC7932]
J. Alakuijala; Z. Szabadka. Brotli 압축 데이터 형식. 2016년 7월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc7932
[STREAMS]
Adam Rice; 외. Streams 표준. Living Standard. URL: https://streams.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. Living Standard. URL: https://webidl.spec.whatwg.org/

비규범적 참고문헌

[RFC7230]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing. 2014년 6월. 제안 표준. URL: https://httpwg.org/specs/rfc7230.html

IDL 색인

enum CompressionFormat {
  "brotli",
  "deflate",
  "deflate-raw",
  "gzip",
};

[Exposed=*]
interface CompressionStream {
  constructor(CompressionFormat format);
};
CompressionStream includes GenericTransformStream;

[Exposed=*]
interface DecompressionStream {
  constructor(CompressionFormat format);
};
DecompressionStream includes GenericTransformStream;

MDN

CompressionStream/CompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js17.0.0+
MDN

CompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

DecompressionStream/DecompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js17.0.0+
MDN

DecompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+