Text Compression for Web Developers

HTML5 Rocks

소개

웹 상의 대부분의 텍스트 데이터는 HTML, JavaScript, CSS 로 구성되어 있습니다. 이런 형식들의 파일에는 손실 압축을 적용할 수 없습니다. 그래서 여러분은 무손실 인코더를 제한적으로 사용하게 되며 이것은 손실 이미지/비디오 압축 코덱에 비해 극적인 압축률을 제공할 수 없습니다. 그렇다면 여러분은 여러분의 웹앱 풋프린트를 어떻게 줄일수 있을까요? 이 글은 웹앱 풋프린트를 줄일수 있는 방법을 안내하여 여러분에게 도움을 드릴 것입니다.

I should take a vacation.

TL;DR : 텍스트 데이터 압축 체크리스트

  1. 사용자 경험을 모바일 우선으로 생각하세요
    1. 여러분의 페이지 리소스 풋프린트는 어떤것입니까? 여러분을 그것을 줄일 수 있습니까?
    2. 여러분의 페이지 로딩 평균시간은 어느 정도 입니까?
  2. 모든 콘텐츠는 축소 가능한 만큼 축소(minify) 해 주세요.
    1. CSS 와 Javascript Minifier는 강력하며 사용하기 쉽고 기존 빌드 파이프라인에 적용이 쉽습니다.
    2. 여러분의 데이터를 여러분이 할 수 있는 만큼 최대한 전처리하세요.
  3. 모든 텍스트 리소스에 대해 GZIP 압축을 사용하세요.
    1. 여러분의 서버에 GZIP 압축이 켜져 있는지 확인하세요.
    2. Zopfli 또는 7zip을 사용하는 것으로 오프라인에서 좀 더 압축된 GZIP 데이터를 생성하세요.
  4. 만약 더 높은 압축률이 필요하다면 BZIP2 and LZMA와 같은 고성능의 코덱을 사용하세요.

왜 작은것이 좋은가?

모바일은 전세계적으로 연결성이 증가하여 이미 거대한 마켓이 되었습니다. 테크놀로지 회사들은 곧 온라인으로 합류할 5억 인류를 위해 콘텐츠와 데이터를 전달하기 위한 방법을 찾고 있습니다. 에릭슈미츠의 “New Digital Age”에서 해당 토픽에 대해 잘 설명하고 있습니다.:

아프리카에는 이미 6.5억 이상, 아시아에는 3억 가까이 되는 모바일 폰 사용자가 있습니다. 대부분의 사람들은 음성통화, 텍스트 메시지 기능을 제공하는 일반 폰을 사용하고 있습니다. 그들 나라에서 데이터 서비스 비용이 종종 엄두를 못 낼 만큼 비싸기 때문입니다. 따라서 웹사용이 가능한 폰 또는 스마트 폰을 살 수 있는 사람들도 비용을 감당할 수 없어 사용하지 못합니다. 이것은 바뀔 것입니다. 스마트폰 혁명이 시작될 때 이 인구들에게 큰 이득이 될 것입니다.

Cisco 리포트에 따르면 이것은 새로운 정보가 아닙니다. 모바일 사용자는 이미 2015년까지 예상된 7.88억명에 근접하고 있습니다. 물론, Cisco 같이 큰 회사들에게 이것은 큰 관심사입니다. Cisco는 2012년에 그들의 하드웨어를 통해 월간 597 petabytes의 데이터를 흘려 보냈습니다.

모바일 연결 속도와 단말 성능
지난 몇년간 전세계 네트워크 속도는 비약적으로 발전하였습니다. 그러나 이 개선점이 얼마나 수치적으로 혹은 지리적으로 동일하게 적용되었는지 살펴 보는 것이 중요합니다. Google Analytics는 전세계적인 연결성 경향을 보여주는 환상적인 차트를 가지고 있습니다. 개선점이 균일하지 않다는 것을 쉽게 알 수 있습니다. 예를 들어 중국에서 데스크탑의 페이지 로드 평균시간은 8% 증가하였고(느려졌습니다) 모바일에서는 33% 감소하였습니다(빨라졌습니다). 하지만 여전히 3.5초 이상의 로딩 시간이 필요합니다. 15억 3천만 인구 중 42%가 온라인 상에 있다는 것을 고려 했을 때 이것은 아주 큰 숫자입니다.

