GVATECHブログ
🦧

事業を起点に考えるプロダクト立ち上げ時の技術選定と開発体制

に公開

GVA TECH株式会社でエンジニアをしているYorintonと申します。
初めての記事投稿です。
今回は、私が立ち上げから担当している『OLGA』というプロダクトの『法務データ基盤モジュール』について、プロダクト立ち上げ時の技術選定と開発体制の構築の考え方をご紹介します。

この記事の目的

  • OLGAの法務データ基盤の開発チームが技術だけでなく事業からブレイクダウンして技術選定や開発体制の構築を行なっている、ということを知ってもらいたい
  • 技術の特性だけでなく、事業や組織も技術選定に大きな影響を及ぼすということを知ってもらい、これから技術選定する人の参考にしてもらいたい
  • 技術そのものだけでなく事業への貢献(技術と事業の紐付き)を意識している(意識していきたい)エンジニアに興味を持ってもらいたい

この記事の前提

  • この記事は弊社が運営するOLGAの法務データ基盤モジュールの立ち上げ時期(2021年7月時点)でどのような考え方で技術選定を行ったか、を記載しています
  • 上流からブレイクダウンしていく考え方を提示することを重視しており、1つ1つの技術についてはざっくりとした記述に留めています
  • 立ち上げ当時はエンジニアは私一人でスキルセットや経験値は以下のような感じでした
    • エンジニア歴: 3年ちょい
    • 言語: PHP / TypeScript / JavaScript
    • フレームワーク: Laravel / CakePHP / Vue.js
    • インフラ(クラウド): AWS
    • 開発環境: Docker
    • データベース: MySQL

今回の記事の対象となるサービス概要

OLGAの法務データ基盤モジュールという、企業の法務案件の受付・管理を効率的に行い、過去の法務案件をナレッジとして活用できるサービスです。
https://gvamanage.com/about-olga/database/

企業の法務部が主なターゲットになるためtoCのサービスのような膨大なトラフィックやCMなどによるスパイクが想定されるようなプロダクトではありませんでした。
逆に、セキュリティやデータの整合性(案件ステータス管理など)は重視されることが想定されました。

前提となる事業状況

まずは、立ち上げ当時の事業状況について整理しようと思います。
プロダクトの立ち上げ当時は以下のような事業状況でした。

  • DX化の流れに乗って法務領域のDXも注目され徐々に市場も伸び始めていた
  • 弊社のエンタープライズ向けの主力サービスはAI契約レビューサービスのみだった
  • AI契約レビューにおいて競合には大きな差をつけられていた
  • AI契約レビューは法務部の業務フローの中では「点」のサービスであり、業務フロー全体をカバーするような強い競合サービスはまだ無かった
  • CEOによるユーザー企業などへのインタビューにより、法務案件の受付・進捗管理・ナレッジの活用に大きな課題があることがわかっていた

当時の事業方針

当時の状況を踏まえ、事業の方向性として以下のようなことが考えられていました。

  • AI契約レビューという「点」のサービスでこのまま戦い続けても逆転は難しいため、まだ強い競合のいない法務案件の受付・進捗管理・ナレッジ活用という業務フロー全体を抑えるサービスを早期に投入することでシェアを取る
  • その上で自社のAI契約レビューサービスとの連携を強めることで、先行されたAI契約レビュー領域もひっくり返す

プロダクト立ち上げ初期の方針

上記の事業方針を実現するために、プロダクト立ち上げは以下のような方針で進めることになりました

  • まずは数社のパートナー企業向けにクローズドでプロダクトを提供(ベータ版)し他社が簡単には追いつけないくらいブラッシュアップする
  • プロダクトがブラッシュアップ出来たら正式リリースして一気にプロモーションや営業をかけて素早くシェアを取る

事業方針・プロダクト立ち上げ方針を実現するための組織の方針

