hyiromori’s tech blog

Webエンジニア hyiromori の技術ブログです。

あらすじ

  • エンジニアやってるけど、自分の技術を伝える手段を持ってないことに気付いた
  • 手軽に公開できるので GitHub Pages を採用した
  • 可搬性を高めるために(別のホスティングとかに移動しやすいように)独自ドメインを設定した
  • 柔軟に色々なことができるように、静的サイトジェネレーターもどきを作った
  • 一部は SPA で作成し、技術スタックは TypeScript + React + Webpack + ServiceWorker で作った
  • できあがったポートフォリオサイトは こちら
  • ソースコードGitHub にあります

作ろうと思ったきっかけ

  1. 今後もエンジニアとして飯を食っていこうと思った時何が必要か、的なことをふと考えた。
  2. 勉強してできることを増やしていくことも大事だけど、自分ができるを伝えることも同じぐらい大事で、でもその努力を今のところしていないな〜、と思った。
  3. パッと見てこんなことができる人なんだ〜、と理解してもらえるようなサイトを作れば良さそうだと思った。

という感じで思いたち、じゃあ作ろうと決めた感じです。 ちなみに、調べてみるとこういうのをポートフォリオサイトと言うらしいです。

どうやって公開しようか考えた

お金がかかったり、公開やメンテナンスに手間がかかる方法だと怠惰な自分には続かないので、公開が容易な方法を調べました。 その中で GitHub Pages は、無料で使える上に、 GitHub にプッシュするだけで公開できるので、採用しました。

どうやって作るか考えた

今回の目的は、自分の技術を公開するものなので、なるべく自分で作るのが良いと思いました。 よって、以下のような方針で作ることに決めました。

  • 基本的な部分は Markdown で手軽に書けるようにする
  • SPA が得意なので、動的なページは SPA で作る
    • TypeScript + React + Webpack の(多分)ベーシックな構成にする。

デザインやレイアウトはどうしようか考えた

デザイナーじゃないので凝ったことはしたくないけど、 Bootstrap とかのCSSフレームワークを使うのは「自分の技術の公開」とはなにか違う気がするし、何より面白味がない😏 基本は自分で全部作り、以下のような方針でやることに決めました。

  • なるべくシンプルな構造にする
  • Markdown を変換するので、基本的なHTMLタグを書くだけである程度デザインが整ったページを作れるような構成にする( GitHubMarkdownプレビューのようなイメージ)
  • レスポンシブにする(とりあえず自分の MacbookiPhone の両方でちゃんと表示できることを目標)

サイトの構成を考えた

そんなにコンテンツはないですが、ちょっとだけ考えました。

  • とりあえず自己紹介は必須なので、ホーム画面は主に自己紹介を書く
  • 主に技術記事を書くブログも併設する
  • 自分で実験的に作ったプロダクトを公開するページを作る

GitHub Pages の独自ドメインを設定した

DNS の設定

IP アドレスと CNAME で設定する2つの方法があるようですが、 CNAME の方が管理が楽そうなので、そちらを採用しました。 AWS Route53 での設定は以下のようになります。

f:id:hyirm:20200326085904j:plain

GitHub の設定

設定ページで以下の箇所に独自ドメインを設定するだけで OK です。

f:id:hyirm:20200326085858j:plain

Let's Encrypt で生成された証明書が使われるようです。

f:id:hyirm:20200326085855j:plain

あと CNAME というファイルが自動的に追加され、独自ドメインの設定が保存されるているようです。 間違ってこのファイルを消したら、アクセスできなくなって焦った・・。

静的サイトジェネレーターもどきを作成した

とりあえず GitHub Pages で採用されている Jekyll を当初使おうと思いました。 最初は問題なかったのですが、使っている内に細かい不満が出てきて Jekyll の採用はやめました。

で、他の静的サイトジェネレーターを探してみたのですが、世の中にはたくさんのジェネレーターがあるんですね・・・。 一つ一つ試してみるのも大変ですし、やりたいことは MarkdownHTML に変換することと、 SCSSCSS にできれば大体のことができるので、自作することにしました。

言語の選定

JavaScript にしました。 自分の得意言語であること以外、特に理由はないです。 nodenpm にガッツリ依存しますが、まぁこの2つが潰れることはないでしょう。

ライブラリの選定

以下のライブラリを使用しました。

  • marked : Markdown -> HTML の変換
  • ejs : テンプレートエンジン
  • sass-loader : SCSS -> CSS の変換

Markdown の変換