로딩 시간에 대한 사용자 인지과 민감성은 가장 중요한 통계입니다. 우리가 살펴보았듯이 레이턴시는 새로운 웹 성능 병목현상이며 대부분의 국가에서 네트워크의 개선이 하드웨어 문제점과 직접적인 관련이 있다는 것을 알 수 있습니다. 새로운 통신 기지국과 광케이블 건설은 토목 공학적인 악몽이며 엄청난 투자비용을 나타냅니다. 문제점은 일부 기업들이 다른 방법으로 문제점을 해결하기 위해 수백만 달러의 위성을 개발하는 것과 같이 너무 복잡합니다. 모바일 네트워크는 속도를 증가(천천히, 균일하지 않으며 큰 비용으로)시키기 위한 노력을 계속 할 것입니다. 만약 여러분이 모바일 웹의 속도가 갑자기 빨라지는 것을 기다린다면 여러분은 좀 더 편한 방법을 찾아볼 필요가 있습니다.

적게 보내는 것으로 사용자에게 더 많이 주세요.
웹개발자는 가장 빠르고 저렴하며 최고 품질의 사용자 경험을 위해 여러분의 웹사이트를 최적화하는 방법에 대한 최대한의 제어를 할 수 있어야 합니다; 가장 좋은 방법 중 하나는 압축입니다. 물론 여러분은 적은 콘텐츠와 적은 범위의 내용으로 모바일 사이트를 만들수도 있습니다. 그러나 사용자는 그런 모바일 사이트를 원하지 않습니다(사이트 모바일 방문자의 1/3은 모바일 사이트와 일반 사이트 중 모든 콘텐츠와 기능을 제공하는 일반 사이트를 선택합니다.). 빠르고 신뢰할 수 있으며 다양한 장치 및 연결에서 크로스 플랫폼 사용자 경험을 줄 수 있는 사이트는 근 미래의 웹을 소유하게 될 것입니다.

압축 알고리즘 종류

텍스트 압축 부분은 무손실 압축 알고리즘으로 구성되는 것이 지배적입니다. (텍스트 기반의 부동소수점 데이터와 같은 특별한 경우를 제외하고). 압축 알고리즘은 소스 스트림에서 정확성과 정보의 손실 없이 직접 복원이 가능해야 하는 것이 일반적입니다. 대부분의 압축 알고리즘 중 인기있는 무손실 코덱으로 LZ77, 허프만, 산술 인코딩이 있습니다. 무손실 압축 알고리즘은 대부분 코덱의 중추입니다. 종종 몇 %의 압축을 더 하기 위해 다른 알고리즘 뒤에 적용되기도 합니다.

압축 전
압축 후
aaaaabbbbbcccddddeeeeffffaaaaabb
a5b4c2d4e4f4a5bb0
표 1 - 무손실 압축 예제입니다. 연속글자를 연속되는 글자과 연속 길이로 인코딩하였습니다. 우리는 처음 스트림을 적절히 복원 할 수 있습니다. 만약 연속되는 글자의 길이가 2 이하인 경우 변경하지 않고 그대로 두었습니다. 스트림의 마지막에 있는 'bb'를 참조하세요.

몇몇 드문 경우, 여러분은 무손실 압축 적용 전, 여러분의 콘텐츠 일부분애 손실 압축을 적용하여 더 많은 절약을 얻을 수 있습니다. 이러한 변형은 처음 소스 상태로 복구될 수 없기 때문에 일반적으로 정보의 손실로 문제가 발생하지 않는 텍스트 기반 데이터 타입에 사용됩니다. 예를 들어 부동 소수점 숫자에서 두자리 소수점까지만 잘라내는 것은 데이터셋에서 받아들일 수 있는 변형일 것입니다.

압축 전
압축 후
0.123, 1.2345, 21.2165, 21.999, 12.123
0,0,20,20,10
표 2 - 손실 압축의 예제, 값들이 위치한 10의 최소 배수로 양자화 되었습니다. 이 변형은 되돌릴 수 없습니다.

텍스트 압축 포맷