上記の事業やプロダクト立ち上げの方針を実現するため、以下のような方針で組織作りを行うことになりました。

  • スピード感を持って柔軟に動けるよう、少数精鋭チームを構想
    • 立ち上げ時はCEO、デザイナー1名、エンジニア1名の3名
    • その後追加で2名までエンジニア採用予定
  • チーム内での情報の非対称性を無くし質が高く建設的な議論を行えるようにする
    • エンジニア含め全員でユーザーインタビューを行い全ての一次情報を共有する
    • デイリーでMTGを開き情報共有や要件などに関する議論を密に行う

開発面で重視したポイント

上記の方針を踏まえ、開発面において重視したいポイントを洗い出しました。
技術選定や開発体制構築の目的を突き詰めると結局は「事業を成功させること」だと思うので、重視するポイントは事業方針やプロダクト立ち上げの方針に大きく関わっています。

  • 早期にクローズドベータを始めるためのスピード重視の開発
  • 最低限エンタープライズ企業向けに導入してもらえるくらいのセキュリティ要件の充足
    • セキュリティ面の問題で導入すらしてもらえなかった場合、そもそもクローズドベータでブラッシュアップすることすら出来ないため
  • クローズドベータ版でのインタビューと改善のサイクルをスピード感を持って回していくための要件変更や機能追加への柔軟な対応
  • 案件管理におけるステータスなど仕様が複雑な部分のデータ整合性を担保する

特にスピードとセキュリティの両立はかなり頭を悩ませましたが、既存サービスのセキュリティチェックシートをベースに最低限対応する項目を事前にビジネスサイドとすり合わせて、必要以上に工数をかけないようにしました。
また、AWSのマネージドサービスを活用して低い実装コストでセキュリティ要件を実現することが出来ました。

技術選定や開発体制の構築で意識したこと

開発面で重視したポイントを実現するため、さらに以下の点を意識して技術選定や体制構築を進めました。

1.オーバーエンジニアリングを避ける

  • 例えば、長期を重要視して短期を蔑ろにした結果長大なシステムになってしまった場合、そもそも短期目標を達成出来ずに想定していた「長期」のタイミングすら訪れない可能性があります。中長期もある程度は意識しつつもそこにばかり捉われず、短期目標をしっかり実現できる技術選定を行った上で中長期も一定意識する、くらいの温度感が良いと考えました

2.ボトルネックを作らない

  • 短期的にスピードを出す必要がある以上、何かボトルネックになる可能性のある要素は可能な限り排除するよう意識しました

3.極力慣れている技術を使う

  • 少なくとも1人目エンジニアである自分がパフォーマンスを出せる、と言える選定を意識しました。自分が全く知見がない技術だと他のエンジニアが入ってきた時に、本当に適切な設計・実装か、オーバーエンジニアリングになっていないか、などを判断が出来ないと考えたためです

4.コミュニケーションコストを最小限にする

  • 組織戦略のところで述べたように、一次情報を共有し質の高い議論をしたいと考えていました。逆に言うと事業成長にとって重要ではなく避けられるコミュニケーションコストは極力避けられるようにしようと考えました

5.一定の技術負債を許容しつつ、最低限の保守性や変更容易性を担保する

  • 技術的負債をゼロに抑えるというのはエンジニア視点では理想ではありますが、事業を最速で進めながら技術的負債を完全に無くすことは現実的に難しいと考えました。むしろ技術的負債が一定発生することをエンジニア全員が理解・許容しつつ、可能な範囲でコントロールすることを意識する、という考えの方が精神衛生上も良いですし、事業スピードを無駄に毀損しなくて済むのではないかと考えました

6.技術選定自体にコストをかけずぎない

  • 例えば1つ1つのライブラリの細かい選定まで厳密に行うといくら時間があっても足りないですし、プロダクト立ち上げまでの猶予も限られていたため、重要な技術要素についてはある程度調査を行いつつも時間をかけすぎないよう意識しました

7.セキュリティ・データ整合性など重要な点はある程度コストをかける

  • スピード重視といいつつも、上述の通りセキュリティやデータ整合性は短期的な目的を達成する上でも重要になってくる要素だったため、ここには一定コストがかかっても慎重に対応する必要があると考えました