marked を使って変換します。 次にテンプレートエンジンに渡すので、テキストデータを受け取っておきます。

const fs = require('fs');
const marked = require('marked');
const htmlText = marked(fs.readFileSync('Markdownファイルのパス'))

テンプレートの適用

テンプレート用のHTMLファイルに、Markdown のコンテンツを埋め込みます。 <%- JSのコード %> というような形で埋め込みができます。 詳細は 公式サイト を参照してください。

const ejs = require('ejs');
ejs.renderFile('テンプレートファイルのパス', { content: htmlText }, {}, (error, html) => {
  if (error) {
    throw new Error(error);
  }
  fs.writeFileSync('出力先のパス', html);
});

テンプレート内に書かれた <%- content %>Markdown から変換した HTML データが埋め込まれます。

SCSS の変換

普通の CSS を書いても良いのですが、最低限として色を変数で管理はしたいので、 SCSS で書くことにしました。

const fs = require('fs');
const sass = require('node-sass');

sass.render({ file: '変換元の SCSS ファイルパス' }, (error, result) => {
  if (error) {
    throw new Error(error);
  }
  fs.writeFileSync('出力先の CSS ファイルパス', result.css.toString());
});

公開

レポジトリにプッシュするだけなので、特に何も要らない(笑) https://hyiromori.com/ に公開しています。

まとめ

自分で考えて実装して公開するのは、やっぱり楽しいですね! 実際に公開してみて「どんなものが作れるか」と聞かれたらこれを見せれば良い、という安心感が凄いありますね。 とはいえ、今は積極的に転職活動をしているわけではないので、今のところは単なる自己満足😓

あと、静的サイトジェネレーターは、作るよりも選定する時間の方が長かった・・・。 最初から作っとけば良かった。

2020-03-26 追記

最終的にポートフォリオサイト自体は1つのHTMLだけおいて、ブログははてなブログとかに置くことにしました。 ブログサービスとかの方が手軽にかけて良いですね。 また、実験的に作ったプロダクトは、別リポジトリでも GitHub Pages に公開できるのでそちらも分離しました。 (例: test というリポジトリhttps://hyiromori.com/test/ で公開できます)

※ Qiitaからの転載です。

https://qiita.com/hyiromori/items/ba099c401b281d64d1e1

個人でやっている AWS IAM の運用

はじめに

私は個人開発でAWSを使っています。 クラウドサービスが出たおかげで、自宅サーバーやVPSを借りたりしなくても、手軽に色々なものが安価に試せるようになり、非常に便利になりました。 その反面、アカウントを乗っ取られた場合、高額な請求がくる危険性があります。 「AWS アカウント 乗っ取り」とかで調べれば事例がたくさん出てきます。

心配性な私は、なるべく危険を排除して、セキュアにIAMを運用しようと努力しています。 その内容をまとめて見ようと思いこの記事を書きました。

こういう風にしたらよりセキュアになるよ、とか、ここはこういった危険性があるかも、という点があれば、優しくコメントで指摘いただけると嬉しいです。

IAMがよく分からん、という方は以下の記事などを読まれると良いかと思います。

前提

  • 個人レベルでの管理の話です。
  • IAMのみを対象にしています。IAM以外のサービスを使ったセキュリティ(例: GuardDutyなど)や、AWS上に構築したサービスのセキュリティは、対象外とします。
  • macOS での実行を前提にしています。
  • 私はフロントエンドエンジニアをメインに仕事してます。

使用するツール

AWSマネジメントコンソール

AWSを使っているなら知らない人はいないと思いますが、AWSをブラウザ上から色々操作できるツールです。

aws-vault

AWSのアクセスキーをセキュアに管理し、便利に扱う機能があります。 macOSならHomebrewで簡単にインストールできます。 以下のコマンドでインストールできるはずです。

# Homebrewのインストール
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# aws-vaultのインストール
$ brew cask install aws-vault

# インストールされたかの確認
$ aws-vault --version
v5.1.2

IAMベストプラクティス

AWSの公式ドキュメントにある、IAMでやっておくべき推奨事項です。 これを守ればひとまずOKという感じです。 この記事は、このIAMベストプラクティスを踏まえた上で、どう運用するか、という観点で書いています。 読んだことがない方は、こちらの記事を読む前にぜひ一読ください。

ここから具体的な運用についての説明します。

ルートユーザーの保護

ルートユーザーは、アカウント内のリソースすべてにフルアクセスでき、非常に強い権限を持つ上、何も制限をかけることができないので、厳重に保護します。

ルートユーザーは、ミスなどで管理用のIAMユーザーが使用できなくなった場合などに使用する最終手段と私は位置づけおり、ほとんど使うことはありません。

強固なパスワードを使用する

言うまでもないことですが、他では使用していない、できる限りランダムな長い文字列でパスワードを設定します。

MFAを有効にする

こちらも当然ではありますが、多要素認証(MFA)を有効にして、よりルートアカウントをセキュアにしてください。

AWSマネジメントコンソールのIAMのトップ画面にも有効になっているかどうかがいつも表示されてます。 f:id:hyirm:20200326085833p:plain

アクセスキーは作らない

非常に強い権限を持つルートユーザーのアクセスキーは作りません。 ないものは流出もしないので安全です。

必要に応じて最小権限を持つIAMユーザーを作り、アクセスキーを発行します。

IAMユーザーの作成

使用する単位ごとにIAMユーザーを作成

私の場合は、使用する端末ごとにIAMユーザーを作成しています。 (個人の運用なので他の人はいませんが、組織なら当然各人にIAMユーザーを作りましょう)

また、CIについてもリポジトリごとにユーザーを作成しています。 ちなみに GitHub Actions を使っています。

IAMユーザーには権限を付与しない

IAMユーザーは個別に権限を 割り当てません。 IAMユーザーは、後述のIAMグループに所属させるためです。 IAMベストプラクティスにもありますが、グループの方が権限の管理が容易ですし、個別に権限を付与するのは抜け漏れが発生しやすいです。

IAMユーザーのパスワードは作成しない

IAMユーザーはパスワードを作成作成しないようにします。 ないものは流出もしないので安全です。

f:id:hyirm:20200326085837p:plain

パスワードがないとAWSマネジメントコンソール使えないじゃん、と思うかもしれませんが、STSの機能を使ってアクセスキーだけでAWSコンソールにアクセスすることが可能です。 詳細な仕組みまでは知らないのですが、aws-vault を使うと容易に実行できます。後述します。

IAMグループの作成とIAMユーザーの追加

IAMグループの作成

必要なグループを定義して、そこにIAMユーザーを所属させます。 私の場合は、開発者グループとCI用グループを作成しています。

開発者グループには、自身のIAMユーザーに対して、情報を閲覧する権限と、アクセスキーをローテーション(作成/削除)する権限しか付与していません。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:GetUser"
            ],
            "Resource": [
                "arn:aws:iam::123456789012:user/${aws:username}"
            ]
        }
    ]
}

