【HTTPコンテンツ圧縮】ネットワーク通信量を減らそう。

# はじめに
こんにちは、IT業界経験6カ月の韓国出身新人エンジニアです。
業務で経験した技術を深堀りをするため、Qiitaを始めました。

この記事は、ネットワーク通信量を減らすための設定や圧縮アルゴリズムなど、
私が勉強した内容を書いた記事です。
# HTTP コンテンツの圧縮とは？
HTTP コンテンツの圧縮とは、HTTP の通信において Web サーバー側が返すデータを、なんらかの形式で圧縮してクライアントに返すことです。圧縮されたレスポンスをクライアント側は解凍して利用します。

HTTP コンテンツの圧縮によって得られるメリット・デメリットは以下の通りです。
### メリット
・**通信量を減らせる。**
・それによって通信時間が削減し、**サイトのパフォーマンスが向上**できる。
### デメリット
・圧縮・解凍にコストがかかる
・大容量コンテンツやもともと圧縮されているコンテンツ（画像、動画、PDFなど）には非効率
・サイズが削減できない割に、圧縮・解凍にCPUリソースを使い、数百MBを超えるコンテンツになるとそれずれ数秒がかかる。
### HTTP通信の流れ
Webアプリケーションは、ネットワークからリソースを取得し、実行時にエンドユーザのブラウザにロードするように設計されています。

![수정됨_ResourceSizeVsTransferSize01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/ca079a39-f5ff-8278-b489-1c8ac2044e1b.png)
一盤的に通信量が大きければ大きいほど通信速度は遅くなります。

コンテンツのサイズを減らすために色んな圧縮アルゴリズムがあります。
各圧縮アルゴリズムはネットワークリソースの通信に必要な時間を減らすように設計されています。

圧縮は、gzip や brotli などの標準的なリソース圧縮アルゴリズムを使用することで大幅に削減できます。
![수정됨_ResourceSizeVsTransferSize02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/2d1ada01-b9f8-ae10-9573-8bd702f69dc2.png)
![수정됨_ResourceSizeVsTransferSize03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/a872ccb5-a980-4f2b-3247-388899ffd777.png)
80KBだったJSファイルが24KBで圧縮されクライアントに渡されます。
クライアントは渡されたファイルを解凍してブラウザを構成します。

### HTTPコンテンツ圧縮の事例
このような圧縮技術は既に私たちが使っている色んなWEBサイトで使われています。

実際にYahooに接続してGoogle Chromeデベロッパーツールでネットワーク通信を見てみると
![dign.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/934f6da7-4ca3-c5c3-01cf-f39a35af38b8.png)
YahooサイトのHTMLドキュメントは168KBから44.5KBに圧縮できていることが分かります。

# どうやってコンテンツを圧縮する？
### 圧縮方法
クライアントとサーバはコンテンツを圧縮して通信するということを事前に合意していなければなりません。
そのため、クライアントは`Accept-Encoding`をリクエストヘッダに付加し、サーバは`Content-Encoding`をレスポンスヘッダに付加して相互通信を行います。
![수정됨_20210129123916.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/6869a31c-f061-60cd-37ff-d4005e3e9fd5.png)
上記のように設定ができたら、次のステップに行きます。

圧縮を実装するにはクライアントに渡すコンテンツ圧縮を誰が処理するのかによって大きく４つの方法があります。

・ApacheやNginx、IISなどの`WEBサーバ`で処理
・TomcatやWebLogicなどの`Web Application Server(WAS)`で処理
・`Servlet Filter`に登録して処理
・HTMLや画像などの`静的コンテンツを事前に圧縮`しておく

以外にも色んな圧縮形式（gzip、defalte、br）の一つを選んで圧縮します。

・gzip：LZ77 と 32 ビット CR を用いた圧縮形式
・deflate：zlib 構造体と deflate 圧縮アルゴリズムを用いた圧縮形式
・br：Brotli アルゴリズムを用いた圧縮形式。gzip に近いが大容量の言語辞書を用いて、頻出するパターンの単語を圧縮して効率化。そのため文章的なテキストではgzip よりも圧縮率が高いと言われる

### Brotil(br)と既存のDeflate(gzip)形式
この二つの性能を比較した[海外の分析記事](https://cran.rproject.org/web/packages/brotli/vignettes/benchmarks.html)によると、Brotilアルゴリズムがgzipより圧縮率が高いことが分かります。しかし、圧縮と解凍の速度はgzipより遅いため、サイズが小さい静的コンテンツで通信するときはgzipより通信速度が遅いです。

# コンテンツを圧縮してみます。
この記事ではJSONをSpring Bootに取り込まれている`WAS（Tomcat）`でコンテンツを圧縮していきます。

#### 設定
設定する方法は簡単です。下記のように設定できます。
[spring Docs](https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties.server)
```application.properties
# コンテンツ圧縮の設定 (default = false)
server.compression.enabled=true 
# 圧縮から除外するユーザエージェントリスト
server.compression.excluded-user-agents=
# 圧縮する mime-type、コンマで区切る
# (default = text/html, text/xml, text/plain, text/css, text/javascript, 
#            application/javascript, pplication/json, application/xml)
server.compression.mime-types=text/html, text/xml, text/plain, text/css, text/javascript, \
                              application/javascript, application/json, application/xml 
# 圧縮を実行するために必要な「Content-Length」の最小値。(default = 2KB)
server.compression.min-response-size=2048
```
設定を適用し、リズエストをなげると下記のようにgzipを使って圧縮が行われます。
#### 設定前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/32d1d9e4-9512-e78c-01a5-ad824a89a2c3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/f289f9f5-d3d5-51e7-40c0-e0aeda0b1b9c.png)

#### 設定後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/7259888b-c18c-c926-0812-a3bf14d87407.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/caaba565-f0bd-fbff-6ae9-4675aca72e5c.png)
圧縮前269KBだったjsonが26.5KBまで圧縮されました。ほぼ90％の通信量を減らすことができました。


# まとめ
WAS設定をして圧縮してみました。
通信量は削減できましたが、通信速度は少しおそくなりました。しかし、ms単位なので通信量を減らすメリットの方がデメリットを上回っています。

この記事ではただjsonを圧縮しただけですが、実際に動いてるサービスには画像や動画などサイズが大きいリソースがたくさん使われているので、圧縮だけでなく色んな方法で通信パフォーマンス向上できると思います。

これからその技術についてもっと勉強していきたいと思います。

# 参考サイト
https://developer.mozilla.org/ja/docs/Web/HTTP/Compression
https://yozm.wishket.com/magazine/detail/1739/
https://gitabout.com/18
https://developer.medley.jp/entry/2021/02/01/180003
https://www.webperf.tips/tip/resource-size-vs-transfer-size/