공유 사전으로 압축 효율성 극대화

데이터 압축은 사용 가능한 페이지 리소스의 크기를 줄이는 검증된 성능 최적화 기법입니다. 한동안 웹 서버에서 gzip을 주로 사용하여 HTML, CSS, 자바스크립트 파일과 같은 일반적인 텍스트 기반 페이지 리소스를 압축한 다음 압축 해제할 수 있는 클라이언트로 전송하는 것이 일반적이었습니다. 그 결과, 의도한 페이지 동작에 영향을 주지 않고 리소스 로드 시간이 단축됩니다.

gzip은 그 자체로 매우 효과적이지만, 최근 몇 년 동안 웹에서 압축이 더욱 많이 개선되었습니다. 2016년에는 Chrome에 Brotli 알고리즘을 도입하여 적합한 리소스에 대해 전반적으로 더 나은 압축 비율을 제공했습니다. 2017년 말까지 모든 최신 브라우저가 Brotli를 지원했으며 이에 대한 서버 지원이 더 광범위하게 적용되기 시작했습니다. 최근 Chrome에서는 ZStandard 압축을 출시했습니다.

하지만 여기서 멈추지 않습니다. Chrome팀은 웹에서 공유 사전을 사용할 수 있도록 하기 위해 노력해 왔습니다. 이 사전은 현재 Brotli 및 ZStandard용 오리진 트라이얼에서 사용할 수 있습니다. 공유 사전은 Brotli 및 ZStandard 압축을 보완하여 업데이트된 코드를 자주 제공하는 웹사이트에 훨씬 더 높은 압축 비율을 제공하며 경우에 따라 90% 이상의 압축 비율을 제공할 수 있습니다. 이 게시물에서는 공유 사전의 작동 방식과 웹사이트에서 Brotli 및 ZStandard에 이를 사용하기 위해 오리진 트라이얼에 등록하는 방법을 자세히 설명합니다.

공유 사전 설명

압축은 입력에서 중복 시퀀스를 찾고 이 정보를 사용하여 훨씬 더 작은 출력을 생성한 후 나중에 되돌릴 수 있는 프로세스입니다. 압축은 리소스 로드 시간을 상당히 단축하므로 웹에서 잘 작동합니다. Brotli와 ZStandard는 압축 중에 이러한 알고리즘이 사용할 수 있는 추가 패턴 모음인 압축 사전을 사용하여 효과를 더욱 높일 수 있습니다. 실제로 Brotli의 높은 효율성은 내부 사전을 사용함으로써 어느 정도 성취됩니다.

하지만 특정 리소스에 대한 패턴이 포함된 Brotli 및 ZStandard와 함께 커스텀 사용자 선별 사전을 사용할 수 있습니다. 실제로 커스텀 사전은 모든 입력에 적용할 수 있는 외부 파일입니다. 사전은 애플리케이션의 프로덕션 코드에 따라 고도로 한정될 수 있으며, 실제로는 어떤 콘텐츠에도 한정될 수 있습니다. 주어진 사전이 입력에 얼마나 적용되는지는 전반적인 압축 효율성에 큰 영향을 미칠 수 있습니다. 입력의 콘텐츠와 매우 유사한 사전은 일반적이거나 유사하지 않은 콘텐츠가 있는 사전보다 압축률이 높은 출력을 생성합니다.

다음은 커스텀 압축 사전이 얼마나 효과적인지를 보여주는 예입니다. 웹사이트에서 Angular 프레임워크를 사용하고 현재 사용 중인 버전이 1.7.9라고 가정해 보겠습니다. 이 Angular 프레임워크 버전은 약 172KiB(압축되지 않은 상태)입니다. Brotli의 기본 설정으로 압축하면 크기가 약 53KiB가 됩니다. 이는 거의 70% 의 압축률을 생성합니다. 그러나 나중에 Angular 1.8.3으로 업그레이드한다고 가정해 보겠습니다. 이 Angular 버전은 버전 1.7.9와 거의 동일한 크기라는 점을 고려하면 이전 버전과 거의 동일한 압축 비율을 예상할 수 있습니다.

이때 이전 버전의 리소스 사전을 사용해 최신 버전을 압축하는 델타 압축이라고 하는 프로세스를 사용하면 커스텀 사전을 유용하게 활용할 수 있습니다. 이전 예에서 버전 1.7.9를 사전으로 사용하여 Angular의 버전 1.8.3을 압축하면 출력은 4KiB를 약간 넘을 것입니다. 이는 거의 98%의 압축비를 나타냅니다. 압축 사전은 로드 성능에 큰 영향을 미칠 수 있으며 그 효과는 이미 실제 애플리케이션에서도 실현되고 있습니다.