ほとんど何もできないので、万一アクセスキーが流出したとしても安心感があります。 こんな権限じゃ何にも使えないじゃん、と思うかもしれませんが、IAMロールにAssumeRoleをすることで、その権限を実行することができるようになります。詳しくは後述します。

CI用グループは、個別のケースでCIが使う権限を必要最小限にとどめて設定します。 私の場合は殆ど同じような用途で、権限も似ているので、1つのグループにしていますが、色々な用途がある場合は、用途に応じてCIも複数のグループにしたほうが良いかもしれません。 この辺はケースバイケースだと思います。

IAMロールの作成

場面に応じて必要な権限を持つIAMロールを作成

私の場合は、普段使用する「閲覧権限+S3へのアップロードなど」の権限と、AdministratorAccessを付与した管理者権限の2つを作っています。

f:id:hyirm:20200326085844p:plain (管理者権限を持つIAMロールの例)

管理者権限だと最小限じゃないので、個人的には理想と違うんですが、ちょっと新しいことを試そうとしたりするたびに、いちいち権限を調整しないといけないのは実用面で辛いので、現実解として管理者権限を持つユーザーは必要かな、と思っています。 そもそも個人のAWSアカウントで色々なサービスを試してみたい、ということで使っているので、それを阻害するのは避けたいです。

ただし、いつでも管理者権限を使うのではなく、デプロイ時などの特定の場合のみに使用し、普段は権限を制限しているロールで作業するように、私の中のルールで使い分けています。

信頼関係の設定

AssumeRoleを行うための設定を行います。 AssumeRoleはこのケースの場合、許可されたIAMユーザーがIAMロールの権限を一時的に使用することができるようになる、というイメージで一旦理解してもらえると良いかと思います。

詳しくは、以下の記事が参考になります。 IAMロール徹底理解 〜 AssumeRoleの正体 | Developers.IO

指定した状況だと、こういう表示になります。 この場合 homework というユーザーがAssumeRoleを許可されています。

