CodePipelineで開発ブランチを任意のステージング環境へデプロイする - Qiita
やりたいこと・前提条件アプリケーションのソースコードをGitHubで管理しているステージング環境用のアプリケーションがECSで稼働しているDockerイメージのビルドやECSへのデプロイはCo...
https://qiita.com/t0hara/items/36bdf281c89ba4959247
KIYOラーニング株式会社のページをご覧の皆さま、こんにちは。
技術広報メンバーの大原です。
今回は「開発秘話シリーズ」第5弾として、当社のオンライン資格講座サービス「スタディング」に関連するWebシステムの刷新プロジェクトについてご紹介します。
2025年2月、ユーザーの皆さまにより快適にご利用いただくため、スタディングのWebサービスの一部を対象に、システムの基盤をより安定的かつ拡張性の高い構成へと刷新しました。
本記事では、プロジェクトに関わったメンバーへのインタビューを通じて、開発の背景や進め方、乗り越えてきた課題についてお伝えします。
このプロジェクトで刷新の対象となるWebシステムは、10年以上前にPHPとFuelPHPフレームワークで構築されたものでしたが、PHPのバージョンアップに伴ってフレームワークとの互換性に課題が生じ、システムの保守が困難となっていました。
こうした背景から、このWebシステムの全面的なリプレイスが決定されました。
また、リプレイスにあたっては、ユーザー体験の向上やSEOの観点から、サイト表示のパフォーマンス改善も重要なテーマとして掲げられました。ページ表示速度は、離脱率や検索順位にも大きな影響を与えるため、単なる機能移行にとどまらず、より高速で快適なWebシステムを実現することがプロジェクト全体の大きな目標の一つとなりました。
プロジェクトは技術選定や検証といった検討・準備段階を丁寧に進めたうえで、本格的な開発に着手しました。実装、QAテスト、関係部門によるレビューなど、複数のフェーズを重ねながら、長期間にわたる取り組みの末、無事リリースを迎えることができました。開発ボリュームも大きく、多くの関係者が関わった大規模プロジェクトとなりました。
開発部署のメンバー全員が集まり、どのような技術を用いてリプレイスを行うべきか、活発な議論が交わされました。いくつか候補が挙がりましたが、パフォーマンス改善の実現可能性や開発のしやすさを見極めるため、実際にプロトタイプを開発し、SPAのレンダリング速度やAPIレスポンスの検証を行いました。
その結果、フロントエンドにはNext.js、サーバーサイドにはLaravel(PHP)の構成を採用することに決まりました。またインフラについてはAWSに再構築し、コンテナサービスを基盤とする運用体制を目指すことになりました。
中でもNext.jsは、当社としてこれまで導入実績がなく、学習やキャッチアップが必要な新しい技術領域でした。その意味で、今回の技術選定はチャレンジングな側面を持ちつつも、将来を見据えた前向きな挑戦でもありました。
Next.jsの採用が決まり、開発は当時の最新バージョンである13.5.6をベースにスタートしました。ちょうどその頃、新しいルーティング方式である「App Router」が正式に導入され始めており、私たちのプロジェクトでもこの新機能を活用することになりました。
App Routerは、それまで主流だったPage Routerとは設計思想が大きく異なり、とくにサーバーコンポーネントやデータ取得の仕組みに関して、従来のベストプラクティスが通用しない場面が多くありました。
しかし、App Router自体が安定版として登場したばかりだったため、Web上にある情報もまだ限られていました。そのため、開発チームは日々発生する課題に対し、App Routerの仕様を正しく理解しながら試行錯誤を重ね実装を進めていくことになりました。
加えて、開発を進める中でNext.jsの新バージョンが次々とリリースされたため、バージョンアップによる課題解決も並行して行いました。ただし、バージョンアップが原因で別の問題が発生することもあったため、必ずしも最新バージョンを追い続けるのではなく、実装との相性や安定性を見極めながら、その都度最適なバージョンを選択していきました。
このような中での開発は決して平坦ではありませんでしたが、最新技術への積極的な取り組みとして、チーム全体で技術力を磨く貴重な経験となりました。
従来のSSR(サーバーサイドレンダリング)方式から、SSRとCDNキャッシュを組み合わせた疑似ISR(Incremental Static Regeneration)方式を採用しました。
初回アクセス時は従来どおりSSRでページを生成し、2回目以降のアクセスでは、生成済みのHTMLをCDNキャッシュから返すことで、高速なページ表示を実現しています。この仕組みは、CloudFrontとLambda@Edgeを組み合わせることで制御しています。
キャッシュ化にあたっては、ログイン状態に応じたユーザー固有の情報はキャッシュできないため、それらの情報はクライアント側でAPIを介して動的に表示する必要がありました。
また、ページコンテンツが更新された際には、適切なタイミングでCDNキャッシュを削除できるよう、キャッシュ管理の仕組みもあわせて実装しました。
この方式は、システムをまたいで処理が複雑になるものの、パフォーマンス改善のために不可欠な対応でした。
本格的に開発を開始した当初は、3名体制でプロジェクトを進行していました。しかし、Next.jsのApp Routerを用いた開発では予想以上に技術的な課題が多く、スケジュールの遅延を余儀なくされる状況となっていました。
この状況を打開するため、私(大原)がプロジェクトマネージャーとして参画することになり、チームは4名体制になりました。開発体制の見直しと並行して課題の洗い出しを進めた結果、状況の全体像が徐々に明らかになったものの、リリース時期は当初の予定より大幅に遅れることも判明しました。
状況を挽回するため、インフラ構築などのタスクの担当者を再編し、チーム全体の負担を分散させることで、開発効率の最大化を図りました。その結果、開発は一定の動作確認ができるレベルまで到達し、並行してテスト環境の整備も完了しました。
開発が軌道に乗ってきたころ、メンバーの一人が離脱することになりました。重要な戦力だったこともあって大きな痛手でしたが、円滑な引継ぎと開発の継続を実現するため、事前に相談すべき事項を整理し、計画的に引継ぎを進めました。
具体的には、タスクの完了を厳密に追求するのではなく、ある程度見通しが立った時点で区切りをつけ、次のタスクに取り掛かってもらうようにしました。これにより、未着手のタスクを最小限に抑え、スムーズに開発を継続することができました。
また、開発が大詰めに入るころには、デザインチームの早狩さんの協力を得て、デザイン実装を進めました。そしてテストフェーズではQAチームの坪根さんと連携し、品質向上にも注力しました。
今回のリプレイスでは、AWSサービスの構成を刷新し、運用の効率化と安定性の向上を図りました。ほとんどのAWSサービスは新規作成または再構築を行っています。また開発を進める中でも設計の見直しを重ね、現在の最適な構成に至っています。
例えばコンテナサービスはAWS App Runnerを使う計画でしたが、スケーラビリティやリソース管理の柔軟性を高めるためにAWS Fargate(ECS)へ変更しました。コンテナイメージのビルドはGitHub Actionsで実行する方法を試しましたが、AWSリソースとの統合を強化するためにCodeBuildへ変更しました。
その結果、AWS CodePipelineを利用したCI/CDの導入や、AWS Secrets Managerなどを利用した環境変数の一元管理が可能になりました。
▼ステージング環境へのデプロイについてはこちらのQiita記事にて発信しています。
また、デプロイ時のダウンタイム問題にも対応しました。Next.jsでは、ビルド時にJSファイルの名前にハッシュ値が自動付与されるため、デプロイ時のアクセスのタイミング次第ではブラウザ側で古いJSファイルを参照してしまい、404エラーが発生する可能性があります。この影響でサイトが正常に表示されないケースが発生しました。
この問題を解決するため、コンテナサービスではブルー/グリーンデプロイを採用し、デプロイ時の切り替えをスムーズにしました。さらに、Next.jsの静的アセットファイルを専用CDN(CloudFront)経由で配信することで、404エラーを回避しました。
システムの本格運用に向けた準備の一環として、一時的に新システムへサービスを切り替える形で試験運用を行いました。短期間のモニタリングを通じて、いくつかの課題が明らかになったため、リスク回避を優先し、既存システムへの切り戻しを実施しました。
その後は、試験運用で得られたフィードバックをもとに改修を重ね、特に安定性の向上に注力しました。QAチームとも密に連携し、品質の向上にも継続して取り組みました。
こうした丁寧な改善プロセスを経て、十分な品質と信頼性を確保したうえで本番リリースを迎え、無事にサービスの提供を開始することができました。
本プロジェクトの成功には、多くのエンジニアや関係者の尽力がありました。中でも、開発をリードしたエンジニアの幸田さんと、QAテストを担当し品質向上に貢献したQAエンジニアの坪根さんの存在は欠かせません。それぞれの視点でプロジェクトを振り返った感想を伺いたいと思います。
大原「幸田さんは入社早々プロジェクトに参画することになりましたが、当時を振り返ってみてどうですか?」
幸田「既存システムと新システムの仕組みを理解するのに苦労しました。今回のプロジェクトでは、サイトのデザインはほぼそのままに裏側の仕組みを変更する形だったので、新旧両方のシステムを理解する必要があり、入社直後の私にとっては大きな負担でした。
加えて、これまで蓄積されていた技術的負債を解消していく必要もありました。HTML構造に問題があったデータがこれまではブラウザの補完機能で表示されていたのに、Next.jsを導入したことでエラーとして扱われるケースが発生するようになりました。そのため、表示できないページの洗い出しを行い、データ修正やプログラムの改修で柔軟に対処しなければなりませんでした。」
大原「約1年にわたりプロジェクトに関わってみて、特に印象に残っていることや学びはありましたか?」
幸田「モダンな開発環境の整備に取り組めたことが印象に残っています。GitHub ActionsとAWS CodePipeline、サーバレス技術を活用することで、開発効率を向上できました。
また、CDNキャッシュをはじめ、キャッシュの活用範囲が広がったことで、キャッシュを考慮した実装を意識するようになりました。キャッシュを適切に利用することでパフォーマンス向上につながる一方、キャッシュが原因で期待通りに動作しないケースもあり、そのメリットとデメリットを実際に体感できたのは大きな学びでした。」
大原「坪根さんはこのプロジェクトでQAテストを担当されましたが、特に印象に残っていることはありますか?」
坪根「はい、いくつか印象に残っていることがあります。まず、バグバウンティの取り組みですね。システム本部全体で品質向上に取り組み、バグを見つけた数をランキング化したり、イベント感を出すことで、楽しみながら品質改善ができたのが良かったです。
また、自動ビジュアルリグレッションテストの導入も印象的でした。BackstopJSを利用して、UIの変更を視覚的に検出するテストを実施しました。特に、幸田さんが積極的に対応してくれたおかげで、スムーズに導入できました。目視では見逃しがちなデザイン崩れや意図しない変更を検出でき、品質向上に大きく貢献したと感じています。
さらに、最初のリリース後にバグの再発防止の振り返りを行ったことも重要なポイントでした。テストプロセスを見直し、具体的にはAndroidタブレットでもテストを実施するようにしたことで、より多くの環境での品質保証が可能になりました。」
大原「テストを進める中で、特に苦労した点や課題に感じたことはありましたか?」
坪根「はい、一番の課題はテスト範囲の広さでした。対象となる画面数が多く、すべての機能を網羅するのが難しかったです。その結果、一部の機能のテストが不十分になってしまうこともありました。特に、Webシステムのユースケースを事業部の方にヒアリングしていれば、より適切なテスト計画を立てられたのではないかと感じています。
また、Webシステムの自動テストが整備されていなかったため、多くの部分を手動でテストする必要がありました。その分、工数がかかるだけでなく、人的ミスのリスクも高まるため、自動化の必要性を強く感じました。」
本プロジェクトは、技術的・体制的な困難が続く中で、チーム全員が知恵を出し合い、一つひとつの課題を丁寧に乗り越えることで、無事にサービスをリリースすることができました。
私自身にとっても、新たな技術に触れる貴重な機会となり、社内に新たな開発実績を築けたことを嬉しく思います。今後は、このプロジェクトで得た知見をチーム内で積極的に共有し、次の開発に活かしていきたいと考えています。
また、プロジェクトマネジメントの面でも多くの学びがあり、改善すべき点や今後に向けた課題も明確になりました。今回の経験を糧に、より円滑で再現性の高い開発プロセスを構築し、次のプロジェクトへとつなげていきたいと思います。