프론트엔드/HTTP - 후

Compression in HTTP

5ub1n 2024. 10. 13. 16:57

HTTP에서의 압축


압축은 웹사이트 성능을 향상시키는 중요한 방법이다.

일부 문서의 경우, 최대 70%까지 크기를 줄이면, 데이터를 전송하는 데 필요한 대역폭(네트워크 리소스)이 줄어들어 전송 속도가 빨라지거나 네트워크 부하가 줄어든다.

파일이 작아지면 인터넷 연결이 더 작은 데이터를 처리하므로 전송 효율이 높아진다.

수년에 걸쳐 알고리즘도 더 효율적으로 발전했으며, 새로운 알고리즘이 클라이언트와 서버에서 지원되고 있다.

 

실제로 웹 개발자는 압축 메커니즘을 구현할 필요가 없다.

브라우저와 서버 모두 이미 이를 구현하고 있지만, 서버가 적절하게 구성되어 있는지 확인해야 한다.

압축은 세 가지 수준에서 발생한다.

 

  • 먼저, 일부 파일 형식은 특정 최적화된 방법으로 압축된다.
  • 그런 다음, HTTP 수준(HTTP level)에서 일반 암호화가 발생할 수 있다.
    리소스는 끝에서 끝까지 압축되어 전송된다.
  • 마지막으로 압축은 HTTP 연결의 두 노드(connection level, between two nodes of an HTTP connection / 서버, 클라이언트, 프록시 등) 사이의 연결 수준에서 정의될 수 있다.
HTTP level : HTTP 요청과 응답의 리소스가 포함된 부분에서 압축이 적용된다.
HTTP 요청이나 응답의 본문에 있는 리소스(예 : HTML, CSS, 이미지 등)가 압축된다.
이 압축은 클라이언트와 서버 간에 전송되는 콘텐츠 자체를 대상으로 한다.
데이터 크기를 줄여 전송 속도를 높이고 대역폭을 절약하려는 목적이다.

connection level : 네트워크 연결 경로에 해당된다.
두 노드(클라이언트, 서버 또는 중간 프록시 등) 사이에서 데이터를 전달하는 네트워크 연결에 적용된다.
이 경우 압축은 리소스가 아닌, 데이터를 전송하는 통신 경로를 압축하여 전송의 효율성을 높인다.
TLS 압축이나 네트워크 레벨에서 적용되는 전송 효율화 기술이 이에 해당된다.
연결을 통해 전달되는 전체 데이터의 효율을 높이고, 연결 경로 상의 속도와 보안성을 개선하려는 목적이다.

따라서 HTTP level은 리소스의 압축과 관련이 있고, connection level은 네트워크 연결 자체의 효율성에 중점을 둔다.

 


파일 형식 압축 File format compression

각 데이터 유형에는 약간의 중복성, 즉 낭비되는 공간이 있다.

텍스트가 일반적으로 최대 60%의 중복성을 가질 수 있다면 오디오 및 비디오와 같은 다른 미디어의 경우, 이 비율이 훨씬 높을 수 있다.

텍스트와 달리 이러한 다른 미디어 유형은 데이터를 저장하는 데 많은 공간을 사용하므로 저장 공간을 최적화하고 공간을 확보해야 할 필요성이 매우 일찍부터 분명해졌다.

엔지니어들은 이러한 특정 목적을 위해 설계된 파일 형식에 사용되는 최적화된 압축 알고리즘을 설계했다.

파일에 사용되는 압축 알고리즘은 크게 두 가지 범주로 분류할 수 있다.

 

  • 손실없는 압축은 압축-압축 해제 과정에서 복구된 데이터가 원본과 달라지지 않는 방식을 말한다.
    복구된 데이터는 바이트 단위로 일치한다.
    이미지의 경우, GIF와 PNG가 손실없는 압축 방식을 사용한다.
  • 손실 압축은 원본 데이터를 사용자에게 거의 또는 전혀 인지되지 않도록 변경하는 방식이다.
    웹에서 사용되는 비디오 형식은 손실 압축을 사용하여, JPEG 이미지 형식도 마찬가지로 손실 압축 방식이다.

