👻

Amplify で複数のアプリケーションを運用し、同一ドメインでアクセスできるようにした話とその背景について

2022/10/21に公開約5,000字

はじめに

どうも、こんにちは。 @hayata-yamamoto です。

Amplify でプロダクト開発をしているチームは多くなってきました。フロントエンドのホスティング環境として利用してもいいし、バックエンドやストレージなど複数のリソースを同時に Amplify で管理しながら、丸っと全てのアプリケーションを Amplify で運用するパターンも増えているように思います。

今回は、弊社がリポジトリや開発組織をどのように考えているかをお話ししながら、その一例として Amplify で複数のフロントエンドアプリケーションをホスティングしている方法を紹介します。また、どうしてそのような決定を行ったのかについて紹介します。

リポジトリと開発組織のあり方

弊社は現在、さまざまなことを検討した結果、 リポジトリと開発組織の実態が 1:1 で対応することを重視して考え、以下のようなリポジトリと開発組織の関係を設定しています。以下に紹介するメリット・デメリットを踏まえ、弊社は以下のような体制をとっています。

マルチレポのメリット・デメリット

リポジトリを別に分けると、依存する外部のサービスと疎にアプリケーションを保ち、独立して動くことにインセンティブが働き、関心が分離されます。開発する当事者からすると、検討に含めないといけない領域が小さくなる分、検討コストは下がります。

一方で、依存するサービスへの理解や関心を保つのが難しくなります。インターフェースを明確に定義し、そのインターフェースをなるべく変えない状態で開発をすることが求められます。ゆえに、システムの要求や要件が確定的で、変化し得ないサービスには向きます。

リポジトリが全く別に切り出された、マイクロサービスを開発しているチームは、組織体制としても独立して動けるようなチームの持ち方が望ましいのは言うまでもありません。他のシステムのことは考えず、そのシステムのパフォーマンスや品質、運用改善にフォーカスできる体制を整えていくべきです。他のアプリケーションのことも知りながら開発をする体制を整えた場合、やや実態と組織体制がチグハグな関係性になり、開発する際には動きにくさを感じる要因となってしまいます。

モノレポのメリット・デメリット

モノレポではシステム間の依存をゆるく残したまま、ある程度システム間の関係性を頭に入れながら実装をすることが求められます。単純に考えると、考慮しないといけない事項は同じリポジトリに包含されるプロダクト分増え、思考コストがかかります。よくあるパターンは、プロダクト単位で開発をする体制ですが、モノレポにまとめる粒度は千差万別で、意味ある単位でまとまっていればよいでしょう。

思考コストが増えるデメリットがある一方で、あるプロダクトが提供するユーザーストーリーを一つのリポジトリ内で完結できるメリットがあります。例えば、バックエンドの改修を伴う新機能追加を行う際、「提供したいユーザーストーリーが満たせるか」を 1 つの PR で確認することができます。その時、フロントエンド・バックエンドどちらかに変更の必要が生じても、同じ PR に変更が含まれているおかげで一つのブランチに集中して開発を行えます。

それゆえ、ユーザーストーリー中心に開発を行う開発チームの場合、モノレポの方が望ましい場合も多くなります。仮に、エンジニア同士の専門性にばらつきがあったとしても、分業しながら一つのユーザーストーリーの実現に向けて開発を行うことができます。

アプリケーションが大きくなってきたり、複数のプロダクトを複数人が開発するようになってくると、開発チームの組織体制や開発フローの整備に頭を悩ませることも増えてきます。レビューの仕方や、コーディング規約、デプロイの自動化や、システム間の連携・調整、など悩むべきトピックはさまざまです。

今回はその中でも、開発組織とリポジトリ運用 はどの開発チームでも悩むテーマではないでしょうか?モノレポにするのか、マルチレポにするのか、はたまた別の形でリポジトリを持つのか、など議題はたくさんあるし、結局価値観の問題や好みの問題になってしまう議論もたまに目にします。

実際、私もこの半年くらい右往左往しながら検討してきました。どちらにも、メリット・デメリットがあり、また組織の中でどういう目的意識や目指す目標があるかによっても変わってきます。あるべきの議論をしていても、物事は先に進んでいかないですし、将来変わるかもしれないことを織り込みつつ、その時に最適な意思決定をしていくことが求められるテーマです。あくまで、現時点での最適な形であり、将来必ず変わることを見越して、今最適なものを作りすぎずに置いています。

なぜ複数のフロントエンドアプリケーションを管理運用しているのか?

フロントエンドアプリケーションのリプレイスを実施しているからです。

スローガンとしては、"Goodbye React.js, Welcome Next.js" と言った感じで、既存の React ベースで書かれたフロントエンドから、Next.js をベースにしたフロントエンドアプリケーションに移行しています。(エンジニアでプロジェクトチームを組んで、PM を立ててプロジェクトを推進しています)

この意思決定も簡単なモノではありませんでしたが、この記事で書いてしまうとそれだけで字数を食ってしまうので今回は割愛します。ざっと言えば、Next.js のようなより細かい機能と仕様を備えたフレームワークに乗っかることで、フロントエンドのチームが本質的に重要な作業にフォーカスできるようにしたいと考えての判断をしています。

実際どのように行ったか?

複数の Amplify アプリケーションの前段に CloudFront を新しく配置し、ビヘイビア機能を用いてパスベースの置き換えを実施しています。弊社の場合は、 /next パスに来たら新しいアプリケーション、それ以外は旧来のアプリケーションにアクセスが仕分けられるように設計し、サービスを提供しています。

アーキテクチャ画像

上記の構成を実現するために、Amplify 側でも以下の2点を実施しました。

  1. Amplify が作成する透過的な CloudFront を無効化し、DNS 上の CNAME を切り替えること
    1. 一時的なサイト停止が発生するので注意
  2. 複数の Amplify のアプリケーションを main ブランチなど本番用のブランチで自動構築できるよう CI/CD を再設定すること

Amplify の CloudFront から 新規作成した CloudFront への置き換え

以下のような手順で対応を実施しました。
弊社の場合、インフラリソースは原則 Terraform でコード管理しており、手順には Terrform 特有の対応も含まれています。

Amplify CI/CD の yaml 修正

Amplify のモノレポビルドのドキュメントを参考に、以下のような amplify.yml をリポジトリルートに配置しています。このように記載することで、対応する Amplify アプリケーションのビルドを GitHub 上で管理できるようになります。

version: 1
applications:
  - appRoot: app1
    frontend:
      phases:
        preBuild:
          commands:
            - yarn install
        build:
          commands:
            - yarn run build
      artifacts:
        baseDirectory: out
        files:
          - "**/*"

  - appRoot: app2
    frontend:
      phases:
        preBuild:
          commands:
            - yarn install
        build:
          commands:
            - yarn run build
      artifacts:
        baseDirectory: build
        files:
          - "**/*"

終わりに

今回は、弊社がリポジトリや開発組織をどのように考えているかをお話ししながら、その一例として Amplify で複数のフロントエンドアプリケーションをホスティングしている方法を紹介しました。

この記事や弊社に少しでもご興味持っていただけたら、是非カジュアル面談などにお越しください!

https://herp.careers/v1/todoker

参考

Discussion

ログインするとコメントできます