불필요한 리소스 다운로드를 없애는 것 외에 페이지 로드 속도를 개선하기 위해 할 수 있는 가장 좋은 방법은 나머지 리소스를 최적화하고 압축하여 전체 다운로드 크기를 최소화하는 것입니다.
데이터 압축 101
사용하지 않는 리소스가 다운로드되지 않도록 웹사이트를 설정했다면 다음 단계는 브라우저가 다운로드해야 하는 나머지 적격 리소스를 압축하는 것입니다. 리소스 유형(텍스트, 이미지, 글꼴 등)에 따라 웹 서버에서 사용 설정할 수 있는 일반 도구, 특정 콘텐츠 유형의 사전 처리 최적화, 개발자의 입력이 필요한 리소스별 최적화 등 다양한 기술을 선택할 수 있습니다.
최고의 성능을 제공하려면 다음 기술을 모두 조합해야 합니다.
- 압축은 더 적은 비트를 사용하여 정보를 인코딩하는 프로세스입니다.
- 불필요한 데이터를 삭제하면 항상 최상의 결과를 얻을 수 있습니다.
- 다양한 압축 기법과 알고리즘이 있습니다.
- 최상의 압축을 달성하려면 다양한 기법이 필요합니다.
데이터 크기를 줄이는 프로세스를 데이터 압축이라고 합니다. 많은 사람들이 압축률, 압축 속도, 다양한 압축 알고리즘에 필요한 메모리를 개선하기 위해 알고리즘, 기술, 최적화를 제공했습니다.
데이터 압축에 대한 자세한 내용은 이 가이드에서 다루지 않습니다. 하지만 압축이 작동하는 방식과 페이지에 필요한 다양한 애셋의 크기를 줄이는 데 사용할 수 있는 기법을 대략적으로 이해하는 것이 중요합니다.
이러한 기법의 핵심 원칙을 설명하기 위해 이 예시를 위해 고안된 간단한 문자 메시지 형식을 최적화하는 프로세스를 살펴보겠습니다.
# Below is a secret message, which consists of a set of headers in
# key-value format followed by a newline and the encrypted message.
format: secret-cipher
date: 08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
- 메일에는 '#' 접두사로 표시되는 임의의 주석(때로는 댓글이라고 함)이 포함될 수 있습니다. 주석은 메시지의 의미나 동작에 영향을 주지 않습니다.
- 메시지에는 헤더가 포함될 수 있습니다. 헤더는 메시지 시작 부분에 표시되는 키-값 쌍 (위 예에서
":"로 구분됨)입니다. - 메시지는 텍스트 페이로드를 전달합니다.
200자로 시작하는 이전 메시지의 크기를 줄이기 위해 무엇을 할 수 있나요?
- 댓글이 흥미롭지만 메시지의 의미에는 영향을 주지 않습니다. 메시지를 전송할 때 이를 삭제합니다.
- 헤더를 효율적으로 인코딩하는 좋은 기법이 있습니다. 예를 들어 모든 메시지에 'format'과 'date'가 있는 경우 이를 짧은 정수 ID로 변환하여 전송할 수 있습니다. 하지만 사실이 아닐 수도 있으므로 지금은 그대로 두는 것이 좋습니다.
- 페이로드는 텍스트만 포함합니다. 실제 콘텐츠가 무엇인지는 알 수 없지만 (
"secret-cipher"를 사용하는 것으로 보임) 텍스트만 봐도 중복이 많다는 것을 알 수 있습니다. 반복되는 문자를 전송하는 대신 반복되는 문자의 수를 세어 더 효율적으로 인코딩할 수 있습니다. 예를 들어"AAA"는"3A"가 되며, 이는 A가 세 번 반복되는 시퀀스를 나타냅니다.
이러한 기법을 결합하면 다음과 같은 결과가 생성됩니다.
format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A
새 메시지는 56자(영문 기준)이므로 원래 메시지를 72% 압축한 것입니다. 상당히 많이 줄었습니다.
이는 압축 알고리즘이 텍스트 기반 리소스의 전송 크기를 줄이는 데 효과적일 수 있는 간단한 예입니다. 실제로 압축 알고리즘은 이전 예시에서 설명한 것보다 훨씬 정교하며 웹에서는 압축 알고리즘을 사용하여 리소스의 다운로드 시간을 크게 줄일 수 있습니다. 텍스트 기반 애셋에 압축을 적용하면 웹페이지에서 리소스를 로드하는 데 걸리는 시간이 줄어들어 사용자가 압축을 적용하지 않았을 때보다 리소스의 효과를 더 빨리 확인할 수 있습니다.
압축: 전처리 및 컨텍스트별 최적화
여기에서 설명하는 첫 번째 기법은 최소화입니다. 최소화는 엄밀히 말해 압축 알고리즘은 아니지만 소스 코드에 사용되는 불필요하고 중복된 문자를 삭제하여 리소스를 사람이 더 쉽게 읽을 수 있도록 하는 방법입니다. 하지만 프로덕션 웹사이트에서 소스 코드의 기능을 유지하는 데 가독성이 필요하지 않으며 웹에서 리소스 로딩이 지연될 수 있습니다.
축소는 콘텐츠별 최적화의 한 유형으로, 제공된 리소스의 크기를 크게 줄일 수 있으며 이러한 최적화는 빌드 및 배포 프로세스의 일부로 적용하는 것이 가장 좋습니다. 예를 들어 번들러는 웹사이트에 새 프로덕션 코드를 배포하기 직전에 리소스를 자동으로 최소화할 수 있는 일반적으로 사용되는 소프트웨어 유형입니다.
중복되거나 불필요한 데이터를 압축하는 가장 좋은 방법은 데이터를 제거하는 것입니다. 하지만 임의의 데이터를 삭제할 수는 없습니다. 하지만 데이터 형식과 속성에 관한 콘텐츠별 지식이 있는 일부 컨텍스트에서는 실제 의미나 기능에 영향을 주지 않고 페이로드의 크기를 크게 줄일 수 있습니다.
<html>
<head>
<style>
/* awesome-container is only used on the landing page */
.awesome-container {
font-size: 120%;
}
.awesome-container {
width: 50%;
}
</style>
</head>
<body>
<!-- awesome container content: START -->
<div>
This is my awesome container, and it is <em>so</em> awesome.
</div>
<!-- awesome container content: END -->
<script>
awesomeAnalytics(); // Beacon conversion metrics
</script>
</body>
</html>
이전 HTML 스니펫과 스니펫에 포함된 세 가지 콘텐츠 유형을 고려해 보세요.
- HTML 마크업
- 페이지의 프레젠테이션을 맞춤설정하는 CSS
- 상호작용 및 기타 고급 페이지 기능을 지원하는 JavaScript
이러한 콘텐츠 유형마다 유효한 콘텐츠를 구성하는 요소, 댓글을 지정하는 규칙 등이 다릅니다. 하지만 남은 질문은 '이 페이지의 크기를 어떻게 줄일 수 있을까?'입니다.
- 코드 주석은 개발자에게 유용하지만 브라우저에는 필요하지 않습니다. CSS (
/* ... */), HTML (<!-- ... -->), JavaScript(// ...) 주석을 삭제하면 페이지와 하위 리소스의 총 전송 크기가 줄어듭니다. - '스마트' CSS 압축기는
.awesome-container의 규칙을 정의하는 비효율적인 방법을 사용하고 있음을 감지하고 다른 스타일에는 영향을 주지 않으면서 두 선언을 하나로 병합하여 더 많은 바이트를 절약할 수 있습니다. 많은 CSS 규칙에서 이러한 중복을 삭제하면 합산될 수 있지만, 선택기는 미디어 쿼리 내와 같은 다양한 컨텍스트에서 필연적으로 중복되는 경우가 많으므로 적극적으로 적용할 수 있는 것은 아닐 수 있습니다. - 공백과 탭은 HTML, CSS, JavaScript에서 개발자가 편리하게 사용할 수 있는 기능입니다. 추가 압축기는 모든 탭과 공백을 삭제할 수 있습니다. 다른 중복 제거 기법과 달리 이러한 최적화는 페이지의 표현에 이러한 공백이나 탭이 필요하지 않은 한 비교적 적극적으로 적용할 수 있습니다. 예를 들어 사용자가 실제로 보게 될 콘텐츠의 가독성을 보장하므로 HTML 문서에서 텍스트 실행 내의 공백은 유지하는 것이 좋습니다.
<html><head><style>.awesome-container{font-size:120%;width:50%}</style></head><body><div>This is my awesome container, and it is <em>so</em> awesome.</div><script>awesomeAnalytics()</script></body></html>
이전 단계를 적용하면 페이지가 516자에서 204자로 줄어들어 약 60%의 절감 효과를 얻을 수 있습니다. 가독성이 좋지 않지만 사용할 수 있는 데는 문제가 없습니다. 최신 개발 관행을 사용하면 형식이 올바르고 읽기 쉬운 소스 코드 버전을 프로덕션에 제공하는 잘 최적화된 코드와 별도로 유지할 수 있습니다. 변환된 프로덕션 코드의 가독성 있는 표현을 제공하는 소스 맵과 결합하면 프로덕션에서 버그를 더 쉽게 해결할 수 있으므로 사용자 환경을 위해 성능을 최적화하면서도 좋은 개발자 환경을 유지할 수 있습니다.
이전 예에서는 중요한 점을 보여줍니다. 임의의 텍스트를 압축하도록 설계된 범용 압축기는 이전 예의 페이지를 상당히 잘 압축할 수 있지만 의견을 삭제하거나 CSS 규칙을 축소하거나 수십 개의 기타 콘텐츠 관련 최적화를 수행할 수는 없습니다. 이러한 이유로 전처리, 최소화, 기타 컨텍스트 인식 최적화가 중요합니다.
마찬가지로 위에 설명된 기법은 텍스트 기반 애셋을 넘어 확장될 수 있습니다. 이미지, 동영상, 기타 콘텐츠 유형에는 자체 메타데이터 형식과 다양한 페이로드가 포함되어 있습니다. 예를 들어 카메라로 사진을 찍을 때마다 파일에는 카메라 설정, 위치 등 많은 추가 정보가 삽입됩니다. 애플리케이션에 따라 이 데이터가 중요할 수도 있고(예: 사진 공유 사이트) 완전히 쓸모없을 수도 있습니다. 삭제할 가치가 있는지 고려해야 합니다. 실제로 이 메타데이터는 이미지당 최대 수십 킬로바이트를 추가할 수 있습니다.
간단히 말해, 애셋의 효율성을 최적화하는 첫 번째 단계로 다양한 콘텐츠 유형의 인벤토리를 구축하고 크기를 줄이기 위해 적용할 수 있는 콘텐츠별 최적화 종류를 고려하세요. 그런 다음 이러한 최적화가 무엇인지 파악한 후 빌드 및 출시 단계에 추가하여 최적화를 자동화하여 프로덕션에 대한 모든 새 버전에 일관되게 적용되도록 합니다.
압축 알고리즘을 사용한 텍스트 압축
텍스트 기반 애셋의 크기를 줄이는 다음 단계는 압축 알고리즘을 적용하는 것입니다. 이는 텍스트 기반 페이로드를 사용자에게 전송하기 전에 반복 가능한 패턴을 적극적으로 검색하고 사용자 브라우저에 도착하면 압축을 해제하는 방식으로 한 단계 더 나아갑니다. 그 결과 이러한 리소스가 더욱 크게 줄어들고 다운로드 시간이 단축됩니다.
- gzip 및 Brotli는 텍스트 기반 애셋(CSS, JavaScript, HTML)에서 가장 우수한 성능을 보이는 일반적으로 사용되는 압축 알고리즘입니다.
- 모든 최신 브라우저는 gzip 및 Brotli 압축을 지원하며
Accept-EncodingHTTP 요청 헤더에서 두 압축 모두 지원을 알립니다. - 서버가 압축을 사용 설정하도록 구성되어 있어야 합니다. 웹 서버 소프트웨어는 기본적으로 텍스트 기반 리소스를 압축하는 모듈을 사용 설정하는 경우가 많습니다.
- gzip과 Brotli 모두 압축 수준을 조정하여 압축률을 개선할 수 있습니다. gzip의 경우 압축 설정 범위는 1~9이며 9가 가장 좋습니다. Brotli의 경우 이 범위는 0~11이며 11이 가장 좋습니다. 하지만 압축률이 높을수록 시간이 더 필요합니다. 동적으로 압축되는 리소스(요청 시)의 경우 범위 중간에 있는 설정이 압축률과 속도 간에 가장 적절한 절충안을 제공하는 경향이 있습니다. 하지만 정적 압축은 가능합니다. 정적 압축은 응답이 미리 압축되므로 각 압축 알고리즘에 사용할 수 있는 가장 적극적인 압축 설정을 사용할 수 있습니다.
- 콘텐츠 전송 네트워크 (CDN)는 일반적으로 자격 요건을 충족하는 리소스의 자동 압축을 제공합니다. CDN은 동적 및 정적 압축도 관리할 수 있으므로 압축에 대해 걱정할 필요가 없습니다.
gzip 및 Brotli는 바이트 스트림에 적용할 수 있는 일반적인 컴프레서입니다. 내부적으로는 이전에 검사한 파일의 콘텐츠를 기억하고 이후 중복된 데이터 프래그먼트를 효율적인 방식으로 찾아 바꾸려고 시도합니다.
실제로 gzip과 Brotli는 모두 텍스트 기반 콘텐츠에서 가장 우수한 성능을 발휘하며, 큰 파일의 경우 압축률이 70~90% 에 달하는 경우가 많습니다. 하지만 무손실 또는 손실 압축 기법을 사용하는 대부분의 이미지 형식과 같은 대체 알고리즘을 사용하여 이미 압축된 이러한 알고리즘 애셋을 실행하면 개선 효과가 거의 없습니다.
모든 최신 브라우저는 Accept-Encoding HTTP 요청 헤더에서 gzip 및 Brotli 지원을 공지합니다. 하지만 클라이언트가 요청할 때 압축된 리소스를 제공하도록 웹 서버를 올바르게 구성하는 것은 호스팅 제공업체의 책임입니다.
| 파일 | 알고리즘 | 압축되지 않은 크기 | 압축된 크기 | 압축비 |
|---|---|---|---|---|
| angular-1.8.3.js | Brotli | 1,346 KiB | 256 KiB | 81% |
| angular-1.8.3.js | gzip | 1,346 KiB | 329 KiB | 76% |
| angular-1.8.3.min.js | Brotli | 173 KiB | 53 KiB | 69% |
| angular-1.8.3.min.js | gzip | 173 KiB | 60 KiB | 65% |
| jquery-3.7.1.js | Brotli | 302 KiB | 69 KiB | 77% |
| jquery-3.7.1.js | gzip | 302 KiB | 83 KiB | 73% |
| jquery-3.7.1.min.js | Brotli | 85 KiB | 27 KiB | 68% |