💨

コスパ最強アーキテクチャT3-Turboを紹介する

2023/08/01に公開

はじめに

個人開発ほど零細規模でもなく、モジュラモノリスやマイクロサービスを使うほど大規模でもないが、小〜中規模な開発の際にT3-Turboアーキテクチャを使うことでコスパよくシステム構築できます。名前の由来はT3-StackTurborepoになります。個人開発としては素晴らしいT3-Stackですが、T3-Stackではデメリットとなった密結合や拡張性の問題を、monorepoツールやサーバサイドを採用することで解消し、より大きなチーム開発でも対応可能になっています。

技術要素

2023年5月に行われたVercel Shipの中で、Vercel社がフルスタックな開発環境を目指していることがわかりました。このT3-Turboアーキテクチャでは、Vercel社が出している技術を中心に、それらと相性の良い技術を組み合わせて採用しています。

Turborepo

https://turbo.build/repo

Vercel社によって開発されている、Typescrpit/Javascriptに特化したmonorepo管理ツールです。メリットは以下になります。

  • Rust製+並列化でビルドが早い
  • Remote Cachingによって、ビルドキャッシュをチームで共有できる
  • T3-Stackの時にはNextJSと密結合だったモジュールを分割できる

以下にフォルダ構成の例を示します。

t3-turbo
|   - apps
|     | - web       //NextJS
|     | - api       //NestJS
|   - packages
|     | - auth      //AuthJS
|     | - config    //Tailwind, eslint
|     | - database  //Prisma
|     | - tsconfig  //Typescript
|     | - ui        //UI Component
|   - package.json
|   - pnpm-lock.yaml
|   - turbo.json

Turborepoの細かい使用方法はここでは説明しませんが、appsフォルダの下にアプリケーションを、packagesフォルダの下にモジュールを配置しています。まとまったをモジュールとして切り出すことで、密結合を防ぎ、クリーンな設計に落とし込むことができます。

NextJS(App Router)

https://nextjs.org/
NextJSはVercel社が出しているフロントエンドフレームワークです。App Router機能により、より直感的なルーティング、よりサーバーを活用したレンダリングが可能になりました。今後はPage Routerよりもこちらの開発に力を入れていくと思われます。

UI

T3-Stackでも採用されていたTailwindCSSを採用します。
https://tailwindcss.com/

続いて、UI Component LibraryはHeadlessなものを使います。HeadlessなUIとは、UI Componentを「機能」と「見た目」に分けそのうち機能のみを提供するというもので(見た目の部分はTailwindCSSが担う)、特にVercelが推しているSSRと相性がいいです。代表的なHeadless UI Component Libraryとして、Radix UIとMUI Baseがあります。
https://www.radix-ui.com/
https://mui.com/base-ui/
これで十分と言いたいところですが、どちらのライブラリも用意されているComponentは数が貧弱で(むしろ2つの用意されているComponentは被っている部分も少なく、併用したとしても少し不十分)、まだまだMUIやMantineといったメジャーなUI Libraryにも頼る必要がありそうです。

NestJS(Nest-Graphile)

https://nestjs.com/
Typescriptを完全サポートしたNode系バックエンドフレームワークといえばNestJSです。加えてPostgraphileというライブラリを使用することで、GraphQL Engineによって簡単なCRUD処理は自動生成され、リゾルバまで自動で提供してくれます。
https://www.graphile.org/postgraphile/

PostGraphileに関しては別記事で紹介しています。
https://zenn.dev/ficilcom/articles/invitation-to-postgraphile

GraphQL Federationというアプローチをとることにより、フロントエンドからは1つのGraphQL APIだけ取り扱い、複数のサービスを跨いでデータを取得するリクエストが可能になり、尚且つ型安全に開発を進めることができます。GraphQL Federationについてはマネーフォワードさんのテックブログで詳しく解説されています。
https://moneyforward-dev.jp/entry/2021/06/30/graphql-federation/