오늘날 텍스트 압축 시스템들은 성공적으로 동작하기 위해 다양한 데이터 변형이 연결되어 처리되고 있습니다. 시스템에서 각 단계의 요점은 다음 단계에서 처리되고 효율적으로 압축할 수 있도록 데이터를 변환하는 것입니다. 이 단계들의 합계는 작은 크기의 무손실로 복원 가능한 파일을 생산합니다. 각각 서로 다른 종류의 데이터에 대해 장점과 단점을 가지고 있는 수백가지의 압축 포맷과 시스템이 있습니다. 그들은 (여러 종류의 데이터를 처리하는데) 강력하지 않거나 필요한 압축률을 생산할 수 없기 때문에 여러분은 그들 중 대부분에 대하여 전혀 들어보지 못했습니다. 우리의 목적을 위해 GZIP, BZip2 그리고 7zip과 같은 세가지 유명한 포맷에 대해 살펴 보겠습니다.

웹 지원 포맷: GZIP 과 Deflate

오늘날 웹 상에서 HTTP 압축을 위해 DEFLATEGZIP가 일반적으로 사용됩니다.

DEFLATE는 일반적으로 LZ77 알고리즘과 허프만 코딩을 사용하여 데이터를 감싸는 매우 인기있는 압축 알고리즘입니다. GZIP은 몇몇 흥미로운 블럭화, 휴리스틱(경험적 접근법) 필터링, 헤더와 체크섬과 함께 내부적으로 DEFLATE를 사용하는 파일 포맷입니다. 일반적으로 추가적인 블럭화와 휴리스틱 필터링을 사용한 GZIP은 DEFLATE만 단독으로 사용한 것보다 더 좋은 압축률을 제공합니다.

웹 스택은 배포서버로 실제 압축된 파일들을 전달하기 위해 이 기술들을 반자동으로 사용 할 수 있도록 합니다. (두 알고리즘 모두 압축/해제 속도가 매우 빠릅니다. 이것은 서버사이드 모듈로 그들이 좋은 후보가 되도록 하였습니다.) PHP, Apache 심지어 Google App Engine 모두 GZIP을 지원합니다; 그들은 여러분을 대신하여 파일들을 압축하며 여러분은 트래픽이 전송되는 방식을 설명한 HTTP 헤더 안에 플래그로 설정할 수 있습니다.

SPDY와 같은 차세대 전송 프로토콜과 HTTP2.0은 GZIP을 사용한 헤더 압축을 지원합니다. 대부분의 웹 스택은 이 압축 알고리즘에 의존하게 될 것입니다.

더 작은 GZIP 파일 만들기
대부분의 개발자들은 압축되지 않은 콘텐츠를 단순히 업로드 하며 요청시 즉시 데이터를 압축하기 위해 웹서버에 의존합니다. 이것은 대부분 개발자들의 생산성을 크게 향상 시키며 사용하기 쉽습니다. 그러나 대부분의 사람들은 대부분의 서버에 기본 GZIP 레벨이 6으로 설정된 것을 모르고 있습니다. 최대 레벨은 9입니다. 이것은 서버가 더 큰 출력 파일의 비용으로 더 빠르게 데이터를 압축하게 합니다.

여러분은 GZIP을 사용하여 여러분의 파일들을 오프라인에서 압축하거나 압축된 파일을 서버에 업로는 하는 것으로 더 나은 압축을 할 수 있습니다. 여러분은 GZIP을 이 과정에서 직접 사용 할 수 있지만 Zopfli7zip과 같은 고급 압축은 고급 검색/매칭 알고리즘과 더 나은 패턴 매칭을 위해 더많은 메모리를 활용하는 데이터 구조를 통해 알반적으로 더 작은 GZIP 파일을 생성합니다.

파일들을 오프라인에서 압축하고 압축된 파일들을 서버로 업로드 하는 것들로 이점을 얻을 수 있습니다. 여러분은 미리 압축된 콘텐츠가 올바르게 전달되기 위한 서버를 구성해야 합니다.(ApacheAmazon Web Service에서 설정하기 위한 방법이 여기에 있습니다.) 클라이언트가 여러분의 페이지를 요청할 때 클라이언트 사이드 코드 변경없이 기존처럼 전달 및 압축 해제 될 것입니다.

다른 압축 포맷

