불필요한 리소스 다운로드를 제거한 후 페이지 로드 속도를 향상시키기 위해 할 수 있는 가장 좋은 작업은 나머지 리소스를 최적화하고 압축하여 전체 다운로드 크기를 최소화하는 것입니다.
데이터 압축 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자부터 시작)를 줄이려면 어떻게 해야 하나요?
- 주석은 흥미롭지만, 메시지의 의미에는 영향을 주지 않습니다. 메시지를 전송할 때 이를 제거합니다.
- 효율적인 방법으로 헤더를 인코딩할 수 있는 좋은 기술들이 있습니다. 예를 들어 모든 메시지에 '형식' 및 '날짜'가 있다는 것을 안다면, 이 메시지를 짧은 정수 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-Encoding
HTTP 요청 헤더에서 두 가지 모두에 대한 지원을 광고합니다. - 서버는 압축을 사용 설정하도록 구성되어야 합니다. 웹 서버 소프트웨어는 종종 모듈이 텍스트 기반 리소스를 압축하도록 기본적으로 사용 설정합니다.
- 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% |
위의 표는 잘 알려진 JavaScript 라이브러리 중 일부에 대해 Brotli 및 gzip 압축을 모두 사용하면 얻을 수 있는 절감 효과를 보여줍니다. 파일과 알고리즘에 따라 절감 폭은 65~86%입니다. 참고로 Brotli와 gzip 모두 각 파일에 최대 압축 수준이 적용되었습니다. 가능한 경우 gzip보다 Brotli를 사용하세요.
압축을 사용 설정하는 것은 구현하기에 가장 간단하고 효과적인 최적화 중 하나입니다. 웹사이트에서 이 기능을 활용하지 않는다면 사용자의 성능을 개선할 수 있는 큰 기회를 놓치고 있는 것입니다. 다행히 많은 웹 서버는 이 중요한 최적화를 사용 설정하는 기본 구성을 제공하며, 특히 CDN은 압축 속도와 비율의 균형을 맞추는 방식으로 이를 구현하는 데 매우 효과적입니다.
압축이 작동하는 모습을 빠르게 확인하는 방법은 Chrome DevTools를 열고 Network 패널을 연 다음 원하는 페이지를 로드하고 네트워크 패널 하단을 관찰하는 것입니다.
위 이미지와 같이 다음과 같은 세부정보가 표시됩니다.
- 요청 수입니다. 페이지에 로드된 리소스 수입니다.
- 모든 요청의 전송 크기입니다. 이는 페이지의 리소스에 적용된 압축의 효과를 반영합니다.
- 모든 요청의 리소스 크기입니다. 이는 페이지의 리소스가 압축 해제된 후의 크기를 반영합니다.
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은 리소스를 압축할 뿐만 아니라 매우 빠르게 압축할 수 있습니다.
이러한 기준 성능 개념을 웹사이트 아키텍처에 통합하면 성능 최적화 작업이 탄탄한 기반을 갖추고 후속 최적화 작업이 우수한 기준 관행의 견고한 토대를 바탕으로 할 수 있습니다.