그러나 이 흐름이 웹에서 작동하도록 하는 데는 어려움이 있습니다. 사전을 사용하여 리소스를 압축하는 경우 압축을 해제하려면 동일한 사전이 필요하다는 점이 중요합니다. 이 흐름은 이전에 웹(SDCH)에서 시도되었지만 안전하게 구현하기가 어려웠습니다. 공유 사전 압축에 관한 이 최신 제안은 정적 리소스와 동적 리소스 모두에 상당한 이점을 제공하는 동시에 이러한 우려를 해소합니다.

Chrome에서 공유 사전 지원을 광고하는 방법

모든 브라우저는 Accept-Encoding 요청 헤더를 통해 지원하는 압축 알고리즘을 알립니다. 헤더의 콘텐츠는 쉼표로 구분된 지원되는 인코딩 목록입니다.

Accept-Encoding: gzip, br, zstd

이 특정 Accept-Encoding 헤더는 리소스를 요청하는 브라우저가 gzip, Brotli, ZStandard 압축 알고리즘을 지원함을 명시합니다. 그러면 요청에 응답하는 웹 서버가 요청에 응답할 때 사용할 알고리즘을 결정할 수 있습니다.

공유 사전 지원이 사용 설정되고 리소스에 관련 사전을 사용할 수 있으면 Accept-Encoding 헤더에 토큰이 추가됩니다. 이러한 토큰은 Brotli의 경우 br-d, Zstandard의 경우 zstd-d입니다. Chrome에는 사용 가능한 사전의 해시도 포함됩니다. 이에 대해서는 다음 단계에서 다룹니다.

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

웹 서버가 이 토큰을 인식하도록 구성되어 있고 사전을 인식하면, 적용 가능한 인코딩용 사전을 사용하여 압축된 리소스로 해당 요청에 응답할 수 있습니다. 실제로 이를 달성하는 방법은 요청이 정적 리소스에 대한 것인지 동적 리소스인지에 따라 다릅니다.

정적 리소스의 공유 사전 압축

정적 페이지 리소스는 요청된 URL에 대해 항상 동일한 응답을 생성하는 리소스입니다. 압축 가능한 정적 페이지 리소스의 일반적인 예로는 JavaScript 및 CSS 파일이 있습니다. 이러한 리소스는 일반적으로 어떤 식으로든 캐싱 목적으로 버전이 지정됩니다. 어떤 방식으로든 파일 이름에 파일 콘텐츠의 해시 (예: styles.abcd1234.css)가 포함되거나 리소스를 디지털 지문으로 확인하는 다른 방법이 있습니다. 이러한 리소스 유형은 공유 사전에서 제공하는 델타 압축에 적합한 후보입니다. 정적 리소스는 오랜 기간 동안 캐시되고 일정한 빈도로 업데이트되는 경향이 있기 때문입니다.

사전은 Use-As-Dictionary 응답 헤더를 설정하여 정적 리소스의 사전을 지정할 수 있습니다. 헤더는 몇 가지 키-값 쌍 중 하나를 취하지만, 필요한 키-값 쌍은 match뿐입니다. 이 헤더는 사전을 사용해야 하는 리소스 경로를 지정하는 URLPattern 구문을 허용합니다.

Use-As-Dictionary: match="/dist/styles.*.css"

Use-As-Dictionary 헤더는 리소스 내에 지정된 패턴과 일치하는 향후 버전의 리소스에 적용되는 메커니즘이라고 생각하면 됩니다. 웹사이트에서 모든 스타일을 단일 CSS 파일로 제공한다고 가정해 보겠습니다. 편의상 이 리소스의 첫 번째 버전이 /dist/styles.v1.css에 있고 match 값이 /dist/styles.*.cssUse-As-Dictionary 응답 헤더와 함께 전송된다고 가정해 보겠습니다.

시간이 지나면 웹사이트의 CSS를 업데이트하고 /dist/styles.v2.css에 새 버전의 CSS를 제공합니다. 이전 버전의 Use-As-Dictionary 응답 헤더에 사용된 match 값이 이 요청에 적용되므로 브라우저에서 구조화된 필드 바이트 시퀀스로 인코딩된 사전 해시가 포함된 Available-Dictionary 헤더를 전송합니다.

Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:

이 시점에서 일치하는 사전이 사용될 수 있도록 서버 측에서 압축을 구성하는 것은 서버에 달려 있습니다. 그런 다음 해당 사전으로 압축된 리소스가 전송되고 사용자의 브라우저 캐시에 있는 사용 가능한 사전이 압축을 해제하는 데 사용됩니다.

웹사이트에 새 코드를 자주 제공하는 경우 델타 압축이 큰 효과를 발휘할 수 있습니다. 그러나 절차는 유연합니다. 브라우저가 사용자의 브라우저 캐시에 사전이 있는지 확인하지 않으면 Accept-Encoding 헤더에 추가 br-d 또는 zstd-d 토큰을 지정하지 않습니다. 이 경우 표준 압축 흐름이 적용됩니다.