일부 형식은 무손실 압축과 손실 압축 모두에 사용될 수 있다.

예를 들어 Webp와 같은 형식이 있으며, 일반적으로 손실 압축 알고리즘은 더 많이 또는 덜 압축하도록 설정할 수 있는데, 이는 물론 더 낮은 또는 더 높은 품질로 이어진다.

웹사이트 성능을 개선하려면 허용 가능한(시각적으로 만족스러운 수준) 품질 수준을 유지하면서 가능한 한 많이 압축하는 것이 이상적이다.

이미지의 경우, 도구로 생성된 이미지는 웹에 최적화되지 않을 수 있다.

필요한 품질로 최대한 압축하는 도구를 사용하는 것이 좋다.

이러한 작업에 특화된 도구들이 많이 있다.

 

손실 압축 알고리즘은 일반적으로 무손실 압축 알고리즘보다 더 효율적이다.

 

참고 : 압축은 특정 유형의 파일에서 더 효과적으로 작동하기 때문에, 이미 압축된 파일을 다시 압축하는 것은 보통 아무런 이득이 없다.
사실, 이는 종종 역효과를 낼 수도 있다.
압축 알고리즘은 일반적으로 사전(dictionary)을 필요로 하며, 이는 원본 파일 크기에 추가되기 때문에 추가적인 압축 이득보다 오버헤드 비용이 더 커져 파일이 오히려 더 커질 수 있다.
따라서 압축된 형식의 파일에는 다음 두 가지 기술을 사용해선 안된다.

오버 헤드는 어떤 작업을 수행할 때 추가적으로 발생하는 비용이나 자원을 의미한다.
예를 들어, 파일을 압축할 때 압축 알고리즘은 파일의 내용을 효율적으로 압축하기 위해 사전같은 추가 정보를 포함한다.
이 추가 정보는 압축한 파일을 다시 해독하는 데 필요한 데이터로, 파일의 원래 크기 외에 더해지는 부분이다.
압축된 파일을 다시 압축할 경우, 이러한 오버헤드가 중복으로 추가되어 파일 크기가 오히려 커질 수 있다.

 


End-to-end 압축 End-to-end compression

 

압축의 경우 End-to-end 압축은 웹사이트 성능이 가장 크게 향상되는 부분이다.

End-to-end 압축은 서버에서 수행되고 클라이언트에 도달할 때까지 변경되지 않고 지속되는 메시지 본문의 압축을 의미한다.

중간 노드가 무엇이든 몸체는 그대로 유지된다.

 

1. 리소스가 요청되었다. 
2. 리소스가 압축되어 반환된다.
3. 중간 노드는 본문의 압축을 풀지 않는다.
4. 클라이언트는 본문의 압축을 푼다.

 

모든 최신 브라우저와 서버는 이를 지원하며, 협상해야 할 유일한 것은 사용할 압축 알고리즘이다.

이러한 알고리즘은 텍스트에 최적화되어 있다.

1990년대에는 압축 기술이 빠르게 발전하면서 연속적인 알고리즘들이 선택 가능한 옵션에 추가되었다.

현재는 두 가지 알고리즘만이 중요하다.

가장 일반적인 gzip과 새로운 도전자인 br이다.

 

사용할 알고리즘을 선택하기 위해 브라우저와 서버는 사전적 콘텐츠 협상(proactive content negotiation)을 사용한다.

브라우저는 자신이 지원하는 알고리즘과 그 우선순위를 포함한 Accept-Encoding 헤더를 서버로 보낸다.

서버는 이 중 하나를 선택한 뒤, 해당 알고리즘을 사용하여 응답 본문을 압축하고, 선택된 알고리즘을 브라우저에 알리기 위해 Content-Encoding 헤더를 사용한다.