f:id:hyirm:20200326085840p:plain

JSONの指定はこんな感じです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:user/work",
          "arn:aws:iam::123456789012:user/home"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ちなみに、万一AssumeRoleで取得したアクセスキーが流出したとしても、有効期限付きなので少しだけ安心感があります。

aws-vault

このツールを使うことでセキュアに色々なことができるようになります。

こちらの記事が詳細に書かれているので、正直こちらの記事を読めばだいたい分かると思います。ぜひ読んでみてください。 aws-vault でアクセスキーを安全に - Septeni Engineer's Blog

以下、自分が使っている範囲で解説します。

環境変数の設定

そのままでも使えますが、私が設定している環境変数を紹介します。

# ログインKeyChainを使用するように変更
# パスワードを求められる頻度が格段に減る
# (これを設定しない場合、15分経過するとサイドパスワードを求められる)
export AWS_VAULT_KEYCHAIN_NAME="login"

# AssumeRoleを1時間まで可能にする(1時間が最大、デフォルト15分)
export AWS_ASSUME_ROLE_TTL="1h"

リポジトリのドキュメントに他の環境変数も書かれています。

設定

初回はアクセスキーを設定する必要があるので、AWSマネジメントコンソールで対象のIAMユーザーのアクセスキーを発行します。

f:id:hyirm:20200326085851p:plain

続いて以下のコマンドでアクセスキーを設定します。 myprofile はプロファイル名で任意の名前です。わかりやすい名前にしましょう。

$ aws-vault add myprofile
Enter Access Key ID: AKI******************
Enter Secret Access Key: XA1kev******************
Added credentials to profile "myprofile" in vault

これで、アクセスキーを保存できました。 aws-vaultはmacOSの場合はKeyChainに保存されます。 平文でファイルに保存するよりも安心感がありますね。

アクセスキーのローテーション

IAMベストプラクティスでも「認証情報を定期的にローテーションする」と書かれている通り、アクセスキーは頻繁に更新することをおすすめします。

とは言え普通にやるのは面倒なのでなかなかやりませんが、aws-vault ならコマンド一発でローテーションができます!

$ aws-vault rotate -n myprofile
Rotating credentials stored for profile 'myprofile' using master credentials (takes 10-20 seconds)
Creating a new access key
Created new access key ****************B3K5
Deleting old access key ****************A53D
Deleted old access key ****************A53D
Finished rotating access key

これだけで、アクセスキーをローテーションすることができました! 内部では、アクセスキーを新しく発行して、古いキーを削除しているだけですね。

IAMユーザーは、制約としてアクセスキーは2つまでしか同時に発行できません。 なので、アクセスキーを2つ発行している場合はエラーになるので、どちらかを消しましょう。 上限が2つなのは、このようにローテーションするためのものだと思われます。

余談:昔は -n (--no-session) をつけなくても動作したんですが v5.1.2 で実行するとエラーが出るんですよね。Issuev5.1.2 では再現しなくなってクローズされた、とあるんですが、私の環境では再現しました。オプション一つつければ解決するんで、大きな問題ではないですが。

セッショントークンを含んだ一時的なアクセスキーの取得

$ aws-vault exec myprofile -- env | grep "AWS_"
AWS_ACCESS_KEY_ID=ASIAxxxxxxxxxxxxCUVY
AWS_SECRET_ACCESS_KEY=SBpcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxavRg
AWS_SESSION_TOKEN=FwoGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkwpQF8=

aws-vault exec <profile_name> -- <コマンド> で実行すると、AWSの実行に必要な認証情報が環境変数に設定された状態でコマンドが実行できます。 このアクセスキーは有効期限があるので、少しだけ安心感があります。

AssumeRoleの設定

IAMロールに対してAssumeRoleする設定を行います。 ~/.aws/config に対して以下のように記述するとaws-vaultが自動的にAssumeRoleしてくれるようになります。

[profile admin]
source_profile=myprofile
role_arn=arn:aws:iam::123456789012:role/AdminRole

source_profile はAssumeRole対象のプロファイル名(この例だと myprofile)を指定し role_arn はAssumeRoleしたいIAMロールの ARN を指定します。 実行時は以下のように実行します。

$ aws-vault exec admin -- <コマンド>

これで、AdminRoleに設定されている権限でコマンドが実行できるようになります。

ちなみに、MFAの設定もできます。 自分も設定してみたのですが、個人で使っている分にはリスクより手間のほうが大きいと感じているので今は使っていません。 設定されたい方は公式ドキュメントのこの辺りを参考にされると良いかと思います。