また、今回の技術選定における最悪の失敗についても考えました。
最悪の失敗技術選定の失敗が原因でビジネス上求められるスケジュールから大幅に遅れ、競合に先行されシェアを取られることだと考え、それだけ絶対に避ける技術選定・開発体制にしようと考えました。

具体的な技術選定・開発体制

これまで述べてきた前提条件や重視する点などを踏まえて具体的には以下のような技術選定を行いました。
記載しているものよりはもう少し詳しく調査・検討しましたが、今回は事業から技術・開発体制までのブレイクダウンのイメージをシェアすることが目的なのであまり詳しくは書いておりません。
また、以下に挙げるもの以外でも初期段階で決めたことがいくつかありますが、今回は割愛させていただきます。

開発体制

開発体制は、1人のエンジニアが一つの機能に関わる全て(フロント・バックエンド・インフラ)を実装する体制にしました。
(基盤となるインフラは私が一人で構築しました)
職能で役割を分担する体制もあり得たと思いますが、このような体制にした理由は以下になります。

1.どんなエンジニアを採用できるか分からない以上、職能毎に分ける場合に以下のリスクが致命的になる可能性があった

  • 職能間のコミュニケーション(API仕様の議論など)に大きな時間がかかるリスク
  • 他領域への理解不足による領域間の精神的なコンフリクトやそれに伴う仲裁コストが発生するリスク
  • 少数精鋭を前提としていたため、各領域1名ずつとした場合どこかの領域がボトルネックになってリカバリが不可能になるリスク

2.1つの機能を一人のエンジニアが責任を持って開発する体制にすることでその先にある顧客課題にまで視点が向かうようにしたかった

  • 技術領域に閉じると「自分の領域の実装を行うこと」が仕事になり、その先にある顧客課題や事業成長にまで考えが及びづらくなる可能性があると思った
  • エンジニアが顧客課題やその先の事業上の目的まで意識することで、目的に即したより良いコストのかからない方法を提案できる可能性があると思った

レビュー体制

以下の理由でコードレビューは実装者以外の2名で行うことにしました

  • 全員が全体のコードの把握できる状況を作っておいた方がお互いカバーしやすい
  • まだ少数なのでその状況が現実的に作れる

また、テーブル設計レビュー、インフラ設計レビュー、エンドポイント設計レビューはエンジニア全員で行うことにしました。
特にテーブル設計、インフラ設計はプロダクト全体に関わるため保守性や堅牢性などを一定担保したかったのと、設計レビュー段階で各々がどんな機能を実装するかを把握できるため、その後のコードレビューがやりやすいと考えました。

プロダクトの構成

以下の理由でSPAの構成にしました

  • 1人目エンジニアだった私が一番慣れている構成を採用
  • SaaSでありLPとプロダクトは別れているため、プロダクト自体にSEO対策は必要無かった
  • 初回読み込みがめちゃくちゃ重視されるわけでも無かった

フロントエンド

Vue.js 3 / TypeScriptにしました。
ここは素直に自分が一番慣れていてパフォーマンスを発揮できる構成を採用しました。
また、簡単に環境構築できそうだったViteを採用しました。

ちなみに、フロントエンドのコンポーネント構成はAtomic Designを採用しました。
当時知名度があったのと、atoms、molecules、organisms、pagesなどの役割やルールを明確に定義しておくことで一定保守しやすいコンポーネント構成になると考えたためです。

バックエンド

バックエンドは正直PHPが慣れていましたが、以下のような理由でNode.jsを選定しました。

  • フロントとバックエンドを共通の言語にすることで最悪TypeScriptが出来ればOKという状況にし、エンジニア採用のハードルを下げたかった
  • 自分がTypeScriptには慣れていた
  • 完璧ではないものの型安全にできる
  • フロントとバックエンドをTypeScriptで統一してモノレポにすることでAPI仕様のinterfaceをフロントとバックエンドで共有できる
  • サーバー側でものすごくCPUを消費するようなCPUバウンドな処理が必要になるようなプロダクトではなかった

