2022年9月24日(土)~25日(日)に「PHPカンファレンス2022」が大田区産業プラザにて開催されました。GMOインターネットグループはスペシャルスポンサーとして協賛・登壇しました!今回は、スポンサーセッション「17年続くWebサービスを改善する ~新卒2年目からみるカラーミーショップ~」の書き起こし記事となります。ぜひご覧ください。イベント告知:https://developers.gmo.jp/23482/
登壇者(敬称略)
GMOペパボ株式会社 EC事業部ECグループCCXチーム中山 慶祐(やんまー)GMOペパボ株式会社 技術部プラットフォームグループ新宮 隆太(ほみるん)
冒頭
やんまー本日は2人で発表させていただきます。まず、私がGMOペパボ株式会社の中山慶祐と申します。社内では"やんまー"と呼ばれております。
GMOペパボ株式会社の新宮隆太と申します。社内で"ほみるん"と呼ばれております。どうぞよろしくお願いいたします。ほみるん
やんまー本日は、前半と後半の2つに分けて、2つのお話をさせていただきます。前半は、私から「切り取り方を工夫してWebアプリケーションを漸進的に改善する」について30分弱ほどお話しさせていただきます。
後半は、私から「カラーミーショップの改善におけるSRE活動について」を30分お話しさせていただきます。ほみるん
カラーミーショップについて
(以下、やんまーより)発表の前に、タイトルにありましたカラーミーショップについてご説明させてください。
カラーミーショップは、弊社GMOペパボ株式会社が運営するネットショップ作成サービスです。無料で始められ、ECサイトの流通規模が大きくなっても使い続けられるECプラットフォームとなっています。2005年にサービスを開始し、今年で18年目になります。昨年末時点で約45,000ショップのお客様にお使いいただき、年間の流通総額は2,070億円となっております。
このカラーミーショップは、主に2つの開発組織に属する複数のチームで開発運用しております。1つはカラーミーショップを直接運営するEC事業部に所属する複数の開発チームです。私はこちらに所属しております。もう1つはGMOペパボ株式会社の全社横断組織である技術部に属するチームです。ほみるんは、この中のインフラに専門性を持ったサイトリライアビリティエンジニアが所属するチームに属しております。また、システム構成はデータベースを中心とした複数のサブシステムで構成されています。これら全体のWebアプリケーション群からなるECプラットフォームがカラーミーショップです。PHPで開発されているサブシステムも多数ありまして、私も普段PHPを書いて開発しております。この後の発表でカラーミーショップの具体的なシステムの問題や、課題解決を紹介させていただくので、カラーミーショップの前提について少しお話しさせていただきました。
このようなバックグラウンドで今日はお話を進めさせていただきます。どうぞよろしくお願いいたします。
前置きは以上といたしまして、本日の前半のトピックにまいります。
【前半】「切り取り方を工夫してアプリケーションを漸進的に改善する」
https://speakerdeck.com/yammerjp/incremental-improvement-by-devising-application-change-boundaries
まず、漸進的とは何か、なぜ漸進的なのかについて説明します。
そして、そのあと漸進的な改善に必要なアプリケーションの一部を切り取る工夫について、2つの事例を示します。発表の内容が何か皆様のお役に立てれば幸いに思っております。
ここで改めて自己紹介をさせていただきます。
私は中山慶祐と申します。GMOペパボ株式会社のカラーミーショップの開発をしているWebアプリケーションエンジニアです。弊社に入社したのは昨年の4月で、研修のあとカラーミーショップの配属になり、今日でちょうど1年1ヶ月経ちます。このような物理の会場での登壇は実は初めてでして、ちょっと緊張してさっきもあたふたしてしまったのですけれども、ここからは堂々と進めさせていただければなというふうに思っております。
GMOペパボ株式会社では、お互いをあだ名で呼び合う文化があり、私は”やんまー”と呼ばれています。またインターネット上では「@yammerjp」というIDで活動しております。趣味はdotfilesの管理で、設定ファイルを日々コツコツ管理することをしながら毎日を過ごしています。
ということで発表に入らせていただきます。
なぜ漸進的なのか
今日の私の前半のタイトルは、「切り取り方を工夫してアプリケーションを漸進的に改善する」でした。
ところでこの漸進的という言葉は何を指す言葉でしょうか?
辞書によると、「目的、理想などを急激ではなく、順を追ってだんだんと実現しようとする傾向にあること」とあります。
「順を追って」「だんだんと」改善する、それが漸進的な改善です。
ではなぜ漸進的なのでしょうか?これを考えるために少し戻ってみます。
今日はタイトルがもう1つありまして、「新卒2年目からみるカラーミーショップ」となっていました。ということで新卒で配属された頃のことを思い出しています。
今から約1年前、カラーミーショップに配属された当初のことです。
私が感じていたこととしては、「でかい」ということでした。
カラーミーショップは冒頭で示しましたように多数のサブシステムで構成されており、コードはそれぞれのリポジトリで管理されています。でかい、すなわち大きいというのは、コードベースが大きいという意味です。これはカラーミーショップが17年開発運用の続くECプラットフォームであるというだけでなく、私が新卒で入ったので、他のシステムを知らなかったという側面ももちろんあると思います。
複数のサブシステムが協調して動作しており、アプリケーションの全容をすぐに把握するのは難しい…と、配属直後は想像していました。さらに、開発の際に変更を加えるのは大変ではないだろうか、というふうにも思っていました。確かに大きなコードベースに対して大きな変更を加えることは影響範囲も大きくもちろん大変でしょう。これはカラーミーショップに限らずどんなアプリケーションでも当てはまることだと思います。しかし一方で、多くの場合は一瞬ですべてを作り替えるなどということはありません。すべてを変更するのではなく、改修に伴う影響範囲を明らかにして、必要な一部分だけを変更することになります。
そうです。一度に変更するのは一部分だけです。
もし、複数の部分を変えたいならば、一度に一部分のみを変更することを繰り返すことになります。一度に加える変更が大き過ぎれば、影響範囲が大きくなり、リリースに伴う障害発生のリスクも高まります。特に、運用年数が長く、利用者が多いサービスでは、これは顕著でしょう。リスクを避けるには、大きな変更をするにしても、小さな変更の積み重ねになるでしょう。
このような積み重ねは、「順を追って」「だんだんと」変化するものになります。「順を追って」「だんだんと」。これはつまり漸進的な改善です。漸進的に進めることで、影響範囲をコントロールしながら改善を進めることが可能になります。私が一番最初に感じた「でかい」という感想は、ある側面では正しいのですが、一方で開発を進める時にはそのでかいアプリケーションの一部をいかにうまく切り取るかが大事になってくると考えます。実際私も今日までの1年1ヶ月で一部を切り取ることを繰り返してきました。合計200以上のプルリクエストを作ってマージすることになりましたが、これは私に限らずどのエンジニアも一部を切り取って改善を続けています。
というわけで、今日は漸進的な改善についてお話しさせていただきたいと思います。
先ほど、一部を切り取るという風に話しましたけれども、ではこの一部というのはどのようにして決めるのでしょうか?これは開発者が「今回はここを一部とする」と範囲を決めることになります。その切り取り方が大きくなりすぎないよう、また冗長にならないようアプリケーションの一部をうまく切り取るための工夫がカラーミーショップでは実装され、利用されています。
ここではそのアプリケーションの一部を切り取る工夫を2つ紹介させていただきます。
一部を切り取る工夫:モダンWebフロントエンド開発環境の漸進的な導入
事例の1つ目は、「モダンWebフロントエンド環境の漸進的な導入」です。
カラーミーショップは複数のサブシステムからなりますが、そのうち管理画面サブシステムのWebフロントエンド開発環境に課題を抱えていました。状態を変化させるための手続き的なUIが複雑化し、メンテナンスコストが肥大化すること。HTML・CSS・JavaScriptが画面ごとにバラバラに配置されてそれぞれ記述が独自の基準でされているので管理がしづらいということ。また、コードベースが大きく一括でこれらの環境で手を加えるのが難しいこと、などです。
これらの課題に対して宣言的なUIで記述できるようにしたい、もしくは統一的な記述が期待できるフレームワークに則りたい、もしくは大きなコードベースに対しても影響範囲を限定できるよう、漸進的に導入したいといった要求がありました。合わせて、新しい技術の導入にあたっては、開発者に使いやすいインターフェースが求められていました。これは一部の限られた人間のみが開発するわけではないからです。複数のサブシステムの中でも管理画面サブシステムは事業部内の多くのエンジニアが変更を加えることのある場所であり、デザイナーによるUIの開発も一般的に行われています。ここに示した4つの要求-宣言的なUI、フレームワークに則って統一された記述、漸進的な導入、開発者が使いやすいインタフェース、これらすべての要求を満たす方法としてVue.jsとCustom Elementsを用いた方式がとられることになりました。簡単に導入した技術要素について説明させていただきます。
Vue.jsは宣言的なUI記述が可能なJavaScriptフレームワークとして広く知られているものと思います。カラーミーショップにおいても複数のサブシステムで利用されており、事業部内ですでに広く浸透していたことから採用されました。
もうひとつはCustom Elementsです。Custom ElementsはHTMLにおいて独自の要素を定義できる仕様のことです。JavaScriptを用いて、その独自の要素に対する振る舞いを実装することになります。
例えば、あなたが<H1>要素の代わりに<my-element>要素を用意したい、というふうに思ったとしましょう。この時、まずJavaScriptで<my-element>要素を定義し、独自の要素とその振る舞いを定めます。続いて、HTMLのコード内に<my-element>要素を記述し、これを描画します。このような手順を踏むことで、独自の要素を用意できました。
このような前提のうえで、カラーミーショップではVue.jsのコンポーネントをCustom Elementsとして利用できるよう、ビルドする方式がとられました。Vue CLIのWeb Componentモードというものを用いると、Vue.jsのコンポーネントそれぞれをCustom Elementsとして利用できるようにビルドすることが可能です。
このVue CLIのWeb Componentモードについて少しご説明いたします。
Vue CLIのデフォルトのビルドターゲットである Appモードというものは、Vue.jsの単一の<div>要素にVue.jsの親コンポーネントをマウントするような index.htmlが一緒に出力されます。スライドの左のように、画面全体であったりとか、場合によっては画面の一部分がVue.jsで描画されるようになるということです。
一方でWeb ComponentモードではVue.jsのコンポーネントごとにCustom Elementsが定義され、HTML上に独自のタグを記述して利用することになります。独自のタグが書かれた任意の個数の任意の箇所がVue.jsで描画されるようになるということです。スライドの右に示すように、例えば<my-element-hoge>要素や、<my-element-fuga>要素などのコンポーネントが定義されているとして、これらがHTMLの中の好きな場所に出現させることができるというふうになっています。
このような方式をとることで、当初の要求をすべて満たすことができます。宣言的なUIと、フレームワークに則った記述は、Vue.jsを導入することで実現されました。漸進的な導入と使いやすいインタフェースは、Custom Elementsへのビルドで実現されました。
ここでは後者2つに焦点を当ててみます。
漸進的な導入は、Vue.jsのコンポーネントのマウントする個数や箇所を任意に決められることで柔軟に変えられるという特性をもって実現しています。
例えば、スライドに示したスクリーンショットは管理画面サブシステムのとある2つの画面です。画面に表示された要素の詳細は特に重要ではありません。ここでは赤い部分がVue.jsをCustom Elementsにビルドしたコンポーネントが含まれている箇所というふうに認識していただければよろしいかと思います。どちらの画面も複数の箇所に利用されており、また画面ごとに利用されている範囲が異なるので、これらがコントロールされているというようなことが分かるかと思います。漸進的な導入は、このようにして実現されています。
もうひとつの使いやすいインタフェースについては、独自のタグを記述するのみで実現できることからこれを満たしていると考えます。
画面の開発をする際に、Custom Elementsのビルドされたタグを埋め込むことになります。普段の開発では HTMLのコード内にタグを記述するというようなことは変わりません。例えば、管理画面サブシステムではPHPのあるテンプレートエンジンを用いているので、そのテンプレートファイル内にタグを記述して画面を構成するというような構成は従来と変わっていません。変わるのは、一般的な要素ではなく、独自のタグを記述することです。ここで<my-element>要素を記述しているように、例えば<button>要素ではなく<colorme-shop-xxx-button>要素を記述するといったように、独自のタグを記述するということだけでコンポーネントを埋め込むことになります。このようなコンポーネントは、事前に用意することが必要になる一方で、利用する際はこのタグを記述するだけでリッチなUIを実現できます。
改めて利点を示します。詳細を述べた2点を含め、Custom Elementsをビルドすることは管理画面サブシステムに多くのメリットをもたらしました。宣言的なUI、フレームワークに則って統一された記述、漸進的な導入、開発者が使いやすいインタフェースです。
ここまでのまとめです。モダンWebフロントエンド環境の漸進的な導入としてCustom ElementsとしてビルドできるようにビルドされたVue.jsコンポーネントを用いて既存画面の一部置き換えや新規実装というものを進めています。新たなUIフレームワークを導入しても、画面全体の再実装が必要になることを避け、必要に応じて柔軟に組み合わせることができるようになっています。このような方法を通してWebフロントエンド領域において変更の粒度を小さくし、切り出しやすい一部を柔軟に決めて、漸進的に改善できる方法が提供されています。
ここまでが、Webフロントエンドの領域における漸進的な改善でした。
一部を切り取る工夫:Feature Toggleの活用と管理
PHPカンファレンスですので、バックエンドに関心を強く持たれる方が多いかと思うのでもしかしたら少し退屈だったかもしれませんが、ここからはWebのバックエンド領域も含めたお話になってまいります。
ここからは、先ほどは少し視点を変えて、アプリケーションの一部を切り出す工夫のもう1つを紹介させていただきます。それはFeature Toggleの活用と管理です。
まずはFeature Toggleについてです。
トグルと聞くと、電気のスイッチを想像されるのではないかと思います。ここではFeature Toggleを「特定の機能の有効や無効といった状態を、コード内の条件で切り替える手法」とさせていただきます。実装が存在してもトグルを有効化していないと機能が動作しないように制御することが可能です。
スライドに示したコードは、単純な実装例です。まず、真偽値を持つ変数isEnabledNewFeatureに、falseを代入しています。次の行は同じ変数isEnabledNewFeatureにtrueを代入している行ですが、これはコメントアウトされています。
続いて、isEnabledNewFeatureがtrueならば新しい機能、falseならば既存の機能を実行するというような分岐が記述されています。このようなコードを埋め込むことで、開発を行ったあと機能を無効にしたまま本番環境へリリースできるようになります。
ここでの例は大変原始的で単純な例ですが、もう少し高度な例として、if-elseをこの処理と切り離すために抽象化層を導入したり、設定ファイルに真偽値を分離したり、開発環境でだけ有効になるようにしたりといった仕組みを導入するという実装も考えられます。
いくつかの実装は考えられますが、どの実装もFeature Toggleは開発中の機能を無効化した状態でリリースできるというメリットがあります。機能がユーザーから利用できない状態になるので、全容が完成していなくとも完成した一部分を、レビューを経てリリースできるようになります。これはアプリケーションに対する変更の粒度を小さくし、既存機能への影響がないことが常に確認された状態を維持したまま開発を進められることになります。つまり、その一部を切り取ることができるようになります。
ところで、先ほどのコードにはいくつか課題がありますが、1つにはトグルの変更にデプロイが必須というようなことが挙げられます。
スライドに示したのは、先ほどと同じコード例です。
ここでは、isEnabledNewFeatureにtrueを代入している部分がコメントアウトされていますけれども、この行と上のfalseが代入されている行を編集してレビューしてCIを通してデプロイするといった流れを踏むことになりますけれども、これはどうしても多少の時間がかかってしまいます。
デプロイをせずともトグルを変更できるようにして、リリースやその切り戻しを素早く行いたいといった需要があります。
このような需要への対応として、Feature Toggleの管理を外部化することが挙げられます。トグルの有効もしくは無効といった状態をアプリケーションのコードの外で保持するような手法のことです。例えば、トグルの状態をデータベースに保存しておき、開発者が変更可能にします。また、アプリケーションはトグルの変更を取得して分岐するようにします。
ここでもまた、少しコードを示させていただきます。画面に示した例では、FeatureToggleクラスというものがすでに定義されていて、このFeatureToggleクラスのisEnabledメソッドが外部から状態を取得して戻り値を返しているということを前提にしたコード例です。このisEnabledメソッドの真偽値がtrueならば新しい機能を、falseならば既存の機能を実行するというコード例です。
このような方式をとる時にはこのFeatureToggleクラスのisEnabledメソッドが通信する先として、例えばアプリケーションのデータベースを使ってそこにトグルの情報を入れておく、そのトグルを変更する場合には管理画面を別に用意しておく、というような自作する方法が考えられます。他にはこのようなFeature Toggleの管理を行えるようなサービスというものがあり、これを使うという方法もあります。
このFeature Toggleの管理をするサービスの1つに、Unleashが挙げられます。
カラーミーショップを含むGMOペパボでは、Unleashを利用してFeature Toggleの管理の外部化を実現しています。Unleashはマネージドサービスとして利用することも、自前でホストすることも可能です。スライドに示しているのはUnleashの管理画面のデモページの例です。
このUnleashは、スライドに示している管理画面を含む管理を行うアプリケーションと、もう1つはFeature Toggleの状態を取得するSDKがあり、これらが合わせて提供されています。トグルの状態はUnleashの管理画面から操作可能です。アプリケーションの実装時には、SDKを使い、トグルの状態を取得できるようにしておきます。
なお、SDKにはPHP向けのものもありまして、Composerを用いてPHPアプリケーションに導入することも可能です。
このようなFeature Toggleの管理を外部化することで、デプロイをせずともトグルの変更が可能になります。リリースの時点では管理画面からトグルを変更するだけで済みますし、切り戻しも同様です。これはデプロイとリリースを切り離すということになります。これはFeature Toggleの管理を外部化することのメリットとなります。もう1つ大きなメリットとして、Unleashに付属している便利な機能として、条件を満たした一部の場合のみトグルを有効化することができます。例えば、ユーザーのアカウントIDを渡して本番環境で特定のアカウントのみをトグル有効にしたり、リクエストごとやセッションごと、アカウントごとに任意の割合で有効にしたりするということです。一部のユーザーのみのトグルを変更するというようなことは、新しい機能を開発者や社内のユーザーのみが利用できるようになるということです。また、一定の割合でリリースできるようになるということは、すなわちカナリアリリースとしてアプリケーションのメトリクスや利用者の反応を見ながら提供の割合をコントロールするようなことができるようになります。つまり、アプリケーションの実装ではなく、ここではリリースの範囲を一部に切り取ることが可能になります。これは漸進的なリリースといえると思います。
ここまでのまとめです。
ここまではFeature Toggleについて紹介しました。Feature Toggleを用いてユーザーが利用できる機能の全容でなくとも完成した一部分のみをリリースすることができるようになります。また、Feature Toggleの管理を外部化することでより柔軟な運用を可能とします。これらは変更の粒度を小さくし、アプリケーションの実装やリリースの範囲を一部に切り出すということを実現しています。
以上、アプリケーションの一部を切り取る工夫として2つの事例を紹介させていただきました。1つ目はモダンWebフロントエンド環境の漸進的な導入、2つ目はFeature Toggleの活用と管理でした。
おわりに
最後に、ここまでの発表を振り返ることで前半の締めとしたいと思います。
本発表では、カラーミーショップを含むWebアプリケーションの開発が、一度に一部分のみを変更するということを繰り返す漸進的な改善によってなされていることを説明しました。また、アプリケーションの一部を切り取る工夫として、その範囲を柔軟に決めやすくなるような取り組みを2つ紹介しました。
これからも、切り取り方を工夫しながらアプリケーションの漸進的な改善を続けていきたいと思っております。
以上で前半の発表を終わります。ご清聴ありがとうございました。
後半
https://developers.gmo.jp/24747/
アーカイブ映像
https://youtu.be/lz4IVcds9Fo
PHP Conference Japan 2022: 17年続くWebサービ… / やんまー、ほみるん | GMOペパボ - YouTube