なお、AssumeRoleの設定は、アクセスキーと一緒に漏れるとIAMロールの権限内で諸々実行可能になってしまうので、なるべく流出しないようにしたほうが良いと思います。 私はAWSアカウントもなるべく漏れないように気を使い、ロール名も推測できないように実際は乱数を付与して運用しています。

AWSマネジメントコンソールへのログイン

CLIからAWSマネジメントコンソールにログインできます。

$ aws-vault login myprofile
# ブラウザでAWSマネジメントコンソールが開きます

$ aws-vault login admin
# IAMロールの権限でAWSマネジメントコンソールが開くことも可能です

いちいちパスワードを打つ必要がないので便利です!

ざっくりまとめ

  • ルートユーザーはなるべくセキュリティを強固にして使わない
  • IAMユーザーはパスワードがないので、そもそも流出しない
  • aws-vaultを使用するとアクセスキーはKeyChainにあるので容易には盗まれない
  • IAMユーザーのアクセスキーは流出しても権限がほとんどない
  • aws-vaultで実行すると、通常は有効期限付きのアクセスキーで実行される
  • 万一IAMユーザーのアクセスキーが流出しても、AssumeRoleの情報が分からない限り何もできない

おわりに

セキュリティに終わりはないので、ここに書いてある内容を実施しても100%安全と言うわけではないですが、私は大分安心してAWSが使えるようになりました。 アクセスキーはAWSを使う上で重要になってくるので、なるべくセキュアに扱いたいものです。

今回は対象外としましたが、AWSの他のサービス(GuardDutyやConfigなど)も併用するとよりセキュアになるので、設定することをおすすめします。 Developers.IOはよくお世話になっています。

【初心者向け】AWSの脅威検知サービスAmazon GuardDutyのよく分かる解説と情報まとめ | Developers.IO AWS Configはとりあえず有効にしよう | Developers.IO

冒頭にも書きましたが、こういう風にしたらよりセキュアになるよ、とか、ここはこういった危険性があるかも、という点があれば、優しくコメントで指摘いただけると嬉しいです。

※ Qiitaからの転載です。

https://qiita.com/hyiromori/items/668c3fbe1312b8909264

CSSだけでテーブルの縦横2列を固定してスクロールできるようにする

はじめに

タイトルのような、とても大変な要件のテーブルを作って欲しいという要望があったので、その際に試行錯誤した結果を記録しておいたエントリです。

サンプル

CodePenで作ったサンプルです。

See the Pen ScrollTable with fixed 2rows & 2columns header. by hyiromori (@hyiromori) on CodePen.

コードの解説

このコードではposition: stickyを使用することで、テーブルの行、列を固定しています。

position: stickytop right bottom left と組み合わせて使うことで position: relativeposition: absoluteを組み合わせたような動きが可能になる指定です。

Safari ではposition: -webkit-sticky;のようにベンダープレフィックスをつけないと動作しませんでした。

詳細はMDNの解説をご覧ください。

position: sticky の対応状況

Can I Useによれば、モダンブラウザは対応済みです。 ちなみにChromeなどは

Supported on th elements, but not thead or tr

とある通りthead trにバグがあるようです。 このサンプルはthead trに指定していないので、対応ブラウザなら正常に動作するはずです。

幅と高さの制約

position: sticky を使用するため、一部のセルは幅または高さを固定する必要があります。 今回のサンプルは、縦横それぞれ2列を固定するため、以下を固定しなければなりません。

  • 1行目の高さ(2行目のtopを指定しないと固定できないため)
  • 1列目の幅(2列目のleftを指定しないと固定できないため)

実際に使用する場合は、これらのセルを指定した幅と高さで必ず収まるように要素を配置しないといけません。

表示上の制約

テーブルの親要素の幅が十分に広い場合、右側に余白ができてしまう場合があります。 これは table {width: 100%} を指定しても解消できませんでした。

WindowのResizeイベントMutationObserver を使って、 ある程度の幅以下になったら横スクロールを適用するという方法で乗り切りました。

ResizeObserverも使えますが、まだまだ対応ブラウザが少ないです。 対応ブラウザが増えたらこちらも使えるかもしれません。

WebRTC の資料リンク集

WebRTC を調査していた際に集めたリンク集です。

RFC

ミドルウェア

テストツール

Voluntasさん

時雨堂代表取締役社長さん。