また、以下のような理由でフレームワークにはNestJSを採用しました。

  • 短期的なスピードが重視されていたので、フレームワークはフルスタック寄りのものにしたかった
  • NestJSはモジュール間の分離などの仕組みもあり、NestJSのお作法に則れば一定保守性や変更容易性も担保できそうだと思った

コードのアーキテクチャとしては基本的にはNestJSの構成に従いました。
ただ、案件のステータスや担当者など案件に関連するデータは仕様が複雑であり整合性の担保が重要だったので、そこだけドメインモデルに切り出して各ユースケースで再利用しやすい構成にしました。

データベース

マルチテナント構成における企業間のデータ分離方式でRLS(Row Level Security)を使いたかったため、PostgreSQLを選定しました。
クエリの書き方には大きな違いはないため特に大きなキャッチアップコストはかからなそう、と判断しました。

マルチテナントにおける企業間データ分離の方式は他にDBの分離やスキーマ分離、テーブル分離などいくつかありますが、企業ごとにテーブルやスキーマを変更する必要がなく、既存のORMやマイグレーション機能を活用しやすいため、他の分離方式と比較して実装コストを抑えられると考えました。

ORM

TypeScriptのORMはいくつかありましたが、新しく勢いのあるPrismaと長く運用してきて安定しているTypeORMで比較しました。
ここはちょっと悩みましたが、新しいとはいえドキュメントが充実しておりコミット頻度も高く、TypeORMよりも型安全に使えるなどメリットも大きかったPrismaを採用しました。

インフラ

パブリッククラウド

ここは素直に自分が一番慣れていてパフォーマンスを発揮できるAWSを採用しました。

フロントエンドサーバー

構築やデプロイが簡単で最速でリリース出来そうだったAWS Amplifyを採用しました。

バックエンドサーバー

以下のような理由でECS / Fargateを採用しました。

  • ECSによるコンテナ運用についてはある程度知見があった
  • Fargateによってインフラストラクチャ部分をマネージドにしてreadOnlyRootFileSystemにすることで比較的コストをかけずに一部のセキュリティ要件を満たすことが出来た

技術選定に対するざっくりとした振り返り

結果的にかなりタイトなスケジュールではありましたが、ビジネスサイドが求めるスケジュールでリリースが出来、早期のブラッシュアップやリリース後のグロースに貢献できたかなと思います。
ただ、これは技術選定だけが要因だとは思っていません。
その後の実行フェーズでの1つ1つの判断を、技術的な事情だけでなく事業状況を踏まえて総合的判断してきたことやチームメンバー1人1人が事業目的を達成するために粘り強くやり切った、という点が大きいと思っています。

正直、技術選定などの初期の選択においては、大きな失敗はあっても大きな成功は無く、結局何かしらトレードオフが発生し、何かを得る代わりに何かを捨てる決断になるかなと思っています。
その前提で考えると、今回の選定は大きな失敗はなく、比較的マシな選定だったかなと思います。

