불필요한 리소스 다운로드를 없애는 것 외에 페이지 로드 속도를 개선하기 위해 할 수 있는 가장 좋은 방법은 나머지 리소스를 최적화하고 압축하여 전체 다운로드 크기를 최소화하는 것입니다.
데이터 압축 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% |
| jquery-3.7.1.min.js | gzip | 85 KiB | 30 KiB | 65% |
| lodash-4.17.21.js | Brotli | 531 KiB | 73 KiB | 86% |
| lodash-4.17.21.js | gzip | 531 KiB | 94 KiB | 82% |
| lodash-4.17.21.min.js | Brotli | 71 KiB | 23 KiB | 68% |
| lodash-4.17.21.min.js | gzip | 71 KiB | 25 KiB | 65% |
위 표에는 Brotli와 gzip 압축이 몇 가지 잘 알려진 JavaScript 라이브러리에 제공할 수 있는 절감액이 나와 있습니다. 절감률은 파일과 알고리즘에 따라 65% ~86% 입니다. 참고로 Brotli와 gzip 모두 각 파일에 최대 압축 수준이 적용되었습니다. 가능한 경우 gzip보다 Brotli를 사용하는 것이 좋습니다.
압축을 사용 설정하는 것은 구현하기 가장 간단하고 효과적인 최적화 중 하나입니다. 웹사이트에서 이를 활용하지 않으면 사용자에게 더 나은 성능을 제공할 수 있는 큰 기회를 놓치게 됩니다. 다행히 많은 웹 서버는 이 중요한 최적화를 지원하는 기본 구성을 제공하며, 특히 CDN은 압축 속도와 비율의 균형을 맞추는 방식으로 이를 구현하는 데 매우 효과적입니다.
압축이 작동하는 것을 빠르게 확인하려면 Chrome DevTools를 열고 네트워크 패널을 열고 원하는 페이지를 로드한 후 네트워크 패널의 맨 아래를 확인하면 됩니다.
위 이미지와 같이 다음 항목의 분석이 표시됩니다.
- 요청 수입니다. 페이지에 로드된 리소스 수입니다.
- 모든 요청의 전송 크기입니다. 이는 페이지 리소스에 적용된 압축의 효과를 반영합니다.
- 모든 요청의 리소스 크기입니다. 이는 페이지의 리소스가 압축 해제된 후의 크기를 반영합니다.
Core Web Vitals에 미치는 영향
성능 개선을 반영하는 측정항목이 없으면 성능 개선을 측정할 수 없습니다. Core Web Vitals 이니셔티브는 실제 사용자 경험을 반영하는 측정항목을 만들고 이에 대한 인식을 높이기 위해 마련되었습니다. 이는 사용자 환경 품질로 명확하게 변환되지 않는 단순한 페이지 로드 시간과 같은 측정항목과 대조됩니다.
이 가이드에 설명된 최적화를 웹사이트의 리소스에 적용하면 최적화된 리소스와 관련 측정항목에 따라 Core Web Vitals에 미치는 영향이 달라질 수 있습니다. 하지만 이러한 최적화를 적용하면 웹사이트의 Core Web Vitals를 개선할 수 있는 경우가 있습니다.
- 최소화되고 압축된 HTML 리소스는 해당 HTML의 로드와 하위 리소스의 검색 가능성을 개선하여 하위 리소스의 로드를 개선할 수 있습니다. 이는 페이지의 최대 콘텐츠 페인트(LCP)에 도움이 될 수 있습니다.
rel="preload"와 같은 리소스 힌트를 사용하여 리소스의 검색 가능성에 영향을 줄 수 있지만, 너무 많은 리소스 힌트를 사용하면 대역폭 경합 문제가 발생할 수 있습니다. 탐색 요청의 HTML 응답이 압축되도록 하면 미리 로드 스캐너가 최대한 빨리 리소스를 검색할 수 있습니다. - 압축을 사용하면 일부 LCP 후보도 더 빨리 로드할 수 있습니다. 예를 들어 LCP 후보인 SVG 이미지는 텍스트 기반 압축을 통해 리소스 로드 지속 시간을 줄일 수 있습니다. 이는 JPEG 이미지가 손실 압축을 사용하는 방식과 같이 다른 압축 방법을 통해 본질적으로 압축되는 다른 이미지 유형에 적용하는 최적화와는 다릅니다.
- 또한 텍스트 노드는 LCP 후보가 될 수도 있습니다. 이 가이드에 설명된 기법은 웹페이지의 텍스트에 웹 글꼴을 사용하는지 여부에 따라 달라집니다. 웹 글꼴을 사용하는 경우 웹 글꼴 최적화 권장사항이 적용됩니다. 하지만 웹 글꼴을 사용하지 않고 리소스 로드 기간이 발생하지 않고 표시되는 시스템 글꼴을 사용하는 경우 CSS를 최소화하고 압축하면 이 기간이 줄어들어 잠재적인 LCP 텍스트 노드의 렌더링이 더 빨리 발생할 수 있습니다.
결론
텍스트 기반 애셋의 인코딩 및 전송을 최적화하는 방법은 기본적인 성능 개념이지만 큰 영향을 미칩니다. 축소 및 압축이 가능한 리소스가 이러한 최적화의 이점을 누릴 수 있도록 최선을 다해야 합니다.
무엇보다 이러한 프로세스가 자동화되어야 합니다. 축소의 경우 번들러를 사용하여 축소 가능한 리소스에 축소를 적용합니다. 웹 서버 구성이 압축을 지원하는지 확인하고, 가장 효과적인 압축을 사용하세요. 이 작업을 최대한 간단하게 하려면 CDN을 사용하여 압축을 자동화하세요. CDN은 리소스를 압축할 수 있을 뿐만 아니라 매우 빠르게 압축할 수도 있습니다.
이러한 기준 성능 개념을 웹사이트의 아키텍처에 적용하면 성능 최적화 노력이 좋은 기반 위에 이루어지고 후속 최적화가 좋은 기준 관행이라는 견고한 토대 위에 이루어질 수 있습니다.