日本語の情報はかなり少ない中で、かなり技術的な話がわかりやすく書かれています。

SkyWayの中の人

こちらも、貴重な日本語情報です。

その他

今更ながら HTTP/2 について調べてまとめてみた

この記事の目的

今更ながら HTTP/2 がどのようなものかを調べたくなったので、その結果をまとめた記事になります。 あくまで概要をまとめたもので、今はたくさんの良記事があるので、詳細が知りたい場合は最後の参考文献のリンク先を見ると参考になると思います。

HTTP/2 の特徴

  • ストリームという概念を導入したことで HTTP/1.1 に比べて効率的に通信できます
  • ヘッダー圧縮を行うことで HTTP/1.1 より通信量を減らすことができます
  • サーバープッシュによりリクエストされる前にサーバーからリソースを送信することで HTTP/1.1 よりラウンドトリップ回数を減らすことができます
  • HTTP/1.1 と互換性があります
  • 事実上 TLS による暗号化が必須になります
  • モダンブラウザは対応済です (最新の対応状況は Can I Use で確認してください)

ストリームとは?

HTTP/1.1 の欠点

HTTP/1.1 では、1回目のリクエスト→1回目のレスポンス→2回目のリクエスト→・・・というように、一度リクエストをするとそのレスポンスを受け取ってから次のリクエストを行う必要があります。 大量の画像やファイルで構成されているページを表示する際には、この制約が大きなネックになります。そのため、モダンブラウザでは複数のコネクションを同時に使用することで高速化を図っているそうです。 また、HTTP/1.1 では HTTP パイプラインという高速化手法もありますが、問題があることから、ほとんどのブラウザでは既定で無効になっています。

ストリームを導入することでどう変わるか?

ストリームとは、1つのコネクションの中に独立した複数の仮想的なコネクションのようなものがあり、リクエストとレスポンスを並列で行えるようになるため、1つのコネクションで効率的に通信が行えるようになります。

ヘッダー圧縮とは?

HTTP/1.1 は数百バイト〜数KBあるヘッダーを非圧縮かつ全てのヘッダーを毎回送受信する必要があります。 HTTP/2 では HPACK という圧縮方式を使用し、データ自体を圧縮するとともに、ヘッダーのキャッシュを行うことで差分のみを送受信することが可能になり、ヘッダーを効率よくやり取りできます。

サーバープッシュとは?

HTTP/1.1 では、通常最初に HTML ファイルを受け取ってから、再度描画に必要なリソースをリクエストする、という形になっています。 HTTP/2 では、リクエストに対し(クライアントからのリクエスト無しに)予めサーバーから必要と思われるリソースを送信することが可能になっています。 これにより、ラウンドトリップ回数を減らし、リソースの読み込みまでの時間を短縮することができます。

HTTP/1.1 との互換性

HTTP/2 通信を開始する際は、最初に従来どおりの HTTP リクエストの中に、以下のヘッダー情報を加えて送信し、サーバーから 101 Switching Protocols のレスポンスを受け取ってから HTTP/2 の通信を開始することで、互換性を保っています。

  • Connection: Upgrade, HTTP2-Settings
  • Upgrade: h2c

HTTP/2 を使うメリット

HTTP/2 はここまでの説明の通り、様々な手法で効率よく通信を行えるようになるため、 HTTP/1.1 よりページの読み込み時間が短縮されることが、最大のメリットだと思います。 また HTTP/1.1 との互換性があるため、HTTP/2 非対応のブラウザであってもアクセス可能であるため、導入が容易であることもメリットであると思います。

HTTP/2 を使うデメリット

全てのサイトで高速化されるわけではないことだと思います。例えば、もともと必要なソースが少なく、リクエスト数が少ない場合はあまり恩恵が受けられないと思います。 ただ、遅くなるわけではないので、デメリットという程でもないかと思います。 あとは HTTP/2 に対応する作業コストといったところかと思いますので、実質デメリットはないかな、と思いました。

調べてみた感想

HTTP というプロトコルはステートレスでシンプルなプロトコルが最大の特徴だと個人的には思っているのですが、HTTP/2 は結構複雑だな、という印象です。ヘッダーの圧縮とか、ステートレスな点もありますし。 ただそれも、HTTP が世界で圧倒的に普及した結果、僅かな高速化でも大きな影響があるため、あらゆる手法を取り入れていこうとした結果なのだろうな、とも思います。 デメリットもほぼないと言っても良さそうなので、利用できる時は積極的に使っていくべき技術だと感じました。

参考文献