GZIP이 블록에 대한 유일한 옵션이 아닌 상황에서 만약 웹앱이 큰 블록의 데이터를 전송해야 하거나 자주 전송해야 한다면 여러분은 콘텐츠 사이즈를 줄이는 다른 기술에 투자할 필요가 있습니다. 이 기술들 중 하나는 합리적인 압축 해제 속도로 여러분에게 GZIP보다 더 나은 압축을 제공하는 자바스크립트 빌드 압축 형식을 사용하는 것을 포함 할 수 있습니다.

두가지 경쟁적인 압축 포맷들로 BZIP2LZMA가 있습니다. 이것들 모두는 일반적으로 GZIP보다 더 작은 파일을 생산할 수 있으며 다양한 상황에서도 더 빠르게 압축 해제 할 수 있습니다.

안타깝게도 이들 두 포맷들은 브라우저에서 네이티브 레벨로 지원하지 않습니다. 하지만 이 인기있는 포맷들은 현재 자바스크립트로 포팅되어 있으며 이것은 여러분이 이 코덱들로 오프라인에서 데이터를 압축할 수 있으며 클라이언트에서 자바스크립트로 압축 해제 할 수 있는 것을 의미합니다.

압축 해제 시간은 (사용자가 데이터를 전달받는 시간을) 더 느려지게 합니다. 즉, 모든 데이터에 적합하지 않다는 것을 의미합니다. 그러나 개발자는 상호작용과 매우 상세한 웹 앱에서 이 방법들을 통해 좋은 결과를 찾을 수 있을 것입니다.

이 압축 포맷들을 사용할 때 이들 두가지는 압축 경로에서 완전히 다른 단계에 사용합니다. 따라서 GZIP에 대하여 적절한 비교를 하는 것이 어렵습니다.

예를 들면 BZIP2Burrows Wheeler TransformMove To Front Transform으로 만들어 졌습니다. 이 transforms 모두는 데이터의 실제 사이즈를 줄이기 위해 아무것도 하지 않는 대신에 허프만/산술 인코더에서 실제 압축을 수행할 수 있는 방식으로 데이터를 변형합니다. BZIP은 종종 큰 메모리 사용때문에 비판을 받지만(BWT는 네이티브 구현으로 신속하게 메모리를 사용할 수 있습니다.) 지금까지의 비교로는 GZIP보다 쉽고 더 작게 압축할 수 있습니다.

LZMAGZIP의 먼 사촌으로 생각할 수 있습니다. 그들 모두는 통계적 범위 인코딩 시스템을 따르는 인기있는 LZ dictionary 압축에서 시작 되었습니다. LZMAGZIP보다 더 작은 파일들을 생산합니다. 하지만 이것은 LZMA의 고급 LZ matching and windowing 알고리즘 때문입니다.

더 나은 압축을 위한 텍스트 전처리

일반적으로 웹상의 텍스트 압축은 2단계 과정을 갖습니다; 첫번째는 최소화 단계와 이어서 무손실 압축하는 단계입니다.

최소화

첫번째 단계, 최소화기본 시스템에 의한 처리없이 가능한 데이터 사이즈 줄이기입니다. 기본적으로 문장구성의 변화없이 가능한한 필요없는 데이터를 삭제합니다. 예를 들면 자바스크립트 파일의 대부분의 공백은 삭제해도 안전하며 자바스크립트 문법에 변화를 주지 않고 파일 사이즈를 줄일 수 있습니다. 최소화는 일반적으로 빌드 프로세스에서 수동 단계 혹은 자동화 된 빌드 체인의 부분으로 다뤄집니다.

CSS Minifiers
선택할수 있는 많은 CSS Minifire가 있습니다. 사용 할 수 있는 몇가지 옵션들을 포함합니다.

몇가지 시도해보고 좋을 결과를 주며 최소한의 충돌로 여러분의 워크플로우에 맞는 하나를 선택하세요.

이 도구들의 주요 차이점은 그들의 최소화 과정의 깊이에 있습니다. 예를 들어 간단한 최적화 필터는 테스트에서 초과 공백과 빈 블록을 제거합니다. 더 나은 고급 최적화는 파일에서 hex 양식을 줄이기 위해 "AntiqueWhite"를 "#FAEBD7"로 교환하며 GZIP 압축 향상을 위해 모든 문자를 소문자로 강제로 변환 하는 것을 포함합니다.

