コスパ最強アーキテクチャT3-Turboを紹介する
はじめに
個人開発ほど零細規模でもなく、モジュラモノリスやマイクロサービスを使うほど大規模でもないが、小〜中規模な開発の際にT3-Turboアーキテクチャを使うことでコスパよくシステム構築できます。名前の由来はT3-StackとTurborepoになります。個人開発としては素晴らしいT3-Stackですが、T3-Stackではデメリットとなった密結合や拡張性の問題を、monorepoツールやサーバサイドを採用することで解消し、より大きなチーム開発でも対応可能になっています。
技術要素
2023年5月に行われたVercel Shipの中で、Vercel社がフルスタックな開発環境を目指していることがわかりました。このT3-Turboアーキテクチャでは、Vercel社が出している技術を中心に、それらと相性の良い技術を組み合わせて採用しています。
Turborepo
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)
NextJSはVercel社が出しているフロントエンドフレームワークです。App Router機能により、より直感的なルーティング、よりサーバーを活用したレンダリングが可能になりました。今後はPage Routerよりもこちらの開発に力を入れていくと思われます。
UI
T3-Stackでも採用されていたTailwindCSSを採用します。
続いて、UI Component LibraryはHeadlessなものを使います。HeadlessなUIとは、UI Componentを「機能」と「見た目」に分けそのうち機能のみを提供するというもので(見た目の部分はTailwindCSSが担う)、特にVercelが推しているSSRと相性がいいです。代表的なHeadless UI Component Libraryとして、Radix UIとMUI Baseがあります。
これで十分と言いたいところですが、どちらのライブラリも用意されているComponentは数が貧弱で(むしろ2つの用意されているComponentは被っている部分も少なく、併用したとしても少し不十分)、まだまだMUIやMantineといったメジャーなUI Libraryにも頼る必要がありそうです。NestJS(Nest-Graphile)
Typescriptを完全サポートしたNode系バックエンドフレームワークといえばNestJSです。加えてPostgraphileというライブラリを使用することで、GraphQL Engineによって簡単なCRUD処理は自動生成され、リゾルバまで自動で提供してくれます。
PostGraphileに関しては別記事で紹介しています。
GraphQL Federationというアプローチをとることにより、フロントエンドからは1つのGraphQL APIだけ取り扱い、複数のサービスを跨いでデータを取得するリクエストが可能になり、尚且つ型安全に開発を進めることができます。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がおすすめです。
Vercel PostgresはNeonDBをベースに作られていますが、まだまだ機能を再現しきれていない部分も多く(他のStorage系サービスも同様)、本家を使うと良いでしょう。NeonDBには以下のような特徴があります。- ServerlessなPostgresDB
- DBスキーマをブランチ管理できる
- VercelのPreview機能に合わせてNeonのブランチを切れる
また、ORMにはPrismaを使います。KyselyやDrizzleがあります。
PrismaはNode/Typescript専用のORMです。同様の他のORM候補として以下の手法でPrismaのデータスキーマ変更をNeonにMigrateします。
Storage
Vercel Blobの元になったCloudflare R2がおすすめです。
AWS S3互換で、低レイテンシ・高スループットを実現しています。Redis
Vercel KVの元になったUpstashがおすすめです。
Redisストレージ等を提供します。T3-Turboのメリット
- フロントもバックもフルTypescript構成なため、型安全で堅牢な上に、フルサイクルエンジニアの開発リソースを最大限効率的に活用できます。
- AWSやGCPといったパブリッククラウドを使わなずに済むため、インフラの運用管理コストを最小限に抑えられます。
- クエリや型の自動生成によって、開発効率が爆速になります。
T3-Turboの限界
これで中規模くらいまでのサービスなら対応可能でしょう。Nodeの限界がこのアーキテクチャの限界と言えそうです。これで限界ならIaaSへ移行や、モジュラモノリス/マイクロサービスの採用を検討した方が良いでしょう。
将来性
モバイルアプリ化に関して
モバイルアプリの開発によく使われるFlutterに関しては、Turborepoの管理対象外となります。Turborepoの管理可能な中では、Expo(React Native)が第一候補になります。
ただ執筆時点ではまだα版ですが、Tauri Mobileを利用することで、NextJSで構築したWebサービスをモバイルアプリ化する方法があり、こちらを検討した方が良いかもしれません。モジュラモノリス・マイクロサービスへの拡張
NextJSはフロントエンドの主流となり、NestJSもBFFとしてよく使われれる技術です。Turborepoでは管理できないものの、NsetJSをBFF化することで、他の言語のマイクロサービスを採用することができます。
まとめ
T3-Turboアーキテクチャで作った全体像が下図のようになります。(あくまで1例であり、プロダクトの要件によって最適なサービスを取捨選択してください)
まだまだ発展途上な部分はありますが、T3-Turboを使うことで、モダンな技術スタックかつ開発効率、保守性、拡張性に優れた開発体験を得ることができます。資金/時間などのリソースが限られている新規事業、スタートアップにとっても使い勝手が良く、Ruby on RailsやLaravelに変わる手段として今後主流になりそうです。
フィシルコムのテックブログです。マーケティングSaaSを開発しています。 マイクロサービス・AWS・NextJS・Golang・GraphQLに関する発信が多めです。 カジュアル面談はこちら(ficilcom.notion.site/bbceed45c3e8471691ee4076250cd4b1)から
Discussion