イベント
イベントを探す
本日開催のイベント
明日開催のイベント
ランキング
カレンダー
マガジン
マガジンを読む
マガジン
技術ブログ
書籍
動画
動画を見る
グループ
グループを探す
グループを作る
イベントを作成・管理
学生の方はこちら
ログイン
|
新規会員登録
TOP
グループ
株式会社メドレー
ブログ
トップ
イベント
ブログ
株式会社メドレー の技術ブログ
全1359件
2024/09/10
<![CDATA[ iOSDC Japan 2024に プラチナスポンサーとして協賛しました! ]]>
こんにちは。人材プラットフォーム本部で EngineeringManager をしている倉林です。2024 年 4 月にメドレーにジョインし、少しづつエンジニアの組織作りに携わり始めています。 メドレーは 2024/8/22 〜 8/24 の 3 日間に早稲田大学西早稲田キャンパスにて開催された「 iOSDC Japan 2024 」にプラチナスポンサーとして協賛させていただきました。 iOSDC は、iOS 関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスで、各所からアプリエンジニアが集う大規模なイベントです。毎年、多くのアプリエンジニアが集まり、最新の技術やトレンドを共有する活気あるイベントとして知られています。 2016 年から開催され、今年で 9 回目。メドレーはなんと今年で 8 年連続のスポンサー参加となり、今年も採用担当・広報・ネイティブアプリエンジニアが参加し、多くのエンジニアや関係者の方々との交流を深めることができました。 会場の様子 会場は早稲田大学西早稲田キャンパス。今年はオンライン・オフラインのハイブリッド開催で、オフライン 1100 名、オンライン 400 名の合計約 1500 名以上の参加者で賑わいました。 登壇や LT などもたくさんあり、通常セッションが 50 セッション、LT がルーキーズ LT 含めて 30 本以上で内容も幅広く、様々なインプットを得ることができました。 まさに「アプリエンジニアのお祭り」という雰囲気でした! 会場は各ブースをスタンプラリー方式で巡る形式だったこともあり、どのブース・空間も終始賑やかで、スポンサー・一般参加者・エンジニア・人事関係なく交流が行われていました。大学での開催ということもあるのか学生も多く参加しているのが印象的でした。 スポンサーブーススタンプラリー、フリードリンクや軽食、お昼時にはキッチンカー、朝ドーナツや夕方からはアルコール類の提供、ネイルやボディペイントなどのアートブースなど楽しむための様々な工夫がされていて、まさにコミュニケーションの場となる空間作りがされたカンファレンスだったと感じました。運営の方々の準備と当日のスムーズな対応に感謝です。 (スタンプを 1 列揃えて BINGO するとたこ焼き、2 列揃えるとクレープ、全部集めると iOSDC ノベルティと交換) メドレーブースの様子 メドレーブースでは、メドレーが展開するアプリの紹介と、アンケートパネルを用いて参加者の方々に医療体験に関するお悩みを伺いました。 特に課題として多かったは以下の 3 つ 待ち時間が長い 圧倒的一位でした、特に子供がいる家庭は子供を連れて薬局へも行かなくてはいけないのが辛い との回答が多数 キャッシュレス決済がしたい 大分増えてはきたけど。。。との声でした! オンラインで予約したい 電話で予約するのが面倒という方が圧倒的に多かった 予約とはちょっと違うけど病院の口コミを見たい という声も多かったです それぞれの課題についてメドレーのプロダクト・サービスを通じて解決できていること・これから解決していくことなどをご紹介させていただきました。 iOS のイベントということもあり、実施に CLINICS アプリ の画面をお見せしながら説明させていただき以下のような感想もいただきました。 オンライン診療が受けれて、薬が Uber Eats で届く。もうそこまで体験が到達しているとな思わなかった 病院検索の UI が体感が早く心地よい・どうやって実装しているのか オンライン診療で話した内容を電子カルテに書き込んだりできないのか?など新しい機能提案 などなど。 メドレーはアプリを展開している印象があまりなかったので、参考になったなどの声も頂きました。 各アプリの技術スタックは以下の画像の通りで、React Native や Flutter などのクロスプラットフォーム技術で開発しているものもあれば Swift, Kotlin などネイティブ言語で開発しているものもあり提供したい価値やアプリ特性によって様々な技術スタックを選定しています。 CLINICS では全画面の実装が SwiftUI 、SPM を用いたマルチモジュール構成だったりと新しい技術を積極的に導入しています。 セッションやブース 個人的に気になったセッション及び、弊社メドレーの吉田による登壇について少し紹介させていただければと思います。 Ditto SDK 紹介: インターネットなしで快適なデータ同期 アプリ内に SDK の処理を入れておくと、P2P で端末同士がローカルでやり取りしてデータを同期できます、というサービスの紹介。 Flutter や RN にも対応していて「ローカルの端末同士で P2P をいい感じにやる部分」と「ローカルのデータを吸い上げて適宜配信する中央サーバー」といった印象で、需要ありそうだと感じました。 Swift 6 の Typed throws と Swift におけるエラーハンドリングの全体像を学ぶ Swift 6 の新機能の 1 つである Typed throws についての紹介。 安易に使うべきではないとしながら、どういう場面では効果的かなど、実践的な内容も聞くことができました。 普段使っている Optional がエラーハンドリングにおいてどの位置づけかを含め、エラーハンドリングの全体像の概観を理解することができました。 座談会 「Strict Concurrency と Swift 6 が開く新時代: 私たちはどう生きるか?」 超満員の人気セッションで、Swift 6 対応の盛り上がりを感じました。 CLINICS アプリでも Swift 6 対応を進めているのですが、どこまでを MainActor のスコープとするか、どのレベルでのリファクタリングを同時にやっていくかが議論になっていたので、大変参考になりました。 座談会という形式も普段のトークとは異なり新鮮でした。 bitkey さんブース:bitlink をさがして! 個人的に一番面白かったのは Bitkey さんのブースです。iBeacon になる自社製品(bitlink)を携帯して歩いている社員の方がいるので、iOS アプリを自作してその人を見つけられれば、景品を渡す、という企画でした。 メドレーメンバーも結構早めにアプリ作って探しましたが、3 番目だったとのこと。残念! Forkwell さんブース 会場で配布していた資料に、イチ推し求人としてメドレーの求人情報を掲載していただいていました!いつもお世話になっております! メドレー登壇 医療アプリ開発における安全性と生産性のバランスについて医療プラットフォーム本部 患者プロダクト開発グループの吉田 ( @shzero5 ) が登壇させていただきました。 医療アプリの開発においては、患者の安全と利便性の向上が最重要課題となります。一方で、医療制度の変更への迅速な対応や新規機能の実装など、高い生産性も求められます。この 2 つの要件は相反するものですが、その両立は避けられない課題だと感じています。 今回の登壇では、メドレーのオンライン診療サービスを含む総合医療アプリ「CLINICS」の開発を通じて、いかにして安全性と生産性の両立に取り組んでいるかをご紹介しました。 診療報酬改定などの制度変更に柔軟に対応できる体制 SPM マルチモジュール、トランクベース開発など生産性向上の工夫 MagicPod を活用した自動テスト環境での効率的な品質確保 法律・ガイドライン・制度対応や社内他部門との連携を含む総合的なアプローチ 医療アプリの開発は技術的側面のみならず、適切な規制対応や組織間調整など様々な課題に直面します。 今回の登壇では、そうした課題への具体的な取り組みをご紹介しつつ、品質と速度の両立に向けた実践的な知見をお話ししました。 質問もいくつかいただきました。 トランクベース開発とのことだが、ブランチ作成からマージまでの間隔は? 大きな機能開発でも、ブランチ作成からコードレビューを通してマージまで、1 日かからない程度の粒度に分割しています MagicPod の導入をチームで進めているが、自動化するテストシナリオの選択基準は? MagicPod で自動化できるテストシナリオは全て自動化しているが、ビデオ通話など、どうしても自動テストしづらい部分は課題として残っています iOS、Android、Web で越境して実装してるとのことだが、コードレビューはどうしているのか 個々で強みのプラットフォームがあるので、知見のある人がレビューすることが多いです 発表後にブースに来ていただいて面白かったとコメント頂いたり、改めて医療領域に興味をもっていただけたりしました。医療 × テクノロジーの最前線で得られた学びを、皆様の開発にも活かしていただければ幸いです。 終わりに メドレーはこれからもアプリを通じて様々な医療体験にインパクト与えるようにプロダクト・サービスを開発していきます。引き続き技術的なチャレンジも行っていきますのでご注目ください! 最後に、改めて iOSDC Japan 2024 の運営の皆様、登壇されたスピーカーの皆様、参加者の皆様、ありがとうございました。来年 10 周年の開催も楽しみにしています! メドレーでは一緒に働く仲間を募集しています。 ぜひこの記事やブースや登壇などで興味を持っていただいた方はご連絡いただければと思います!カジュアル面談など実施可能ですので、お気軽にお問い合わせください! https://www.medley.jp/jobs/ また DroidKaigi 2024 にもスポンサードしてブースなど予定していますので、興味のある方はぜひ会場にて会話させていただけると嬉しいです。
2024/09/10
<![CDATA[ iOSDC Japan 2024に プラチナスポンサーとして協賛しました! ]]>
こんにちは。人材プラットフォーム本部で EngineeringManager をしている倉林です。2024 年 4 月にメドレーにジョインし、少しづつエンジニアの組織作りに携わり始めています。 メドレーは 2024/8/22 〜 8/24 の 3 日間に早稲田大学西早稲田キャンパスにて開催された「 iOSDC Japan 2024 」にプラチナスポンサーとして協賛させていただきました。 iOSDC は、iOS 関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスで、各所からアプリエンジニアが集う大規模なイベントです。毎年、多くのアプリエンジニアが集まり、最新の技術やトレンドを共有する活気あるイベントとして知られています。 2016 年から開催され、今年で 9 回目。メドレーはなんと今年で 8 年連続のスポンサー参加となり、今年も採用担当・広報・ネイティブアプリエンジニアが参加し、多くのエンジニアや関係者の方々との交流を深めることができました。 会場の様子 会場は早稲田大学西早稲田キャンパス。今年はオンライン・オフラインのハイブリッド開催で、オフライン 1100 名、オンライン 400 名の合計約 1500 名以上の参加者で賑わいました。 登壇や LT などもたくさんあり、通常セッションが 50 セッション、LT がルーキーズ LT 含めて 30 本以上で内容も幅広く、様々なインプットを得ることができました。 まさに「アプリエンジニアのお祭り」という雰囲気でした! 会場は各ブースをスタンプラリー方式で巡る形式だったこともあり、どのブース・空間も終始賑やかで、スポンサー・一般参加者・エンジニア・人事関係なく交流が行われていました。大学での開催ということもあるのか学生も多く参加しているのが印象的でした。 スポンサーブーススタンプラリー、フリードリンクや軽食、お昼時にはキッチンカー、朝ドーナツや夕方からはアルコール類の提供、ネイルやボディペイントなどのアートブースなど楽しむための様々な工夫がされていて、まさにコミュニケーションの場となる空間作りがされたカンファレンスだったと感じました。運営の方々の準備と当日のスムーズな対応に感謝です。 (スタンプを 1 列揃えて BINGO するとたこ焼き、2 列揃えるとクレープ、全部集めると iOSDC ノベルティと交換) メドレーブースの様子 メドレーブースでは、メドレーが展開するアプリの紹介と、アンケートパネルを用いて参加者の方々に医療体験に関するお悩みを伺いました。 特に課題として多かったは以下の 3 つ 待ち時間が長い 圧倒的一位でした、特に子供がいる家庭は子供を連れて薬局へも行かなくてはいけないのが辛い との回答が多数 キャッシュレス決済がしたい 大分増えてはきたけど。。。との声でした! オンラインで予約したい 電話で予約するのが面倒という方が圧倒的に多かった 予約とはちょっと違うけど病院の口コミを見たい という声も多かったです それぞれの課題についてメドレーのプロダクト・サービスを通じて解決できていること・これから解決していくことなどをご紹介させていただきました。 iOS のイベントということもあり、実施に CLINICS アプリ の画面をお見せしながら説明させていただき以下のような感想もいただきました。 オンライン診療が受けれて、薬が Uber Eats で届く。もうそこまで体験が到達しているとな思わなかった 病院検索の UI が体感が早く心地よい・どうやって実装しているのか オンライン診療で話した内容を電子カルテに書き込んだりできないのか?など新しい機能提案 などなど。 メドレーはアプリを展開している印象があまりなかったので、参考になったなどの声も頂きました。 各アプリの技術スタックは以下の画像の通りで、React Native や Flutter などのクロスプラットフォーム技術で開発しているものもあれば Swift, Kotlin などネイティブ言語で開発しているものもあり提供したい価値やアプリ特性によって様々な技術スタックを選定しています。 CLINICS では全画面の実装が SwiftUI 、SPM を用いたマルチモジュール構成だったりと新しい技術を積極的に導入しています。 セッションやブース 個人的に気になったセッション及び、弊社メドレーの吉田による登壇について少し紹介させていただければと思います。 Ditto SDK 紹介: インターネットなしで快適なデータ同期 アプリ内に SDK の処理を入れておくと、P2P で端末同士がローカルでやり取りしてデータを同期できます、というサービスの紹介。 Flutter や RN にも対応していて「ローカルの端末同士で P2P をいい感じにやる部分」と「ローカルのデータを吸い上げて適宜配信する中央サーバー」といった印象で、需要ありそうだと感じました。 Swift 6 の Typed throws と Swift におけるエラーハンドリングの全体像を学ぶ Swift 6 の新機能の 1 つである Typed throws についての紹介。 安易に使うべきではないとしながら、どういう場面では効果的かなど、実践的な内容も聞くことができました。 普段使っている Optional がエラーハンドリングにおいてどの位置づけかを含め、エラーハンドリングの全体像の概観を理解することができました。 座談会 「Strict Concurrency と Swift 6 が開く新時代: 私たちはどう生きるか?」 超満員の人気セッションで、Swift 6 対応の盛り上がりを感じました。 CLINICS アプリでも Swift 6 対応を進めているのですが、どこまでを MainActor のスコープとするか、どのレベルでのリファクタリングを同時にやっていくかが議論になっていたので、大変参考になりました。 座談会という形式も普段のトークとは異なり新鮮でした。 bitkey さんブース:bitlink をさがして! 個人的に一番面白かったのは Bitkey さんのブースです。iBeacon になる自社製品(bitlink)を携帯して歩いている社員の方がいるので、iOS アプリを自作してその人を見つけられれば、景品を渡す、という企画でした。 メドレーメンバーも結構早めにアプリ作って探しましたが、3 番目だったとのこと。残念! Forkwell さんブース 会場で配布していた資料に、イチ推し求人としてメドレーの求人情報を掲載していただいていました!いつもお世話になっております! メドレー登壇 医療アプリ開発における安全性と生産性のバランスについて医療プラットフォーム本部 患者プロダクト開発グループの吉田 ( @shzero5 ) が登壇させていただきました。 医療アプリの開発においては、患者の安全と利便性の向上が最重要課題となります。一方で、医療制度の変更への迅速な対応や新規機能の実装など、高い生産性も求められます。この 2 つの要件は相反するものですが、その両立は避けられない課題だと感じています。 今回の登壇では、メドレーのオンライン診療サービスを含む総合医療アプリ「CLINICS」の開発を通じて、いかにして安全性と生産性の両立に取り組んでいるかをご紹介しました。 診療報酬改定などの制度変更に柔軟に対応できる体制 SPM マルチモジュール、トランクベース開発など生産性向上の工夫 MagicPod を活用した自動テスト環境での効率的な品質確保 法律・ガイドライン・制度対応や社内他部門との連携を含む総合的なアプローチ 医療アプリの開発は技術的側面のみならず、適切な規制対応や組織間調整など様々な課題に直面します。 今回の登壇では、そうした課題への具体的な取り組みをご紹介しつつ、品質と速度の両立に向けた実践的な知見をお話ししました。 質問もいくつかいただきました。 トランクベース開発とのことだが、ブランチ作成からマージまでの間隔は? 大きな機能開発でも、ブランチ作成からコードレビューを通してマージまで、1 日かからない程度の粒度に分割しています MagicPod の導入をチームで進めているが、自動化するテストシナリオの選択基準は? MagicPod で自動化できるテストシナリオは全て自動化しているが、ビデオ通話など、どうしても自動テストしづらい部分は課題として残っています iOS、Android、Web で越境して実装してるとのことだが、コードレビューはどうしているのか 個々で強みのプラットフォームがあるので、知見のある人がレビューすることが多いです 発表後にブースに来ていただいて面白かったとコメント頂いたり、改めて医療領域に興味をもっていただけたりしました。医療 × テクノロジーの最前線で得られた学びを、皆様の開発にも活かしていただければ幸いです。 終わりに メドレーはこれからもアプリを通じて様々な医療体験にインパクト与えるようにプロダクト・サービスを開発していきます。引き続き技術的なチャレンジも行っていきますのでご注目ください! 最後に、改めて iOSDC Japan 2024 の運営の皆様、登壇されたスピーカーの皆様、参加者の皆様、ありがとうございました。来年 10 周年の開催も楽しみにしています! メドレーでは一緒に働く仲間を募集しています。 ぜひこの記事やブースや登壇などで興味を持っていただいた方はご連絡いただければと思います!カジュアル面談など実施可能ですので、お気軽にお問い合わせください! https://www.medley.jp/jobs/ また DroidKaigi 2024 にもスポンサードしてブースなど予定していますので、興味のある方はぜひ会場にて会話させていただけると嬉しいです。
2024/09/10
<![CDATA[ iOSDC Japan 2024に プラチナスポンサーとして協賛しました! ]]>
こんにちは。人材プラットフォーム本部で EngineeringManager をしている倉林です。2024 年 4 月にメドレーにジョインし、少しづつエンジニアの組織作りに携わり始めています。 メドレーは 2024/8/22 〜 8/24 の 3 日間に早稲田大学西早稲田キャンパスにて開催された「 iOSDC Japan 2024 」にプラチナスポンサーとして協賛させていただきました。 iOSDC は、iOS 関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスで、各所からアプリエンジニアが集う大規模なイベントです。毎年、多くのアプリエンジニアが集まり、最新の技術やトレンドを共有する活気あるイベントとして知られています。 2016 年から開催され、今年で 9 回目。メドレーはなんと今年で 8 年連続のスポンサー参加となり、今年も採用担当・広報・ネイティブアプリエンジニアが参加し、多くのエンジニアや関係者の方々との交流を深めることができました。 会場の様子 会場は早稲田大学西早稲田キャンパス。今年はオンライン・オフラインのハイブリッド開催で、オフライン 1100 名、オンライン 400 名の合計約 1500 名以上の参加者で賑わいました。 登壇や LT などもたくさんあり、通常セッションが 50 セッション、LT がルーキーズ LT 含めて 30 本以上で内容も幅広く、様々なインプットを得ることができました。 まさに「アプリエンジニアのお祭り」という雰囲気でした! 会場は各ブースをスタンプラリー方式で巡る形式だったこともあり、どのブース・空間も終始賑やかで、スポンサー・一般参加者・エンジニア・人事関係なく交流が行われていました。大学での開催ということもあるのか学生も多く参加しているのが印象的でした。 スポンサーブーススタンプラリー、フリードリンクや軽食、お昼時にはキッチンカー、朝ドーナツや夕方からはアルコール類の提供、ネイルやボディペイントなどのアートブースなど楽しむための様々な工夫がされていて、まさにコミュニケーションの場となる空間作りがされたカンファレンスだったと感じました。運営の方々の準備と当日のスムーズな対応に感謝です。 (スタンプを 1 列揃えて BINGO するとたこ焼き、2 列揃えるとクレープ、全部集めると iOSDC ノベルティと交換) メドレーブースの様子 メドレーブースでは、メドレーが展開するアプリの紹介と、アンケートパネルを用いて参加者の方々に医療体験に関するお悩みを伺いました。 特に課題として多かったは以下の 3 つ 待ち時間が長い 圧倒的一位でした、特に子供がいる家庭は子供を連れて薬局へも行かなくてはいけないのが辛い との回答が多数 キャッシュレス決済がしたい 大分増えてはきたけど。。。との声でした! オンラインで予約したい 電話で予約するのが面倒という方が圧倒的に多かった 予約とはちょっと違うけど病院の口コミを見たい という声も多かったです それぞれの課題についてメドレーのプロダクト・サービスを通じて解決できていること・これから解決していくことなどをご紹介させていただきました。 iOS のイベントということもあり、実施に CLINICS アプリ の画面をお見せしながら説明させていただき以下のような感想もいただきました。 オンライン診療が受けれて、薬が Uber Eats で届く。もうそこまで体験が到達しているとな思わなかった 病院検索の UI が体感が早く心地よい・どうやって実装しているのか オンライン診療で話した内容を電子カルテに書き込んだりできないのか?など新しい機能提案 などなど。 メドレーはアプリを展開している印象があまりなかったので、参考になったなどの声も頂きました。 各アプリの技術スタックは以下の画像の通りで、React Native や Flutter などのクロスプラットフォーム技術で開発しているものもあれば Swift, Kotlin などネイティブ言語で開発しているものもあり提供したい価値やアプリ特性によって様々な技術スタックを選定しています。 CLINICS では全画面の実装が SwiftUI 、SPM を用いたマルチモジュール構成だったりと新しい技術を積極的に導入しています。 セッションやブース 個人的に気になったセッション及び、弊社メドレーの吉田による登壇について少し紹介させていただければと思います。 Ditto SDK 紹介: インターネットなしで快適なデータ同期 アプリ内に SDK の処理を入れておくと、P2P で端末同士がローカルでやり取りしてデータを同期できます、というサービスの紹介。 Flutter や RN にも対応していて「ローカルの端末同士で P2P をいい感じにやる部分」と「ローカルのデータを吸い上げて適宜配信する中央サーバー」といった印象で、需要ありそうだと感じました。 Swift 6 の Typed throws と Swift におけるエラーハンドリングの全体像を学ぶ Swift 6 の新機能の 1 つである Typed throws についての紹介。 安易に使うべきではないとしながら、どういう場面では効果的かなど、実践的な内容も聞くことができました。 普段使っている Optional がエラーハンドリングにおいてどの位置づけかを含め、エラーハンドリングの全体像の概観を理解することができました。 座談会 「Strict Concurrency と Swift 6 が開く新時代: 私たちはどう生きるか?」 超満員の人気セッションで、Swift 6 対応の盛り上がりを感じました。 CLINICS アプリでも Swift 6 対応を進めているのですが、どこまでを MainActor のスコープとするか、どのレベルでのリファクタリングを同時にやっていくかが議論になっていたので、大変参考になりました。 座談会という形式も普段のトークとは異なり新鮮でした。 bitkey さんブース:bitlink をさがして! 個人的に一番面白かったのは Bitkey さんのブースです。iBeacon になる自社製品(bitlink)を携帯して歩いている社員の方がいるので、iOS アプリを自作してその人を見つけられれば、景品を渡す、という企画でした。 メドレーメンバーも結構早めにアプリ作って探しましたが、3 番目だったとのこと。残念! Forkwell さんブース 会場で配布していた資料に、イチ推し求人としてメドレーの求人情報を掲載していただいていました!いつもお世話になっております! メドレー登壇 医療アプリ開発における安全性と生産性のバランスについて医療プラットフォーム本部 患者プロダクト開発グループの吉田 ( @shzero5 ) が登壇させていただきました。 医療アプリの開発においては、患者の安全と利便性の向上が最重要課題となります。一方で、医療制度の変更への迅速な対応や新規機能の実装など、高い生産性も求められます。この 2 つの要件は相反するものですが、その両立は避けられない課題だと感じています。 今回の登壇では、メドレーのオンライン診療サービスを含む総合医療アプリ「CLINICS」の開発を通じて、いかにして安全性と生産性の両立に取り組んでいるかをご紹介しました。 診療報酬改定などの制度変更に柔軟に対応できる体制 SPM マルチモジュール、トランクベース開発など生産性向上の工夫 MagicPod を活用した自動テスト環境での効率的な品質確保 法律・ガイドライン・制度対応や社内他部門との連携を含む総合的なアプローチ 医療アプリの開発は技術的側面のみならず、適切な規制対応や組織間調整など様々な課題に直面します。 今回の登壇では、そうした課題への具体的な取り組みをご紹介しつつ、品質と速度の両立に向けた実践的な知見をお話ししました。 質問もいくつかいただきました。 トランクベース開発とのことだが、ブランチ作成からマージまでの間隔は? 大きな機能開発でも、ブランチ作成からコードレビューを通してマージまで、1 日かからない程度の粒度に分割しています MagicPod の導入をチームで進めているが、自動化するテストシナリオの選択基準は? MagicPod で自動化できるテストシナリオは全て自動化しているが、ビデオ通話など、どうしても自動テストしづらい部分は課題として残っています iOS、Android、Web で越境して実装してるとのことだが、コードレビューはどうしているのか 個々で強みのプラットフォームがあるので、知見のある人がレビューすることが多いです 発表後にブースに来ていただいて面白かったとコメント頂いたり、改めて医療領域に興味をもっていただけたりしました。医療 × テクノロジーの最前線で得られた学びを、皆様の開発にも活かしていただければ幸いです。 終わりに メドレーはこれからもアプリを通じて様々な医療体験にインパクト与えるようにプロダクト・サービスを開発していきます。引き続き技術的なチャレンジも行っていきますのでご注目ください! 最後に、改めて iOSDC Japan 2024 の運営の皆様、登壇されたスピーカーの皆様、参加者の皆様、ありがとうございました。来年 10 周年の開催も楽しみにしています! メドレーでは一緒に働く仲間を募集しています。 ぜひこの記事やブースや登壇などで興味を持っていただいた方はご連絡いただければと思います!カジュアル面談など実施可能ですので、お気軽にお問い合わせください! https://www.medley.jp/jobs/ また DroidKaigi 2024 にもスポンサードしてブースなど予定していますので、興味のある方はぜひ会場にて会話させていただけると嬉しいです。
2024/09/10
<![CDATA[ iOSDC Japan 2024に プラチナスポンサーとして協賛しました! ]]>
こんにちは。人材プラットフォーム本部で EngineeringManager をしている倉林です。2024 年 4 月にメドレーにジョインし、少しづつエンジニアの組織作りに携わり始めています。 メドレーは 2024/8/22 〜 8/24 の 3 日間に早稲田大学西早稲田キャンパスにて開催された「 iOSDC Japan 2024 」にプラチナスポンサーとして協賛させていただきました。 iOSDC は、iOS 関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスで、各所からアプリエンジニアが集う大規模なイベントです。毎年、多くのアプリエンジニアが集まり、最新の技術やトレンドを共有する活気あるイベントとして知られています。 2016 年から開催され、今年で 9 回目。メドレーはなんと今年で 8 年連続のスポンサー参加となり、今年も採用担当・広報・ネイティブアプリエンジニアが参加し、多くのエンジニアや関係者の方々との交流を深めることができました。 会場の様子 会場は早稲田大学西早稲田キャンパス。今年はオンライン・オフラインのハイブリッド開催で、オフライン 1100 名、オンライン 400 名の合計約 1500 名以上の参加者で賑わいました。 登壇や LT などもたくさんあり、通常セッションが 50 セッション、LT がルーキーズ LT 含めて 30 本以上で内容も幅広く、様々なインプットを得ることができました。 まさに「アプリエンジニアのお祭り」という雰囲気でした! 会場は各ブースをスタンプラリー方式で巡る形式だったこともあり、どのブース・空間も終始賑やかで、スポンサー・一般参加者・エンジニア・人事関係なく交流が行われていました。大学での開催ということもあるのか学生も多く参加しているのが印象的でした。 スポンサーブーススタンプラリー、フリードリンクや軽食、お昼時にはキッチンカー、朝ドーナツや夕方からはアルコール類の提供、ネイルやボディペイントなどのアートブースなど楽しむための様々な工夫がされていて、まさにコミュニケーションの場となる空間作りがされたカンファレンスだったと感じました。運営の方々の準備と当日のスムーズな対応に感謝です。 (スタンプを 1 列揃えて BINGO するとたこ焼き、2 列揃えるとクレープ、全部集めると iOSDC ノベルティと交換) メドレーブースの様子 メドレーブースでは、メドレーが展開するアプリの紹介と、アンケートパネルを用いて参加者の方々に医療体験に関するお悩みを伺いました。 特に課題として多かったは以下の 3 つ 待ち時間が長い 圧倒的一位でした、特に子供がいる家庭は子供を連れて薬局へも行かなくてはいけないのが辛い との回答が多数 キャッシュレス決済がしたい 大分増えてはきたけど。。。との声でした! オンラインで予約したい 電話で予約するのが面倒という方が圧倒的に多かった 予約とはちょっと違うけど病院の口コミを見たい という声も多かったです それぞれの課題についてメドレーのプロダクト・サービスを通じて解決できていること・これから解決していくことなどをご紹介させていただきました。 iOS のイベントということもあり、実施に CLINICS アプリ の画面をお見せしながら説明させていただき以下のような感想もいただきました。 オンライン診療が受けれて、薬が Uber Eats で届く。もうそこまで体験が到達しているとな思わなかった 病院検索の UI が体感が早く心地よい・どうやって実装しているのか オンライン診療で話した内容を電子カルテに書き込んだりできないのか?など新しい機能提案 などなど。 メドレーはアプリを展開している印象があまりなかったので、参考になったなどの声も頂きました。 各アプリの技術スタックは以下の画像の通りで、React Native や Flutter などのクロスプラットフォーム技術で開発しているものもあれば Swift, Kotlin などネイティブ言語で開発しているものもあり提供したい価値やアプリ特性によって様々な技術スタックを選定しています。 CLINICS では全画面の実装が SwiftUI 、SPM を用いたマルチモジュール構成だったりと新しい技術を積極的に導入しています。 セッションやブース 個人的に気になったセッション及び、弊社メドレーの吉田による登壇について少し紹介させていただければと思います。 Ditto SDK 紹介: インターネットなしで快適なデータ同期 アプリ内に SDK の処理を入れておくと、P2P で端末同士がローカルでやり取りしてデータを同期できます、というサービスの紹介。 Flutter や RN にも対応していて「ローカルの端末同士で P2P をいい感じにやる部分」と「ローカルのデータを吸い上げて適宜配信する中央サーバー」といった印象で、需要ありそうだと感じました。 Swift 6 の Typed throws と Swift におけるエラーハンドリングの全体像を学ぶ Swift 6 の新機能の 1 つである Typed throws についての紹介。 安易に使うべきではないとしながら、どういう場面では効果的かなど、実践的な内容も聞くことができました。 普段使っている Optional がエラーハンドリングにおいてどの位置づけかを含め、エラーハンドリングの全体像の概観を理解することができました。 座談会 「Strict Concurrency と Swift 6 が開く新時代: 私たちはどう生きるか?」 超満員の人気セッションで、Swift 6 対応の盛り上がりを感じました。 CLINICS アプリでも Swift 6 対応を進めているのですが、どこまでを MainActor のスコープとするか、どのレベルでのリファクタリングを同時にやっていくかが議論になっていたので、大変参考になりました。 座談会という形式も普段のトークとは異なり新鮮でした。 bitkey さんブース:bitlink をさがして! 個人的に一番面白かったのは Bitkey さんのブースです。iBeacon になる自社製品(bitlink)を携帯して歩いている社員の方がいるので、iOS アプリを自作してその人を見つけられれば、景品を渡す、という企画でした。 メドレーメンバーも結構早めにアプリ作って探しましたが、3 番目だったとのこと。残念! Forkwell さんブース 会場で配布していた資料に、イチ推し求人としてメドレーの求人情報を掲載していただいていました!いつもお世話になっております! メドレー登壇 医療アプリ開発における安全性と生産性のバランスについて医療プラットフォーム本部 患者プロダクト開発グループの吉田 ( @shzero5 ) が登壇させていただきました。 医療アプリの開発においては、患者の安全と利便性の向上が最重要課題となります。一方で、医療制度の変更への迅速な対応や新規機能の実装など、高い生産性も求められます。この 2 つの要件は相反するものですが、その両立は避けられない課題だと感じています。 今回の登壇では、メドレーのオンライン診療サービスを含む総合医療アプリ「CLINICS」の開発を通じて、いかにして安全性と生産性の両立に取り組んでいるかをご紹介しました。 診療報酬改定などの制度変更に柔軟に対応できる体制 SPM マルチモジュール、トランクベース開発など生産性向上の工夫 MagicPod を活用した自動テスト環境での効率的な品質確保 法律・ガイドライン・制度対応や社内他部門との連携を含む総合的なアプローチ 医療アプリの開発は技術的側面のみならず、適切な規制対応や組織間調整など様々な課題に直面します。 今回の登壇では、そうした課題への具体的な取り組みをご紹介しつつ、品質と速度の両立に向けた実践的な知見をお話ししました。 質問もいくつかいただきました。 トランクベース開発とのことだが、ブランチ作成からマージまでの間隔は? 大きな機能開発でも、ブランチ作成からコードレビューを通してマージまで、1 日かからない程度の粒度に分割しています MagicPod の導入をチームで進めているが、自動化するテストシナリオの選択基準は? MagicPod で自動化できるテストシナリオは全て自動化しているが、ビデオ通話など、どうしても自動テストしづらい部分は課題として残っています iOS、Android、Web で越境して実装してるとのことだが、コードレビューはどうしているのか 個々で強みのプラットフォームがあるので、知見のある人がレビューすることが多いです 発表後にブースに来ていただいて面白かったとコメント頂いたり、改めて医療領域に興味をもっていただけたりしました。医療 × テクノロジーの最前線で得られた学びを、皆様の開発にも活かしていただければ幸いです。 終わりに メドレーはこれからもアプリを通じて様々な医療体験にインパクト与えるようにプロダクト・サービスを開発していきます。引き続き技術的なチャレンジも行っていきますのでご注目ください! 最後に、改めて iOSDC Japan 2024 の運営の皆様、登壇されたスピーカーの皆様、参加者の皆様、ありがとうございました。来年 10 周年の開催も楽しみにしています! メドレーでは一緒に働く仲間を募集しています。 ぜひこの記事やブースや登壇などで興味を持っていただいた方はご連絡いただければと思います!カジュアル面談など実施可能ですので、お気軽にお問い合わせください! https://www.medley.jp/jobs/ また DroidKaigi 2024 にもスポンサードしてブースなど予定していますので、興味のある方はぜひ会場にて会話させていただけると嬉しいです。
2024/09/10
<![CDATA[ iOSDC Japan 2024に プラチナスポンサーとして協賛しました! ]]>
こんにちは。人材プラットフォーム本部で EngineeringManager をしている倉林です。2024 年 4 月にメドレーにジョインし、少しづつエンジニアの組織作りに携わり始めています。 メドレーは 2024/8/22 〜 8/24 の 3 日間に早稲田大学西早稲田キャンパスにて開催された「 iOSDC Japan 2024 」にプラチナスポンサーとして協賛させていただきました。 iOSDC は、iOS 関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスで、各所からアプリエンジニアが集う大規模なイベントです。毎年、多くのアプリエンジニアが集まり、最新の技術やトレンドを共有する活気あるイベントとして知られています。 2016 年から開催され、今年で 9 回目。メドレーはなんと今年で 8 年連続のスポンサー参加となり、今年も採用担当・広報・ネイティブアプリエンジニアが参加し、多くのエンジニアや関係者の方々との交流を深めることができました。 会場の様子 会場は早稲田大学西早稲田キャンパス。今年はオンライン・オフラインのハイブリッド開催で、オフライン 1100 名、オンライン 400 名の合計約 1500 名以上の参加者で賑わいました。 登壇や LT などもたくさんあり、通常セッションが 50 セッション、LT がルーキーズ LT 含めて 30 本以上で内容も幅広く、様々なインプットを得ることができました。 まさに「アプリエンジニアのお祭り」という雰囲気でした! 会場は各ブースをスタンプラリー方式で巡る形式だったこともあり、どのブース・空間も終始賑やかで、スポンサー・一般参加者・エンジニア・人事関係なく交流が行われていました。大学での開催ということもあるのか学生も多く参加しているのが印象的でした。 スポンサーブーススタンプラリー、フリードリンクや軽食、お昼時にはキッチンカー、朝ドーナツや夕方からはアルコール類の提供、ネイルやボディペイントなどのアートブースなど楽しむための様々な工夫がされていて、まさにコミュニケーションの場となる空間作りがされたカンファレンスだったと感じました。運営の方々の準備と当日のスムーズな対応に感謝です。 (スタンプを 1 列揃えて BINGO するとたこ焼き、2 列揃えるとクレープ、全部集めると iOSDC ノベルティと交換) メドレーブースの様子 メドレーブースでは、メドレーが展開するアプリの紹介と、アンケートパネルを用いて参加者の方々に医療体験に関するお悩みを伺いました。 特に課題として多かったは以下の 3 つ 待ち時間が長い 圧倒的一位でした、特に子供がいる家庭は子供を連れて薬局へも行かなくてはいけないのが辛い との回答が多数 キャッシュレス決済がしたい 大分増えてはきたけど。。。との声でした! オンラインで予約したい 電話で予約するのが面倒という方が圧倒的に多かった 予約とはちょっと違うけど病院の口コミを見たい という声も多かったです それぞれの課題についてメドレーのプロダクト・サービスを通じて解決できていること・これから解決していくことなどをご紹介させていただきました。 iOS のイベントということもあり、実施に CLINICS アプリ の画面をお見せしながら説明させていただき以下のような感想もいただきました。 オンライン診療が受けれて、薬が Uber Eats で届く。もうそこまで体験が到達しているとな思わなかった 病院検索の UI が体感が早く心地よい・どうやって実装しているのか オンライン診療で話した内容を電子カルテに書き込んだりできないのか?など新しい機能提案 などなど。 メドレーはアプリを展開している印象があまりなかったので、参考になったなどの声も頂きました。 各アプリの技術スタックは以下の画像の通りで、React Native や Flutter などのクロスプラットフォーム技術で開発しているものもあれば Swift, Kotlin などネイティブ言語で開発しているものもあり提供したい価値やアプリ特性によって様々な技術スタックを選定しています。 CLINICS では全画面の実装が SwiftUI 、SPM を用いたマルチモジュール構成だったりと新しい技術を積極的に導入しています。 セッションやブース 個人的に気になったセッション及び、弊社メドレーの吉田による登壇について少し紹介させていただければと思います。 Ditto SDK 紹介: インターネットなしで快適なデータ同期 アプリ内に SDK の処理を入れておくと、P2P で端末同士がローカルでやり取りしてデータを同期できます、というサービスの紹介。 Flutter や RN にも対応していて「ローカルの端末同士で P2P をいい感じにやる部分」と「ローカルのデータを吸い上げて適宜配信する中央サーバー」といった印象で、需要ありそうだと感じました。 Swift 6 の Typed throws と Swift におけるエラーハンドリングの全体像を学ぶ Swift 6 の新機能の 1 つである Typed throws についての紹介。 安易に使うべきではないとしながら、どういう場面では効果的かなど、実践的な内容も聞くことができました。 普段使っている Optional がエラーハンドリングにおいてどの位置づけかを含め、エラーハンドリングの全体像の概観を理解することができました。 座談会 「Strict Concurrency と Swift 6 が開く新時代: 私たちはどう生きるか?」 超満員の人気セッションで、Swift 6 対応の盛り上がりを感じました。 CLINICS アプリでも Swift 6 対応を進めているのですが、どこまでを MainActor のスコープとするか、どのレベルでのリファクタリングを同時にやっていくかが議論になっていたので、大変参考になりました。 座談会という形式も普段のトークとは異なり新鮮でした。 bitkey さんブース:bitlink をさがして! 個人的に一番面白かったのは Bitkey さんのブースです。iBeacon になる自社製品(bitlink)を携帯して歩いている社員の方がいるので、iOS アプリを自作してその人を見つけられれば、景品を渡す、という企画でした。 メドレーメンバーも結構早めにアプリ作って探しましたが、3 番目だったとのこと。残念! Forkwell さんブース 会場で配布していた資料に、イチ推し求人としてメドレーの求人情報を掲載していただいていました!いつもお世話になっております! メドレー登壇 医療アプリ開発における安全性と生産性のバランスについて医療プラットフォーム本部 患者プロダクト開発グループの吉田 ( @shzero5 ) が登壇させていただきました。 医療アプリの開発においては、患者の安全と利便性の向上が最重要課題となります。一方で、医療制度の変更への迅速な対応や新規機能の実装など、高い生産性も求められます。この 2 つの要件は相反するものですが、その両立は避けられない課題だと感じています。 今回の登壇では、メドレーのオンライン診療サービスを含む総合医療アプリ「CLINICS」の開発を通じて、いかにして安全性と生産性の両立に取り組んでいるかをご紹介しました。 診療報酬改定などの制度変更に柔軟に対応できる体制 SPM マルチモジュール、トランクベース開発など生産性向上の工夫 MagicPod を活用した自動テスト環境での効率的な品質確保 法律・ガイドライン・制度対応や社内他部門との連携を含む総合的なアプローチ 医療アプリの開発は技術的側面のみならず、適切な規制対応や組織間調整など様々な課題に直面します。 今回の登壇では、そうした課題への具体的な取り組みをご紹介しつつ、品質と速度の両立に向けた実践的な知見をお話ししました。 質問もいくつかいただきました。 トランクベース開発とのことだが、ブランチ作成からマージまでの間隔は? 大きな機能開発でも、ブランチ作成からコードレビューを通してマージまで、1 日かからない程度の粒度に分割しています MagicPod の導入をチームで進めているが、自動化するテストシナリオの選択基準は? MagicPod で自動化できるテストシナリオは全て自動化しているが、ビデオ通話など、どうしても自動テストしづらい部分は課題として残っています iOS、Android、Web で越境して実装してるとのことだが、コードレビューはどうしているのか 個々で強みのプラットフォームがあるので、知見のある人がレビューすることが多いです 発表後にブースに来ていただいて面白かったとコメント頂いたり、改めて医療領域に興味をもっていただけたりしました。医療 × テクノロジーの最前線で得られた学びを、皆様の開発にも活かしていただければ幸いです。 終わりに メドレーはこれからもアプリを通じて様々な医療体験にインパクト与えるようにプロダクト・サービスを開発していきます。引き続き技術的なチャレンジも行っていきますのでご注目ください! 最後に、改めて iOSDC Japan 2024 の運営の皆様、登壇されたスピーカーの皆様、参加者の皆様、ありがとうございました。来年 10 周年の開催も楽しみにしています! メドレーでは一緒に働く仲間を募集しています。 ぜひこの記事やブースや登壇などで興味を持っていただいた方はご連絡いただければと思います!カジュアル面談など実施可能ですので、お気軽にお問い合わせください! https://www.medley.jp/jobs/ また DroidKaigi 2024 にもスポンサードしてブースなど予定していますので、興味のある方はぜひ会場にて会話させていただけると嬉しいです。
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 https://open.talentio.com/r/1/c/medley/pages/105574 Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/08/30
<![CDATA[ E2Eテストの信頼性と向き合ってMagicPodのヘルススコアが100に達した話 ]]>
こんにちは、医療プラットフォーム本部 プロダクト開発室 QA グループ所属の小島大周 ( @Daishu ) です。2022 年 4 月に QA エンジニアとしてメドレーに入社しました。主に “ クラウド診療支援システム CLINICS ” のプロダクト開発における QA と、E2E テスト自動化を担当しています。 今回は、MagicPod という自動テストツールに半年間向き合い、テスト内容と結果の信頼性を高める改善を行った話をさせていただきます。 ※ 自動テストツール全般に共通する話なので、自動テストに携わっている方々にご覧いただけると大変嬉しいです。 MagicPod 弊社は E2E テストの自動化に対して MagicPod というツールを採用しています。MagicPod の詳細は割愛しますが、導入時の話は「 UIテストの自動化に MagicPod を導入した話 」にありますので、ぜひご覧ください。 活用状況と背景 私が所属する医療プラットフォーム本部では、医療機関に向けて予約や問診、診察 (電子カルテ)、会計等の機能を提供する “ クラウド診療支援システム CLINICS ” と、患者向けにオンライン診療をはじめ、総合的な医療体験を提供する “ オンライン診療・服薬指導アプリ CLINICS ” を展開しています。 私は画像左側の医療機関向けのプロダクトにおいて社内で **周辺領域 1 ** と呼ぶ機能群 を中心としたQA・テスト自動化を担当しています。MagicPod は導入して4年目になりますが、半年前までこの周辺領域の機能に関しては、MagicPod を十分活用しきれておらず、以下のような状況でした。 MagicPod の自動テスト実行頻度が週 1 回のみ 自動化したリグレッションテストが 3 件しかない ( 20件が推奨値 ) テスト結果が不安定で、自動テストの修正にかかる調査コストが大きい また、MagicPod には “ ヘルススコア機能 ” がありますが、当時のヘルススコアは 30 点と低い数字でした。これは端的に言うと「 自動テストの信頼性が低い 」という状態です。一方で、画像右側の CLINICS アプリ (患者向け) は MagicPod を十分活用できており、既にヘルススコアも 100 点に達していました。それゆえに、CLINICS (医療機関向け) の自動テストの改善が望まれていました。 当時の CLINICS (医療機関向け) のヘルススコア MagicPod ヘルススコア機能 自動テストの改善について話す前に、MagicPod が提供しているヘルススコア機能について説明します。ヘルススコア機能とは、自動テストの活用度合いや成功率などを 100 点満点でスコアリングしたもので、2023 年 12 月にリリースされました。 ざっくりとした採点基準の内訳と配点は下記となっています。 引用元:LeanとDevOpsのために E2E テストができること 注目すべきは、「 テストから信頼性のあるフィードバックを早いサイクルで得られているか 」を重視している点です。これは、手動テストの工数削減や、自動テストでの不具合検出数のような 費用対効果を意識した指標ではなく、開発生産性への貢献を意識した指標 となっています。スコアが低いということは「テストに信頼性がなく必要なフィードバックが得られていない」ことを意味しており、自動テストが開発生産性に貢献できていない状態となります。 私個人も、テストカバレッジが十分ある自動テストが統合ブランチでパスしているなら「開発ブランチで不具合を潰してマージされている」と考えますし、自動テストでは「 統合ブランチが stable であることを保証する 」ことが、「不具合を見つけた件数」と並んで重要と捉えています。ヘルススコア機能がリリースされたことで、こういった活動も定量的に測定できるので重宝しています。 主に3つの改善を実施しました 本題である E2E 自動テストの改善について話していきます。約半年前から本腰をいれて自動テストの信頼性向上に取り組みました。 ① デイリー実行で不安定なテストを解消した 早いサイクルでフィードバックを得るには、自動テストのデイリー実行は必須です。そもそも、ウィークリー実行にしていた理由は、テスト結果が不安定なケース (以下、Flaky test) が多数あり、不具合かどうか調査するコストが大きかったからです。実際、調査してもほとんどが Flaky test で自動テスト側の不備で終わることが多く、ここに時間を割くなら開発機能の QA に使いたいという考えが当時ありました。とはいえ、Flaky test と一口に言っても突き詰めると何かしらの原因があり、発生パターンは限定的です。テスト結果を信頼できるものにするためにも、デイリー実行で Flaky test と向き合いました。 まず、デイリー実行すれば Flaky test となるパターンに遭遇できます。次に「なぜ Flaky test として失敗するのか?」を 1 件ずつ追求していくことで、見つけた “穴” を確実に塞いでいきます。そして、この活動を毎日繰り返すことで、堅牢で精度の高い自動テストを構築できました。これは信頼性のあるフィードバックを得る上でも重要な要素でした。今は「 自動テストはデイリー実行で育てるもの 」という考えで、日々の自動テストの結果と向き合うことができています。 ② テストケースの二重メンテナンスを止めた テストカバレッジが十分でないと、毎日自動テストを動かしても「統合ブランチが stable である」と言い切ることはできません。信頼性を高める上で、テスト対象とする機能の充実化は必須要件でした。しかし、当時のリグレッションテストの自動化フローは、手動テスト用のケースをスプレッドシートで作成した上で自動化する流れとなっており、テストケースを二重メンテナンスする形となっていました。このように本来の必要以上の工数がかかってしまうことからテストカバレッジを素早く上げづらい状況がありました。 手動テスト用のケースは、自動化後に触る機会がほとんどないにも関わらず、仕様変更などで自動テストに手を加えるたびにメンテナンスコストが発生します。もちろん、仕様キャッチアップ等の特定シーンで役立つ事はありますが、常にではありません。こういった運用コストの課題もあり、 テストケースの二重メンテナンスはしない方針 に切り替えました。 現在は下記フローで MagicPod のテスト実装のみ行なっています。 リグレッションテストの自動化手順 この方針により、約半年で CLINICS の周辺領域に含まれる機能のテストカバレッジを 100% まで拡充 できました。一方で、手動テスト用のケースがないことで「テストケースを使った仕様キャッチアップができない、そもそもどんな自動テストがあるのか外から見えづらい」とった課題が生まれましたが、MagicPod がテスト実行時に取得するキャプチャを用いた仕様書や、機能一覧と自動化したテストケースをマッピングした資料を用意することで対応しています。この取り組みについては、別途またご紹介できればと思います。 MagicPod のテスト概要欄の記載例 ③ 先行して共有ステップを作成した この改善が最も成果に結びつきました。 共有ステップ とは MagicPod の標準機能で、テストステップを汎用的なステップ (関数化) として流用できるものです。一般的に、複数のテストで同一のステップがある場合、共有ステップを作成されると思いますが、私は現時点で同一ステップがなくても、 先行投資的に共有ステップを作成する方針 で実装を進めました。これにより、早い段階で共有ステップを拡充できました。 現在は、共有ステップをパズルのように組み上げる、実際のコーディングに近い実装スタイルを確立できました。実装スピードは格段に上がり、再発防止等で確認項目を追加する場合は 10 分ほど、ゼロから大きめの E2E テストを実装する場合でも 1-2 時間ほどで作成できます。 実装スピードの向上はテストカバレッジを上げる上でも役立ちましたが、他のテストで動作保証できた共有ステップを使い回すことで「 デイリー実行で自動テストを育てる前から安定したテストを作りやすい 」という点も大きかったです。 共有ステップ例:Mailtrapに届いたメールの本文から正規表現に一致するテキストを取得 改善した結果どうなったか 一番の成果は、前日にマージされた Pull Request の不具合検出が毎朝行えるようになり、冒頭紹介した「テストから信頼性のあるフィードバックを早いサイクルで得られる」点が達成できたことです。また、テストカバレッジも十分あるので「統合ブランチが stable である」ことが保証でき、 機能開発や QA しやすい状況づくり (=開発生産性) にもコミットできている と思います。 障害発生時には、MagicPod で再発防止策の自動テストを作るという手段を QA エンジニアだけで完結できるようになりました。これまで QA 側で対応できることは手動のリグレッションテストを追加する方法が多かったですが、 自動テストで再発を抑止するという解決手段を QA エンジニアが持てることは運用コスト的にも大きい です。 これらの改善を通して、開発エンジニアの方々からの自動テストに対する信頼感が高まってきた、と感じることも増えてきました。 障害の再発防止として自動テストを作成した際 また先日にはMagicPod 社の ミートアップイベント に登壇する機会もいただきました。登壇時に利用したスライドは下記です。共有ステップの Tips や安定した Xpath ロケータを取得する方法などを紹介しているので、既に MagicPod を利用されている方はぜひご覧ください。 今後やりたいこと 上述した改善により、CLINICS (医療機関向け) の周辺領域における MagicPod のヘルススコアは 30 点から 100 点まで上げることができました。現在は、自動テストの新規追加や変更を加えた際にスコアが変動しないか注視しながら改善を継続しており、 デイリー実行する自動テストの安定稼働と拡張の両立 ができています。 今後もこのプロセスを崩さず、 CLINICS の基幹領域 2 に対してもテストカバレッジを広げていきたい と考えています。まずは、基幹領域の中でE2Eで確認すべき機能の洗い出し、次に洗い出した機能の自動化タスクを個人にアサインできる体制づくりを検討しています。そのためにも、オンボーディングやレビュー体制、コーディングルール等の仕組みづくりもセットで考えていきます。 また、 CLINICS に携わる開発の方々は実装しながらテストコードを書く素晴らしい文化 がありますが、MagicPod の自動テストと一部重複して確認している箇所があります。テスト対象は重複しつつも、 テスト粒度の方針を定めて自動テスト全体の最適化 にも取り組んでいく予定です。 おわりに 私が所属する医療プラットフォームの QA チームはいわゆる完全内製型で少数体制です。しかし、MagicPod の実装の容易さ、メンテナンスコストの低さにより少数でも複数のプロダクトを広範囲でカバーできています。組織体制にも大きく貢献できる MagicPod は素晴らしいツールです。この場をお借りして改めて感謝申し上げたいと思います。いつもありがとうございます。 メドレーは、現在 QA エンジニアを募集しています。医療分野における高い品質目標と、いち早くお客様に価値提供するという課題の両立に対して、QA エンジニアだからできる解決策の打ち手を一緒に考えてコミットしていける方と是非お会いしたいです。 医療PF QAエンジニア / 株式会社メドレー 株式会社メドレーは医療PF QAエンジニアを採用しています。 open.talentio.com Footnotes 周辺領域とは、主に CLINICS の予約や問診、資格確認といった医療機関と患者との接点となるシステムを指す。社内での呼称。 ↩ 基幹領域とは、主に CLINICS の受付・診察・会計といった業務において、電子カルテとレセコン(レセプトコンピュータの略。医療機関から健康保険組合などの支払い機関に対し、診療報酬を請求するために、レセプトと呼ばれる診療報酬明細書を作成するシステム)とのやりとりを行うシステムを指す。社内での呼称。 ↩
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
2024/07/23
<![CDATA[ Next.js と Server-side Rendering をプロダクト環境で3年運用してきた知見と率直な所感 ]]>
こんにちは、医療プラットフォーム本部・プロダクト開発室・第1開発グループ所属の加藤です。 オンライン診療・オンライン服薬指導アプリ「CLINICS」 の開発を担当しています。 今回は CLINICS で採用している Next.js と Server-side Rendering (SSR) についてお話ししたいと思います。 Next.js は昨今注目を集めている React ベースの Web フレームワークです。 これから Web フロントエンドの開発を始めるにあたって採用を検討している方も多いのではないでしょうか。 Next.js といえば React コンポーネントをサーバー上で実行して HTML を返す SSR に対応しているのが大きな特徴です。 SSR には様々なメリットがある一方で、採用にあたって自分たちのプロダクトに SSR は不要なのではないかといった懸念や Node.js の実行環境の運用コストを気にする声もよく耳にします。 この記事ではメドレーでの Next.js, SSR の採用事例を紹介しつつ、採用にあたって一般に懸念される点を実際に採用してみた上での所感も交えてお話しできればと思っています。 メドレーの医療プラットフォーム事業と CLINICS アプリについて まずはメドレーの医療プラットフォーム事業と CLINICS アプリについて簡単に紹介させてください。 メドレーの医療プラットフォーム事業は、2016年にオンライン診療システムとしてリリースされた 「CLINICS」 を原点としています。 当時は医療機関の方が操作する業務システム部分と患者さん向けの iOS/Android アプリとその Web 版が存在するという構成でした。 その後 CLINICS には電子カルテなどの様々な機能が追加され、現在ではオンライン診療に留まらず医療機関の様々な業務を支援するクラウド診療支援システムへと発展しています。 また、2020年にリリースされたかかりつけ薬局支援システム 「Pharms」 や2022年にリリースされたクラウド歯科支援システム 「Dentis」 もプロダクトのラインナップに加わり、より多くの医療機関の業務を支援するプラットフォームとしてサービスの規模を拡大しています。 医療機関向けの業務システムは医科・歯科・調剤薬局とそれぞれの業務特性に合わせてプロダクトが分かれている一方で、患者さん向けの機能はすべて CLINICS アプリに集約されています。 業務システムの機能拡充に伴って CLINICS アプリの機能も拡充されており、現在ではオンライン服薬指導機能や処方箋の事前送信機能など様々な機能が追加されています。 今回お話しするのはこの CLINICS アプリの Web 版 (以下、CLINICS) のフロントエンド開発についてです。 Next.js 採用のモチベーション CLINICS アプリはリリース以後続々と機能が拡張されてきたのですが、こうした開発を支えるため 2021年に大規模なリニューアルを実施しました。 特に Web 版はリニューアルのタイミングでフルスクラッチで実装し直す選択をしています。 リニューアル以前のトップページ 現在のトップページ リニューアル以前の CLINICS はログインの前後で実装が分かれており、この点がフルスクラッチでの実装を選択する大きなモチベーションとなりました。 CLINICS は開発当初から Ruby on Rails で開発されているのですが、患者さん向けのページは Rails のテンプレートエンジンを用いて実装されている部分と SPA として実装されている部分が混在していました。 医療機関の検索や詳細などの検索エンジンからの流入を確保したいページではテンプレートエンジンを用いて HTML を直接レスポンスする、ログインページや予約ページなどの操作性を重視したページでは SPA として実装されている、といった具合です。 こうしたテンプレートエンジンと SPA の併用構成では、ログインの前後で一貫したユーザー体験を提供するのは困難だと感じていました。 例えば、同じ機能がログイン前と後とで2つ存在する箇所もあり、ユーザーから見るとログインを挟んで UI が変わってしまい、あまり良いユーザー体験とは言えない状態でした。 もちろんこういった課題はログイン前後の両方のページの UI を丁寧に設計することで解決が可能ではありますが、異なる技術スタックで同じような機能を実装しつつ UI の一貫性を保つのは容易ではありません。 そういった背景からリニューアルではログイン前後での実装を一本化する方針を立てていました。 実装を一本化する上で SSR に対応している Next.js は非常に魅力的な選択肢でした。 SSR には初期表示のパフォーマンス向上などのメリットもあるのですが、採用にあたっては SEO 面でのメリットを重視していました。 近年では Google のクローラーが JavaScript を実行してくれるのですが、直接 HTML をレスポンスできるのであればその方がより確実だと判断しました。 これが Next.js を採用するに至った最大の理由です。 ちなみに、この当時は App Router がリリースされる前だったため、 Pages Router で開発を開始しました。 以降の内容も基本的に Pages Router を前提としてお話ししていきますが、 App Router や他のフレームワークを使用している場合でも SSR についての考え方は共通している部分が多いので少しでも参考にしていただけたら幸いです。 Server-side Rendering の仕組み Server-side Rendering (SSR) とは、Next.js や Remix などの React ベースのフレームワークが持つ機能のひとつです。 SSR という用語は昨今の React に関する話題の中ではよく耳にする言葉ですが、実は React の公式ドキュメントに SSR とは何かという記述は存在していません。 それでは React 本体にはサーバー環境向けの機能が存在しないのかというとそうではなく、React は コンポーネントから HTML を生成するための API を提供しています。 Next.js や Remix はこうした API を利用してサーバー環境で HTML を生成しつつブラウザ環境では従来の SPA のような振る舞いを実現する機能を提供しており、こうした機能には SSR という名前が付けられています。 例えば、Next.js の Pages Router では getServerSideProps を使用してリクエスト毎に HTML を生成する機能を SSR と呼んでいます。 各フレームワークによってサーバー側でのデータ取得の方法は異なりますが、React コンポーネントから HTML を生成する仕組みは共通しています。 サーバー上で HTML を生成すると言うとテンプレートエンジンなどを用いる場合と変わらないように感じられるかもしれませんが、SSR には ハイドレーション という仕組みが存在するのが大きな特徴です。 生成された HTML はクライアントにレスポンスされてブラウザ上で表示されるのですが、この時点ではイベントハンドラーが DOM にアタッチされておらず、ユーザーの操作に対して反応することができない状態です。 そこで React はブラウザ上で再度コンポーネントをレンダリングしてイベントハンドラーを DOM にアタッチします。 この処理はハイドレーションと呼ばれています。 ハイドレーションが行われるとアプリケーションはユーザー操作に反応することができるようになります。 アプリケーションによってはいわゆる Client-side Rendering (CSR) と呼ばれる useEffect によるデータの取得と追加の描画が行われる場合もあります。 さらに、ハイドレーションが行われた状態からページ遷移が行われる場合には history API が使用されます。 一連の流れをシーケンス図にすると以下のようになります。 このように SSR を使用しているアプリケーションでもハイドレーションが行われた後は従来の SPA と同様に振る舞います。 そのため、Context API や Redux などの状態管理ライブラリを使用してページを跨いで状態を共有することも可能です。 こういった特徴から考えると、SSR はこれまでの React と対立するものではなく、むしろその機能を一層強化するものと言えるでしょう。 CLINICS での活用事例の紹介 ここからは実際にどういった形で Next.js と SSR を利用しているのか、CLINICS の活用事例を紹介していきます。 CLINICS のシステム構成は以下のようになっています。 (実際にはもう少し複雑な構成を取っているのですが、今回の説明では簡略化しています) CLINICS の Next.js サーバーは固有のデータベースを持っておらず、必要なデータはすべてバックエンドの API から取得しています。 SSR の際には Next.js サーバーから、CSR の際にはブラウザから API にリクエストが送信されます。 セッション情報については API サーバー側で管理しており、Next.js サーバー側にはセッション情報を共有しない方針を取っています。 SEO 面でのメリットを重視していたため、SSR するのはログイン不要で閲覧可能なページのみで十分だろうと判断しました。 そのため、SSR をする際にはログイン不要で取得できる情報のみを表示し、ログインが必要な情報を表示する際には CSR を使用しています。 SSR を使用しているページでも部分的に CSR を組み合わせて使用しており、ページによっては SSR を用いずに全体が CSR で実装されているケースもあります。 感覚的には従来の SPA をベースとして部分的に SSR を組み合わせていると言っても良いかもしれません。 採用して良かったと感じている点 ここからは実際に Next.js を使ってみた所感を交えてお話ししていこうと思います。 まずは、Next.js を採用して良かったと感じている点についてです。 全体的な開発体験 フルスクラッチで実装し直す上で Next.js は良い選択だったと感じています。 Next.js というと SSR のイメージが強いかもしれませんが、SSR を抜きにしても SPA の開発に必要な要素は一通り備わっています。 Webpack やトランスパイラなどのビルドツールの設定がデフォルトで含まれており、React のプロジェクトを新規に立ち上げる際には非常に便利なフレームワークだと感じています。 CLINICS では CSS 関連で追加のライブラリを使用しているのを除けば、ほとんどの実装を Next.js と React の標準機能だけで開発しています。 SEO 面での扱いやすさ こちらは Next.js を採用するにあたって重視していた点なのですが、やはり SSR でサーバーから直接レスポンスを返せるという点で SEO 面では扱いやすいと感じています。 title タグや meta タグなどももちろんですが、HTTP ステータスコードも制御できるため、クローラーに意図を伝える伝統的な方法がそのまま使える点は非常に便利です。 SEO とは直接関係ありませんが、SNS でリンクがシェアされる際の OGP 用の meta タグを動的に生成したいといったケースへの対応も容易です。 とはいえ、近年は Google のクローラーも JavaScript を実行してくれるので SPA が必ずしも SEO 的に不利というわけではありません。 クローラーが JavaScript を理解する能力は年々向上しているので、適切に設計された SPA であれば SEO 的に問題ないというケースも多いようです。 こうしたクローラーの進歩や実装上のテクニックも踏まえると SSR の SEO 面でのメリットはあくまでその扱いやすさという観点で考えると良いかもしれません。 パフォーマンスの向上 SSR を取り入れるにあたってパフォーマンス面について特に意識していたわけではないのですが、実際に SSR を使ってみて FCP (First Contentful Paint) や LCP (Largest Contentful Paint) といった初期表示の速度を表す指標の改善に効果があるなと感じています。 CSR では JS でのデータ取得が完了して始めて LCP 要素が表示されるケースが多いため、JS ファイルのダウンロードや実行の分だけ FCP や LCP が遅延しやすい傾向にあります。 SSR ではこうした JS のダウンロードや実行の時間が減る分、初期表示のパフォーマンス改善が期待できます。 体感的にもローディングインジケーターの表示を挟まずにコンテンツが表示されるため、ユーザーにとってはより快適な体験となるのではないかと感じています。 また、SSR 以外にも Next.js は画像の最適化やコードスプリッティングなどのパフォーマンス向上に役立つ機能を多く提供しているため、安定したパフォーマンスの Web アプリケーションを開発する上では非常に心強い存在です。 セッション管理についての反省点 Next.js そのものについて不便に感じている点はあまりないのですが、SSR を取り入れるにあたってセッション管理についてはよく考えておくべきだったと反省している部分もあります。 従来の SPA であればセッション管理は API サーバーが管理するというのが一般的ですが、SSR を採用する場合では Next.js サーバーと API サーバーが存在するという構成になるケースが多いかと思います。 この場合、Next.js サーバーと API サーバーのどちらでセッションを管理するのか、セッション情報を共有するのか、共有するのであればどのような方法で共有するのかといった点で複数の選択肢が考えられます。 CLINICS では前述の通り API サーバーでセッションを管理して Next.js サーバーとの間でセッション情報を共有しない構成を採用しています。 こうした構成の都合で Next.js サーバーでセッション情報を扱うことができないため、ログイン済みのユーザー固有の情報は SSR することができず、CSR で取得して描画する必要があります。 このようにして SSR と CSR を組み合わせた場合、CSR で取得したデータを描画する際にレイアウトシフトが発生しやすくなります。 また、ログイン済みのユーザーに対しては検索結果をカスタマイズしたり並び替えたりといった要件への対応も難しくなってしまいます。 こういった面で SSR と CSR を組み合わせざるを得ない現状の認証構成には課題があると感じています。 こうした課題を解消するためにも、今後はセッション情報を Next.js サーバーと共有する構成へと変更し、CSR している部分を SSR する形に変更していきたいと考えています。 このように SSR を活用する場合には従来の SPA よりもセッション管理の選択肢が増えるため、セッション管理については特に慎重に考える必要があると感じています。 SSR を今は必要としていないというケースでも、将来的な導入に備えてセッション管理について少し考えを巡らせておくと良いかもしれません。 Next.js の採用を検討している方へ 最後に、これから Next.js を採用しようとしている方が気になっているのではないかと思われるポイントについてお話ししていこうと思います。 Next.js を採用するにあたって最も気になるポイントはやはり Node.js の実行環境の運用コストではないでしょうか。 Next.js では一部の例外を除けば SSR を使用するか否かに関わらず実行には Node.js サーバーが必要となります。 SSR は必要としていないが Next.js の様々な恩恵を受けたいという開発者にとっては Node.js サーバーの運用コストが気になるところかと思います。 CLINICS では AWS ECS/Fargate で Next.js サーバーを運用しているのですが、Node.js の実行環境を運用するコストは確かに発生しているものの、現状ではそれほど大きな負担には感じていません。 API サーバーが別で存在する構成では Next.js サーバーが担うのはルーティングに従って API サーバーからデータを取得して SSR するといった比較的シンプルな役割になります。 そのため、データベースを扱うような本格的なバックエンドに比べると運用の手間は低く抑えられている印象です。 どうしても Node.js の実行環境を持たずに運用したいという場合には Static Exports というビルド時に HTML を含む静的アセットを出力する機能の利用も検討してみると良いかもしれません。 ただし、機能面でいくつかの制約があるので、採用を検討する際にはよく確認しておくことをお勧めします。 どちらかと言えば Static Exports は静的なサイトを構築するのに向いている機能であり、動的なコンテンツを扱うようなアプリケーションにはあまり向いていないというのが正直な感想です。 従来の SPA に多く見られるようなビルド済みの JavaScript, CSS などの静的アセットを S3 などのストレージに配置して HTML はバックエンドのサーバーから配信するといった構成が想定されていない点も注意が必要かと思います。 また、Next.js の採用にあたって App Router に追従すべきかというのも悩ましいポイントです。 App Router は Next.js 13 で導入された新しいルーティングシステムで、Server Components/Actions などの React の新機能もサポートしている点が魅力ですが、リリースから日が浅くまだしばらくは様子を見たいと考えている方も多いのではないでしょうか。 現状 CLINICS ではまだ App Router への移行は考えておらず実際の使用感などをお話しすることはできないのですが、ドキュメントを読む限りでは Pages Router の扱いにくい部分がうまく改善されている印象はあります。 ただ、Pages Router のルーティング機能と完全な互換性がない点が移行を考える上で最大のネックだと感じています。 こういった移行のコストや Next.js 自体が App Router への移行を推奨していることを踏まえると、今から新規に開発を始めるのであれば App Router で開発を始めてしまった方が無難な選択かもしれません。 総じて、Node.js サーバーの運用コストが許容できるか、App Router や Server Components/Actions に魅力を感じるかといった点が Next.js の採用を検討する上でのポイントになるのではないでしょうか。 まとめ CLINICS では Next.js を採用しており、SSR と CSR を併用する形で比較的ライトに SSR を取り入れてフロントエンドの開発を進めています。 当初は SEO 面でのメリットを重視していましたが、実際に使ってみるとパフォーマンスの向上や開発体験の向上など様々なメリットを感じています。 セッション管理については課題を抱えている部分もありますが、今後はそういった部分を改善しより一層 SSR の恩恵を受けられるようにしていきたいと考えています。 Next.js の他にも Remix と React Router の統合 が発表されるなど、さらに SSR を活用しやすい環境が整いつつあるという点でも、SSR の今後は非常に楽しみな部分が多いと感じています。
1
More pages
7
8
9
10
11
More pages
68
コンテンツ
トップ
イベント
ブログ
グループに関するお問い合わせ