더 많은 공간을 절약하기 위한 CSS 최소화의 공격적인 방법들은 여러분의 CSS rules를 깨뜨릴 위험을 갖고 동작합니다. 따라서 대부분의 개선점이 항상 자동화 될 수는 없으며 개발자들은 파일 사이즈 개선이 위험에 비해 가치가 있는지 결정해야 합니다.

사실 CSS코드를 좀 더 효율적으로 작성하기 위해 도움을 주는 CSS 언어다른 버전을 만드는 새로운 트렌드가 있습니다. 그리고 추가 혜택으로 컴파일러가 더 작은 CSS 코드를 생성할 수 있습니다.

Javascript Minifiers
CSS minifier와 마찬가지로 한가지로 모든 것을 만족시킬 수 있는 Javascript minifier는 없습니다. 다시 한번 반복하면 그들은 모두 거의 같은 일을 합니다. 그래서 여러분의 빌드 체인과 여러분의 원하는 기능으로 작업할 수 있는 한가지를 선택해야 합니다. 인기 있는 몇가지:

이들 시스템의 대부분은 Abstract Syntax Tree의 일종으로 여러분의 자바스크립트를 컴파일하여 작업하며 ASK로부터 좀 더 컴팩트 한 자바스크립트를 재생성합니다. 공백 최소화, 변수 이름 줄이기, 그리고 짧은 형태로 표현 다시 쓰기를 포함하는 예제 최적화. 예를 들면 foo["bar"] 대신에 foo.bar를 사용합니다.

자동화 된 minifier가 잘 수행되고 있지만 로봇은 어떻게 해야하는지에 대한 생각없으므로 몇가지 고급 최적화가 있습니다. JS 해커의 새로운 세대들은 과거의 자동화 된 minification 방법들을 hand-generated minification에 밀어 넣고 있습니다. 이것은 종종 자동화 된 도구가 생산할 수 있는 어떤 것보다 더 작은 파일을 생성하곤 합니다. 물론 만들어 내기 위한 약간의 정신적 고통이 있습니다.

콘텐츠 별 처리

범용 무손실 압축 알고리즘이 획기적으로 압축된 데이터를 생산하는 동안 여러분의 데이터를 더 압축하기 위한 전처리에 일반적인 경향이 있습니다. 지금의 대부분 압축 시스템들에서 가장 크게 얻을 수 있는 압축률은 정보의 형식과 구조에 대해 높은 이해를 가진 결정들과 분류와 커스텀 압축(이것은 또한 modeling이라고 불립니다.)을 최대한 활용하는 것으로부터 나옵니다. 대부분의 시간이 명확하고, 정확하게 여러분의 콘텐츠를 검토(여러분이 고수준의 압축에서 최대한 활용하기 위한 중복의 종류를 결정하기 위한 검토)하는데 필요합니다. 여기에 몇가지 아이디어가 있습니다:

  • 텍스트 데이터에서 몇몇 기호는 압축된 스트림으로부터 삭제될 수 있으며 이후 클라이언트 상에서 복원됩니다(예를 들면 공백들). 이것들은 전체 파일 크기를 줄일 수 있으며 클라이언트의 성능에 큰 영향을 주지 않습니다.

압축 전
압축
“1,2,3,4,5,6,7,8,0,2,3,4,2,1,2”
“123456780234212”0
표 3 - 알려진 중복된 텍스트를 제거하는 예제. 우리는 모든 값들이 한 자리의 숫자로 되어 있는 것을 이 예제에서 알 수 있으므로 콤마를 제거하고 나중에 복원할 수 있습니다.

  • 만약 여러분이 많은 자리수의 부동소수점을 전달한다면 양자화는 훌륭한 아이디어 입니다. 고유 기호의 개수를 줄이며 또한 파일에 포함될 필요가 없는 일부 정확도를 자르게 됩니다.

압축 전
압축 후
0.123, 1.2345, 21.2165, 21.999, 12.123
0,0,20,20,10
표 4 - 손실 압축의 예제. 값들이 위치한 10의 최소 배수로 양자화 되었습니다. 이 변형은 되돌릴 수 없습니다.

  • 종종 개발자들은 순서 독립성을 위해 인덱스 배열을 전송합니다. 만약 여러분의 인덱스 정보가 닫힌 간격으로 발생하는 경우 (즉, 모든 값이 건너뛰기 없이 X, Y인 경우) 여러분은 정보를 정렬하고 더 큰 이익을 위한 델타 인코딩을 할 수 있습니다.