인코딩을 기반으로 한 표현 형식을 선택하기 위해 콘텐츠 협상이 사용되었으므로, 서버는 반드시 응답에 Accept-Encoding을 포함한 Vary 헤더를 추가해야 한다.

이를 통해 캐시는 리소스의 다양한 표현 형식을 구분하여 캐시할 수 있다.

웹 브라우저와 서버가 웹 페이지 데이터를 전송할 때 압축 알고리즘을 선택하고 이를 캐시에 저장하는 방식을 다루는 내용이다.

웹 페이지를 전송할 때, 데이터를 압축하면 전송 속도가 빨라지고 데이터 용량도 줄어든다.
이를 위해 브라우저와 서버는 압축 방식을 사전에 협상하여 결정한다.

브라우저는 서버에 웹 페이지를 요청하면서 자신이 지원하는 압축 방식을 Accept-Encoding이라는 헤더에 담아 보낸다.
예를 들어, 브라우저가 gzip, br 방식을 지원한다면 이를 Accept-Encoding 헤더에 포함해 서버에 전달한다.
서버는 브라우저가 지원하는 압축 방식 중 하나를 선택한다.
선택한 방식으로 웹 페이지 데이터를 압축하여 응답 본문에 담고, 어떤 압축 방식을 사용했는지 Content-Encoding 헤더에 표시하여 브라우저에 보낸다.
압축 방식에 따라 웹 페이지의 표현 방식이 다를 수 있기 때문에, 서버는 캐시가 이 차이를 인식할 수 있도록 Vary 헤더에 Accept-Encoding 값을 포함시킨다.
이 Vary: Accept-Encoding 헤더 덕분에 캐시는 동일한 리소스의 여러 버전(예 : gzip 압축된 버전, br 압축된 버전 등)을 각각 따로 저장할 수 있다.
그래서 다른 브라우저나 요청이 다른 압축 방식을 요구하더라도 올바른 버전을 가져올 수 있다.

서버가 압축된 데이터를 브라우저에 보낼 때, 캐시가 제대로 작동하도록 추가적인 정보를 포함해야 한다.
브라우저는 각자 지원하는 압축 방식(gzip, br 등)이 다르다.
서버는 브라우저에 맞는 방식으로 데이터를 압축해 보내지만, 캐시(중간 저장소)는 이런 차이를 모르고 모든 브라우저에 똑같은 데이터를 보내려 할 수 있다.
만약 캐시가 압축 방식의 차이를 모른다면, A라는 브라우저는 gzip을 요청했고, 서버가 그에 맞춰 gzip 압축 데이터를 캐시에 저장한다.
그런데 B라는 브라우저는 br을 요청했지만, 캐시는 이미 저장된 gzip 데이터를 보내버린다.
여기서 원본 데이터는 같다.
B는 gzip이 아닌 br을 기대했으므로, 데이터를 제대로 해석하지 못한다.
이 문제를 방지하기 위해 서버는 Vary: Accept-Encoding 헤더를 추가한다.
이 헤더는 캐시에게 압축 방식(Accept-Encoding)마다 별도로 데이터를 구분해 저장해야 한다고 알려준다.
결과적으로, 캐시는 gzip으로 압축된 데이터와 br로 압축된 데이터를 각각 저장하고, 요청에 따라 적절한 데이터를 제공한다.
각자 gzip으로 압축된 데이터와 br로 압축된 데이터를 저장하는 시기는 각각 다른 브라우저(A,B,C)가 요청했을 때, 압축하여 응답하고 그 데이터(gzip, br로 압축하기 전 원본 데이터는 같지만 압축 방식이 다르기 때문에 결과적으로는 서로 다른 데이터)를 압축된 버전으로 저장한다.

 

1. 클라이언트는 두 가지 압축 알고리즘에 대한 지원을 나타내고 있다.

GET /doc HTTP/1.1
Accept-Encoding: br, gzip

