※ こちらはミツモアAdvent Calendar 2022の1日目の記事です。
こんにちは、ミツモアCTOの柄澤(@fmy)です。来年に引き続き今年もアドベントカレンダーをやっていきたいと思います!去年の記事も面白いものがあるので是非ご覧ください。
今回は、去年末から開発している新規プロダクトである「MeetsOne」で使われている技術についてご紹介しつつ、開発開始時の技術選定の中でどのようなことを考えていたかを備忘録的に書いていけたらと思います。
実際に導入した技術スタックは以下のようになっています。
サーバサイド関連
- TypeScript(Node.js)
- NestJS
- Prisma
- OpenAPI
- Jest
フロントエンド関連
- Next.js(React)
- Material UI
- RTK Query
- React Hook Form
- Yup
- FullCalendar
- Dayjs
- Jest
- Storybook
インフラ関連
- AWS ECS(fargate)
- AWS Aurora
- AWS S3
- imgix
- Datadog
- Sentry
- Launchdarkly
技術選定の視点
自分が技術選定をする上での判断軸は、主に次の3つとなっています。
- 技術自体の機能や設計方針、発展性
- 実現したいビジネス要求に対する適正度合い
- 社内のエンジニアのスキル、採用市場での人気といった人的リソースに関する部分
まず1つ目の技術自体に関してチェックするのは、その言語やライブラリの作者の考え方や設計方針です。有名なものは大体公式サイトやGithubのREADMEにoverviewが載っていたりするので、どういうモチベーションで作られたのか何を実現したくて作られたのか確認することができます。IssuesやPRの対応体制やどのような課題があるかも把握します。導入したライブラリは短くても3年は使うと想定しているべきなので、ちゃんとメンテされているのか、セキュリティ対応しているのか知っておく必要があります。新しすぎたり、マイナーすぎたりするものは基本選択しません。
2つ目はビジネス要求に対する適正度やコスパです。技術というのはビジネス要求を実現するための手段であってそこに目を向けないと痛い目を見ることになります。MeetsOneにおいてはある程度汎用的なwebアプリケーションでありますが、ToBのSaaSであるということは大きな特徴です。DBをマルチテナントにするのかどうか、トラフィックとユニークユーザー数がToCに比べて大幅に少なくなる点などを考慮に入れつつインフラ周りを考える必要があります。
3つ目の社内エンジニアのスキルや採用市場での人気という観点は意外と考慮されないのかもしれません。しかしプロダクトによっては一番重要視するべき場合もあります。アプリケーション開発はチーム戦であり、一定の規模を越えると複数のチームを跨った組織戦になってきます。素早い立ち上げのためにも、規模を大きくしていく面でも人が集められることはとても大事です。単純化して話すと、半分の人気の技術を採用すると、エンジニアを集めるのが2倍難しいことになります。
技術選定のプロセス
既存プロダクトに対して技術選定をするときは、まず以下のことをはっきりさせます。
- 解決したい問題
- 既存技術でなぜそれが解決できないのか
- 複数の候補とそのメリデメ
この辺りをドキュメントにまとめて、議論をして決定します。社内の他のメンバーにもそうしてもらっております。
ただ一番最初にプロダクトを立ち上げる時には、既存のシステムに対する明確な問題意識があるといった状況ではないので、上記の視点で一通りの選定はしてしまいます。技術選定にはある程度時間をかけるべきですが、実際に作り始めてみないとわからないこともあります。
ここで注意すべきなのは規模が大きくなりすぎる前にチェックをすることです。実際にMeetsOneでも開発し始めて早い段階で入れ替えを決定したものがあります。早い段階で判断した方が移行コストも少ないですし、リリース前であると尚良いです。
各技術に関して
TypeScript
TypeScript: JavaScript With Syntax For Types.
ミツモアで一番主流な言語であり、BE/FEの両方をTSで書くことが多いです。 meetsmore.com の方もBE/FEともにTypeScriptとなっています。
MeetsOneでもTSを選択しました。この選択はあまり迷うことはなく決定しています。既存エンジニアのスキルがそのまま活かせる点、meetsmore.com を作ってきた上での反省点などのフィードバックをできる点からもTSを選んでいます。
Prisma
Prisma | Next-generation ORM for Node.js & TypeScript
Node.js向けのTypeScript完全対応のORMで、データベースからサーバサイド、フロントエンドまで一貫して型安全なコードを書くためのベースとなっています。類似ライブラリと比較すると新しいですが開発が盛んで、コミュニティのpluginが多くあるのも特徴です。
導入する上で比較したものはTypeORMです。Prismaを選ぶ決め手になったのはこの箇所です。selectしたフィールドに応じた型が生成されるので、真に安全なコードとなります。
OpenAPI & RTK Query
RTK Query Overview | Redux Toolkit
MeetsOneではNestJSのrequest bodyやresponse bodyのDTOをもとに、型情報を含むswagger.jsonを生成しています。その情報をもとに@rtk-query/codegen-openapiを用いてRTK Queryのhooksを自動生成しています。これによりFEで不正な型のrequest bodyを渡すとエラーになりますし、返ってきたresponse bodyの型の情報も明らかです。この部分の詳細は長くなるので他のメンバーの記事に譲ります。
Yup
GitHub - jquense/yup: Dead simple Object schema validation
FEのバリデーションのライブラリです。人気がありエラーメッセージの多言語対応も備えています。schema定義からの型生成もあります。
比較としてはZodが最有力です。Zodは比較的新しいライブラリで活発に開発が行われているので将来的に移行する可能性はありそうです。
FullCalendar
FullCalendar - JavaScript Event Calendar
カレンダーUIのライブラリです。5年前に meetsmore.com のカレンダーを実装するときは独自実装をしました。ただ今回のビジネス要件として様々なビューでカレンダーを見たいというものがありましたが、その部分がMeetsOneのコアとなる部分でもないので、有料のライブラリを使う方針にしております。
MeetsOneの技術選定にあたっては、場合によってはお金を使って適切なショートカットをするという考えがあります。開発の人的コストは冷静になって考える必要があります。
これから
上でも例に挙げた通り、プロダクトが利用する技術の見直しは適切なタイミングで行っていく必要があります。ただやみくもに新しい技術を導入するのはもってのほかで、コストとメリットを比較し慎重に行わなければなりません。使っている技術は遅かれ早かれ必ず陳腐化していく運命にあるので、メンテナンスが止まったり負債を産みやすい作りになっている場合は勇気を持って切り替えることも大切です。
開発が進んでいってどんどん機能が充実しているMeetsOneですが、さらに技術的にチャレンジングなものがプロダクトロードマップに控えているので追加での技術選定が順次必要になっていきます。技術選定の如何が将来の負債の量に繋がるので、日々アンテナを張って最適な技術を模索していきたいと考えています。
最後に
ミツモアではエンジニアの誰もがこういった議論に参加したり、提議したりする文化があり、Github discussionsやNotionで設計やツールの選定を話しあうことができます。ご興味がある方はぜひ気軽に面談しましょう。下記のリンクから、もしくはtwitterのDMでもOKです!