압축 전
압축 후
[8,2,1,5,3,7,6,3,2,9,0,4]
sorted = [0,1,2,3,4,5,6,7,8,9,0]
delta encoded = [0,1,1,1,1,1,1,1,1,1,1]
표 5 - 정렬 및 델타 인코딩 예제. 우리는 우선 데이터를 정렬한 후 각 요소가 이전 값과 차이를 나타내도록 인코딩 했습니다. 델타 인코딩 된 양식은 반복되는 많은 기호를 가질 수 있습니다.

최근에 압축 guru인 Matt Mahoney인간의 DNA 시퀀스를 압축하기 위한 경쟁에 들어갔습니다. 그의 결과는 인상적이었습니다. 일반적으로 추출, 모델링과 유사한 콘텐츠의 분석을 중심으로 했습니다. interleaved 스트림으로부터 비슷한 블록으로 유사 데이터 종류를 추출하는 능력은 종종 몇가지 독립된 데이터 포인트에 기반하여 미래 기호를 예측할 수 있도록 압축에 도움을 주기 위한 지역 정보의 이점을 압축 알고리즘에 활용할 수 있습니다.

임의로 혼합된 콘텐츠 데이터 파일을 위한 콘텐츠 별 압축 유형을 결정하는 것은 매우 까다로우며 복잡합니다. 다행히 여러분들을 위해 어떤 사람들은 이미 그 길을 시작했습니다:

  • XMILLXML 별 압축 시스템입니다. 이것은 다른 종류의 데이터를 추출하고 함께 그룹화하며 다양한 압축 알고리즘을 적용합니다.
  • 또 다른 환상적인 애플리케이션은 JSZap입니다. 이것은 여러분의 Javascript를 추상적인 문법 트리로부터 분석하여 구별된 스트림들로 비슷한 데이터 타입을 분리합니다. 각각의 스트림은 각각에 최적화 된 압축 방법을 사용하여 개별적으로 압축됩니다.
  • 여러분은 JSON 데이터에 이 아이디어를 적용하는 다양한 참조를 쉽게 찾을 수 있습니다; 다시한번, 여러분은 더 나은 압축을 생산하기 위하여 GZIP으로 전달하기 전에 JSON 파일의 전처리를 할 수 있습니다.

결론

대부분 웹사이트 대역폭의 60%를 이미지가 차지하고 있음에도 불구하고 여러분은 텍스트 콘텐츠로부터 나오는 다른 데이터 블록을 무시할 수 없습니다. Javascript 파일들은 계속 커지고 있으며 JSON 데이터는 매일 전송되며 더 많은 사용자들이 성능이 좋지 않은 네트워크를 통해 온라인으로 들어오고 있습니다. 따라서 여러분은 여러분의 사이트 빌드를 내보낼 때마다 텍스트 압축 체크리스트를 따르고 있는지 확인해야 합니다:

  1. 사용자 경험을 모바일 우선으로 생각하세요
    1. 여러분의 페이지 리소스 풋프린트는 어떤것입니까? 여러분을 그것을 줄일수 있습니까?
    2. 여러분의 페이지 로딩 평균시간은 어느 정도 입니까?
  2. 모든 콘텐츠는 축소 가능한만큼 축소(minify)해 주세요.
    1. CSS 와 Javascript Minifier는 강력하며 사용하기 쉽고 기존 빌드 파이프라인에 적용이 쉽습니다.
    2. 여러분의 데이터를 여러분이 할수 있는 만큼 최대한 전처리하세요.
  3. 모든 텍스트 리소스에 대해 GZIP 압축을 사용하세요.
    1. 여러분의 서버에 GZIP 압축이 켜져 있는지 확인하세요.
    2. Zopfli 또는 7zip을 사용하는 것으로 오프라인에서 좀 더 압축된 GZIP 데이터를 생성하세요.
  4. 만약 더 높은 압축률이 필요하다면 BZIP2 and LZMA와 같은 고성능의 코덱을 사용하세요.

Comments

0