2. 리소스가 압축되어 반환된다.
Vary 헤더는 콘텐츠 협상이 알고리즘을 선택하는 데 사용되었음을 나타낸다.
Vary 헤더는 캐시에게 "이 응답은 특정 요청에 따라 달라질 수 있으므로, 방식의 차이를 인식하고 그에 맞는 버전들(gzip, br 등)을 따로 저장해야 한다"라고 지시하는 역할을 한다.

HTTP/1.1 200 OK
Content-Encoding: br
Vary: Accept-Encoding

 

압축을 하면 성능이 크게 향상되므로 이미지, 오디오 파일, 비디오 등 이미 압축된 파일을 제외한 모든 파일에 대해 활성화하는 것이 좋다.

 

Apache는 압축을 지원하고 mod_deflate를 사용한다.

Nginx에는 ngx_http_gzip_module이 있다.

IIS의 경우 <httpCompression> 요소이다.

 


Hop-by-hop 압축 Hop-by-hop compression

 

Hop-by-hop 압축은 end-to-end 압축과 유사하지만 한 가지 근본적인 요소에서 다르다.

서버의 리소스에서 특정 표현을 생성한 뒤 이를 전송하는 방식으로 압축이 이루어지는 것이 아니라, 클라이언트와 서버 사이 경로상의 두 노드 간 메시지 본문에 대해 압축이 이루어진다는 점이다.

연속적인 중간 노드 간 연결에서는 서로 다른 압축 방식을 적용할 수도 있다.

 

 

1. 클라이언트는 압축되지 않은 본문을 보낸다.
2. 중간 노드는 hop-by-hop 방식으로 본문을 압축된 상태 또는 압축하지 않은 상태로 전송한다.
3. 서버는 압축되지 않은 본문을 받는다.

Hop-by-hop 방식의 압축에서는 두 노드 간에 데이터가 압축되어 전송되더라도, 최종적으로 서버가 받는 데이터는 압축되지 않은 원본이다.

 

이를 수행하기 위해 HTTP는 end-to-end 압축을 위한 콘텐츠 협상과 유사한 메커니즘을 사용한다.

요청을 전송하는 노드는 TE 헤더를 사용하여 자신의 의사를 알리고, 상대 노드는 적합한 방식을 선택하여 이를 적용한 뒤, Transfer-Encoding 헤더를 통해 선택한 방식을 명시한다.

 

 

1. 클라이언트가 요청 메시지를 보낸다.
GET /doc HTTP/1.1

2. 메시지를 전달하는 동안 어떤 압축을 지원하는지 보여준다.
GET /doc HTTP/1.1
TE: gzip, br

3. 메시지를 전달한다.
GET /doc HTTP/1.1

4. 압축되지 않은 본문의 리소스를 반환한다.
HTTP/1.1 200 OK

5. 본문을 압축하고 메시지를 전달한다.
HTTP/1.1 200 OK
Transfer-Encoding: br

6. 리소스의 압축을 해제하고 클라이언트에 메시지를 반환한다.
HTTP/1.1 200 OK

 

실제로 hop-by-hop 압축은 서버와 클라이언트에 대해 투명하며 거의 사용되지 않는다.

TE 및 Transfer-Encoding은 주로 리소스의 길이를 알지 못한 상태에서 전송을 시작할 수 있도록 응답을 청크 단위로 전송하는 데 사용된다.

 

홉(hop) 레벨에서 Transfer-Encoding과 압축(Compression)을 사용하는 것은 Apache, Nginx, IIS와 같은 대부분의 서버에서는 매우 드물다는 점에 유의한다.

이러한 설정은 주로 프록시 레벨에서 이루어진다.


 

Compression in HTTP - HTTP | MDN

Compression is an important way to increase the performance of a website. For some documents, size reduction of up to 70% lowers the bandwidth capacity needs. Over the years, algorithms also got more efficient, and new ones are supported by clients and ser

developer.mozilla.org