以下1つ1つの技術選定や体制に対する振り返りです。

  • SPA、AWS、Vue.jsについては慣れていたので立ち上げをスピーディーに進められました。また、現在時点で特にこの選定によって困った、ということはありませんでした。
  • RLS・PostgreSQLの選定も最初に多少のキャッチアップは必要でしたがそこまで大きなコストではなく、運用コストも比較的小さく抑えられたかなと思います。
  • Prismaは途中メモリリークの問題が発生し、定期的にサーバーの再起動が必要になった時期がありました。ここはPrismaの改修を待たざるを得ませんでしたが、Prismaはかなり積極的アップデートを重ねており比較的早期に不具合が解消されたかなと思っています。
    また、selectで取得するレスポンスに対しても型付けしてくれるので実装の際の扱いやすさがあったり機能追加も早くどんどん便利になっている印象があり、総合すると採用して良かったなと思っています。
  • 一人がフロント・バックエンド・インフラ含めて一気通貫で実装する体制ではボトルネックが発生することはありませんでした。コミュニケーションも必要なコミュニケーションにフォーカス出来たかと思います。一つの機能を実装するのにかかる時間は当然職能で分担するよりも大きくなりますが、立ち上げまでの期間でも実装した機能がかなり多かったため、複数機能を並行で進められた点は良かったかなと思っています。
  • バックエンドで一部ドメインモデルを作る構成については、ドメインモデルの再利用によりある程度データ整合性は担保しやすくはなりましたが、ドメインモデル自体がファットになってしまい可読性が低下するなどの弊害がありました。ここはモデリングに適切に時間を割いて検討すべきだったと反省しています。
  • 技術選定自体というより、その後の実行フェーズで短期的なスピードと長期的な品質を両方完全に担保していくのはやはり難易度が高いなと感じました。各種レビューなどで一定の品質は担保出来たとは思いますが、ドメインの複雑性も相まって一定の技術的負債は発生したかなと思います。ただ、最初に一定の技術的負債を許容する、という前提を共有出来たのは良かったと思っています。これによって短期的なスピードと長期的な品質の間でどちらを優先するか、といった議論に必要以上に時間を割かずに済んだと思います。
  • 逆にスピーディーにプロダクトの立ち上げを行えたことで、ビジネス的な負債(無理な営業で後からチャーンが大量発生する、競合に覆せない程の差をつけられる、資金調達出来ず採用に投資出来ない..etc)は回避出来たのは良かったと思います。

技術選定以外で良かったところ

技術選定と直接は関係ないかもしれませんが、エンジニア採用はかなり成功だったなと考えています。
最初に採用したのは2名のエンジニアでしたが、2名ともビジネスやプロダクトに対して積極的に意見をくれたり、理性的で建設的な議論ができる人でした。
そのため、無駄なことに時間を使わず本来向き合うべき課題にフォーカスすることが出来たと思います。

ちなみに、その2名は立ち上げから約4年経過した今も関わってくれていて多大な貢献をしてくれています。
極論ですが、結局人が良ければ技術選定は何でもうまくいくんじゃないか?とも思っていたりいなかったりしますw
(もちろん最初の2名の後にチームに入ってくれた人も良い人が多かったのですが、今回はプロダクトの立ち上げ期の話なのでその時に入ってくれた2名に対して言及してます)

まとめ

初回はOLGAの法務データ基盤開発チームの立ち上げ初期の技術選定と開発体制について書かせて頂きました。
個人的に、エンジニアは事業やプロダクトを成長させるために存在している、と考えているため、技術選定や開発体制を考えるときはかなり事業の状況・方針、プロダクトの方向性などを意識して行いました。
「事業起点で考える」のは、そういうテイを取ることは簡単ですが、本当の意味で1つ1つの判断・決断において事業から落とし込んで考えるためには、やはり自分が担当している事業について深く理解することが大事なんだと思っており、ここに関して私はまだまだ発展途上だなと感じております。

今回の技術選定において、正直全ての選択が正しかったかは分かりません。
技術選定・開発体制の構築から4年経過した今振り返ってみると、ある程度事業成長に貢献出来た選定だったのかなと思いますが、やはり選定後の実行(開発・運用)フェーズでどれだけやり切れるか、が大切だったなと感じております。
また、チームメンバーにも恵まれ、大変なことはありながらも常に事業・プロダクトの成長に集中できる環境で仕事をすることが出来たのも良かったと思っています。

何を選択するかも大事ですが、自分がした選択が正解だっと思えるよう努力すること、やりきることこそが本当は大切なんだと思っています。

まだまだ発展途上のプロダクト・チームですが、これからももっともっと成長できるように頑張っていきたいと思います。

次回以降の記事で話したいこと

今後も以下のような記事を書いていきたいなと思っているのでご期待ください!

  • スピードを重視しながらも保守性や変更容易性を一定担保する仕組み作り
  • チームの生産性を「下げない」ための態度とコミュニケーション原則と具体的なルール作り
    • ここは上述した採用の成功にも寄与していると思います
  • エンタープライズ企業に導入してもらうためのセキュリティ要件をスピード感を持って実現するための工夫
GVATECHブログ
GVATECHブログ

Discussion