PostGraphileで簡単なCRUD処理を行い、それ以外のリクエストに関しては、NestJSの実装を通して対応します。(以下、この方法をNest-Graphileと呼びます)

似たような方法として、HasuraとNestJSを併用してバックエンドを構築する方法があります。こちらはフロントエンドからの最初のリクエストをHasuraが受け取り、簡単なCRUD処理はそのままHasuraで処理し、それで対応できない場合はRemote Schema機能を使ってNestJSに流すというアプローチを取ります。
Nest-Graphileなら1つのサーバーでどちらも処理することがきます。

Hasura + NestJSの場合

Nest-Graphileの場合

Nest-Graphileはコンテナとしてデプロイする必要があるため、AWSやGCP以外で、コンテナ用のPaaSサービスを使います。Tokyo Regionがあるという点でfly.ioがいいと思いますが、個人的なおすすめはKoyebです。

Database

Vercel Postgrasの元になったNeonDBがおすすめです。
https://neon.tech/
Vercel PostgresはNeonDBをベースに作られていますが、まだまだ機能を再現しきれていない部分も多く(他のStorage系サービスも同様)、本家を使うと良いでしょう。NeonDBには以下のような特徴があります。

  • ServerlessなPostgresDB
  • DBスキーマをブランチ管理できる
  • VercelのPreview機能に合わせてNeonのブランチを切れる

また、ORMにはPrismaを使います。
https://www.prisma.io/
PrismaはNode/Typescript専用のORMです。同様の他のORM候補としてKyselyDrizzleがあります。

以下の手法でPrismaのデータスキーマ変更をNeonにMigrateします。
https://neon.tech/docs/guides/prisma-migrate

Storage

Vercel Blobの元になったCloudflare R2がおすすめです。
https://www.cloudflare.com/ja-jp/developer-platform/r2/
AWS S3互換で、低レイテンシ・高スループットを実現しています。

Redis

Vercel KVの元になったUpstashがおすすめです。
https://upstash.com/
Redisストレージ等を提供します。

T3-Turboのメリット

  • フロントもバックもフルTypescript構成なため、型安全で堅牢な上に、フルサイクルエンジニアの開発リソースを最大限効率的に活用できます。
  • AWSやGCPといったパブリッククラウドを使わなずに済むため、インフラの運用管理コストを最小限に抑えられます。
  • クエリや型の自動生成によって、開発効率が爆速になります。

T3-Turboの限界

これで中規模くらいまでのサービスなら対応可能でしょう。Nodeの限界がこのアーキテクチャの限界と言えそうです。これで限界ならIaaSへ移行や、モジュラモノリス/マイクロサービスの採用を検討した方が良いでしょう。

将来性

モバイルアプリ化に関して

モバイルアプリの開発によく使われるFlutterに関しては、Turborepoの管理対象外となります。Turborepoの管理可能な中では、Expo(React Native)が第一候補になります。
https://expo.dev/
ただ執筆時点ではまだα版ですが、Tauri Mobileを利用することで、NextJSで構築したWebサービスをモバイルアプリ化する方法があり、こちらを検討した方が良いかもしれません。
https://tauri.app/blog/2022/12/09/tauri-mobile-alpha/

モジュラモノリス・マイクロサービスへの拡張

NextJSはフロントエンドの主流となり、NestJSもBFFとしてよく使われれる技術です。Turborepoでは管理できないものの、NsetJSをBFF化することで、他の言語のマイクロサービスを採用することができます。

まとめ

T3-Turboアーキテクチャで作った全体像が下図のようになります。(あくまで1例であり、プロダクトの要件によって最適なサービスを取捨選択してください)

まだまだ発展途上な部分はありますが、T3-Turboを使うことで、モダンな技術スタックかつ開発効率、保守性、拡張性に優れた開発体験を得ることができます。資金/時間などのリソースが限られている新規事業、スタートアップにとっても使い勝手が良く、Ruby on RailsやLaravelに変わる手段として今後主流になりそうです。

フィシルコム

Discussion

Hidden comment