동적 리소스의 공유 사전 압축

동적 리소스는 공유 사전 압축도 활용할 수 있습니다. 동적 리소스는 문맥에 따라 변경되는 리소스(예: 기본 페이지가 뉴스 속보 등으로 자주 업데이트되는 뉴스 웹사이트)입니다. HTML 문서는 동적 리소스인 경우가 많습니다. 이러한 경우 사전에는 각 페이지의 고유한 부분만 전송되는 압축된 페이지로 이어지는 사이트의 일반적인 HTML 구조와 템플릿 코드가 대부분 포함될 수 있습니다.

동적으로 생성되는 리소스의 특성으로 인해 사전은 나중에 사용할 수 있도록 클라이언트에 로드되어야 합니다. 사전을 미리 로드하면 동적 리소스에 공유된 사전 압축을 적용하는 것은 추측입니다. 이러한 경우 웹사이트에서 충분한 트래픽이 확보되면 사전 비용을 여러 번 탐색하여 분할 상환할 수 있기를 바랍니다. 사용해 보기로 하는 경우 첫 번째 단계는 페이지 HTML의 <link> 요소를 통해 사전의 위치를 지정하는 것입니다.

<link rel="dictionary" href="/dictionary.dat">

Chrome에서 이 <link> 요소를 발견하면 대역폭 경합을 방지하기 위해 낮은 우선순위로 페이지가 유휴 상태가 되면 사전을 가져올 수도 있습니다. 사전 자체에 대한 응답은 Use-As-Dictionary 헤더를 지정하고 이 헤더가 적용되는 동적 리소스 경로를 지정해야 합니다.

Use-As-Dictionary: match="/product/*"

여기서부터 흐름은 정적 리소스와 대체로 동일합니다. 브라우저는 사전 자체가 일치하는 리소스에 적용되는 것을 확인하고 앞서 설명한 정적 리소스 흐름과 마찬가지로 사전 콘텐츠의 해시를 사용하여 요청에 Available-Dictionary 헤더를 연결합니다.

빌드 시 정적 리소스 압축

번들러에 익숙하다면, 빌드 시 리소스를 압축한 후 압축된 리소스를 제공할 수 있는 다양한 플러그인에 익숙할 것입니다. 예를 들어 Apache에서는 요청 시 지시어를 사용하여 사전 압축된 리소스를 제공할 수 있습니다.

압축을 지원하는 대부분의 Node.js 기반 번들러는 Node의 기본 제공 Zlib 라이브러리를 사용합니다. Zlib는 Brotli 및 이를 사용하는 번들러에 대한 지원을 제공하며, 일반적으로 사전 지원 압축을 지원하는 Zlib로 옵션을 직접 전달하는 인터페이스를 제공합니다. 다음은 사전 사용을 지원하는 몇 가지 번들러입니다.

리소스의 특정 버전에 사용 가능한 사전은 리소스의 이전 버전 중 하나를 사용할 수 있습니다. 즉, 사용자 트래픽을 분석하고 이에 따라 계획을 세워야 합니다. 균형을 유지하고 최대한 많은 재사용자 수에 도움이 되는 리소스를 생성하세요. CDN 제공업체는 현재 공유 사전 압축을 실험하고 있습니다. 아직 공개적으로 사용할 수 있는 구현은 없지만 변경될 예정입니다.

직접 사용해 보신 후

공유 사전 압축을 브라우저의 기존 압축 기능과 통합하면 업데이트된 프로덕션 코드를 자주 제공하고 재방문자로부터 상당한 트래픽을 받는 웹사이트의 로딩 성능을 크게 개선할 수 있습니다. 공유 사전 압축을 사용해 보고 싶다면 다음 두 가지 옵션이 있습니다.

  1. 공유 사전 압축을 직접 사용해보고 작동 방식을 익히고 싶다면 chrome://flags 페이지에서 압축 사전 전송 실험용 기능을 사용 설정하세요.
  2. 프로덕션 웹사이트에서 이 기능을 사용해 보고 공유 사전 압축이 실제 사용자에게 어떤 도움이 되는지 알아보려면 오리진 트라이얼에 등록하여 토큰을 얻고 오리진 트라이얼 작동 방식을 읽어보세요.

결론

우리는 웹에서 압축 기술의 이 중요한 발전과 사람들이 매일 사용하는 기존 응용 프로그램을 훨씬 더 빠르게 만들 수 있다는 것에 대해 매우 기쁜 마음입니다. 꼭 사용해 보시기 바랍니다. 무엇보다도 사용해 본다면 여러분의 의견을 듣고 있습니다. 버그를 발견하면 crbug.com에서 신고하세요. 추가 리소스와 도구는 use-as-dictionary.com에서 확인할 수 있습니다. 마지막으로 이 모든 작동 방식에 대해 자세히 알아보려면 설명 페이지를 참고하세요.