法律を全く知らない状態からの仕様決定に向けた取り組み
経理の現場で今何に困っていて電帳法によってどこが改善されるのかを理解するため、最初の1、2カ月は社内の経理部や既存ユーザーの経理部へのインタビュー、電帳法が関わるプロダクトのPdMへのヒアリング、そもそもの法律の勉強を行いました。最も苦労したのは法律に関するキャッチアップです。
クラウドBoxは電帳法に関わるプロダクトのため、法律に準拠することは何よりも重要でした。法律理解が不十分な状態で行った意思決定には価値がありません。議論中に「ここは法律的にはどうなのか」という疑問が生まれると、それ以上の建設的な議論はほぼ不可能なので、とにかく早く法律を理解し、意思決定を行えるように勉強しました。
最初は新卒が法律のことを語っても「ちゃんと専門家に聞こう」と言われることもあり、悔しい思いもしましたが、社内ドキュメントツールに電帳法の整理を進めていき、いつでも誰でも簡単に一次情報である法律までたどれるような状態を作ることで、最終的に信頼を得ることができました。
また、ステークホルダーが「お客さま」「社内の複数プロダクト」「法律」とかなり多く、認識齟齬を減らすために情報の可視化を重視しました。議事録を取ることはもちろんのこと、ミーティング中に指摘をもらえるように議事録は公開しながら記録し、より多くの人に情報が伝わるように議事録を要約した「3行まとめ」を書き、議事録リンクとともにSlackチャンネルに転記しました。
![実際の3行まとめの例](http://cz-cdn.shoeisha.jp/static/images/article/14703/14703_002.jpg)
電帳法対応ファイルを取り扱うマイクロサービスへ
1月中旬にプロジェクトが発足してから仕様を決めるまでにおよそ2カ月を要しました。プロジェクト発足直後から社内関係者へのインタビューと法律調査を行い、2月下旬から社外インタビューを実施して3月末にはおおよその仕様が決定しました。
仕様検討の結果、クラウドBoxの責務は電帳法に準拠したファイルストレージに加え、ファイルアップロードなどのAPIを「マネーフォワード クラウド請求書」などの電帳法関連プロダクトに提供することになりました。
実装方法は、既存のファイル機能を拡張するか、新しくゼロから作るかという議論もありました。しかし、既存のファイル機能はメインデータベースに依存してしまっていること、ファイルは複数のプロダクトから参照されることを踏まえ、既存のデータベースや設計からは完全に独立したマイクロサービスにし、他サービスからAPI経由でファイルを扱ってもらう構成にしました。
これは第2回でもお話した、単一のデータ(電帳法対応したファイル)は単一のサービス(クラウドBox)からのみ参照され、他サービス(クラウド請求書)からはAPIを経由して操作するという原則にも準じています。
![クラウドBoxと共有データベース・共有ライブラリを持つサービス群の構成の違いと、固有データのAPI連携を通した参照](http://cz-cdn.shoeisha.jp/static/images/article/14703/14703_003.jpg)
このように、最近のマネーフォワードでは新しいサービスを作るにあたり、マイクロサービスを意識したサービス構成となるように意思決定が行われることが多く、モノリシックなマイクロサービスでサービス開発の初速スピードを上げるフェーズからスケーラブルな開発組織を目指してマイクロサービスを選択するフェーズへと変化しています。
技術選定/設計の方針
技術選定では、技術特性や将来性、社内リソースとの適合性を軸に考えました。前回までの取り組みを通して、インフラはサービスチームへ権限移譲され、ライブラリの解体とアカウント基盤のマイクロサービス化が行われています。そのため、「インフラチームの作業工数が増えるからこのミドルウェアしか使えない」や「共有ライブラリを使わないとデータ不整合が発生するから他のサービスと同じ技術を使わざるを得ない」という状況は過去の話となり、ミドルウェアや実行環境に用いる技術を選択する自由度はかなり高くなっています。
クラウドBox開発に求められていた要件は次のようなものがありました。
- 書類の管理を行うサービスであり、画像/PDFファイルのアップロードやダウンロードを行うリクエストが多くなることが予想され、大量のトラフィックをさばき切ることのできる技術・構成にすること
- リリース時点ではリッチな画面を作る必要はなく、他サービスへ電帳法ファイルAPIを提供することが主目的であること
- マルチAWSアカウント/マルチテナントEKS、アカウント基盤を用いて開発する初めてのプロダクトであり、今まではインフラチームが担当していたAWSリソース作成やEKSの設定をサービスチーム自身で行う必要があること
- 改正法の施行日が決まっており、それに間に合うように開発スピードを出せること
前述の条件を踏まえた結果、WebサーバーはNginx、サーバーサイド/フロントエンドはRuby on Railsという技術を選択しました。WebサーバーにNginxを採用したのは、NginxのX-Accel-Redirect機能を用いることで高速な画像配信を可能にするためです。
Nginxは何十万ものクライアントを同時に処理することが可能で、他Webサーバーと比較してメモリ使用量が少なく、コンテンツ配信において高いパフォーマンスを発揮します。
通常はアプリケーションサーバーから直接静的ファイルを配信しますが、X-Accel-Redirectを使えば認証認可などのビジネスロジックが関わる処理はアプリケーションサーバーで処理し、コンテンツの配信のみをNginxサーバーへ肩代わりさせることができ、アプリケーションサーバーが詰まるリスクを低減できます。
![NginxのX-Accel-Redirectを用いたコンテンツ配信のシーケンス図](http://cz-cdn.shoeisha.jp/static/images/article/14703/14703_004.jpg)
X-Accel-Redirectのほかにも、S3の署名付きURLの利用も検討しました。署名付きURLは「HTTPメソッド」「バケット名」「オブジェクトキー」「有効期限」を指定して作成するURLで、このURLを受け取った相手は誰でもオブジェクトへアクセス可能になります。オブジェクトはS3から直接配信されるためX-Accel-Redirectよりも高速で可用性も高いのですが、URLを知っていれば誰でもアクセスできてしまう点がデメリットです。
クラウドBoxでは請求書などのデータを扱うため厳密なセキュリティ要件が求められます。そのためリクエストの度に毎回バックエンドで認証を行うことができるX-Accel-Redirectを用い、署名付きURLは使用しませんでした。
サーバーサイド/フロントエンドにRuby on Railsを用いた理由は、メンバー全員がRuby on Railsの経験者であり、開発スピードを出せるからです。逆に、メンバー全員が未経験だったAWSリソース作成やEKS設定を新しく学ぶ時間を、リリース期日までに確保することが難しかったのも背景にあります。
技術選定は選定時点での最適解でしかないので、サービスの利用状況や開発方針次第で柔軟に変えていくことを前提とした設計も心がけていました。例えばリッチなフロントエンドの機能を提供する必要が出てきた場合はNext.jsやNuxt.jsを利用すること、サーバーサイドのレスポンスがボトルネックになった場合はその部分をGoを使ったマイクロサービスに切り出したくなるはずです。
また、データベース設計においてある1つのカラムが複数のテーブルを参照するpolymorphic(ポリモーフィック)関連はそのカラムに外部キー制約を課して参照整合性を保てないためSQLアンチパターンとされています。しかし、Ruby on Railsではフレームワークレベルでpolymorphicをサポートしており、SQLで参照整合性を保てないというデメリットを低減してくれています。ここでもしpolymorphicをサポートしていないフレームワークにサーバーサイドを書き換える必要が出てきた場合、自らで参照整合性を考慮した実装を行う必要があり、移行後に大きな技術的負債を抱えることになるかもしれません。
補足
最近のマネーフォワードではGoを使う新規サービスが多くなっています。技術スタックをRuby on Railsなどの特定フレームワークへ統一することによるメリットよりも、適材適所での技術選定を行うメリットが事業の成長に合わせて大きくなってきており、Go、Python、Next.js、Nuxt.jsの積極的な採用を推進する方針がCTOから発表されています。
これら技術の普及リードタイムを短くすることに価値があると考えており、社内で特にニーズも高く技術的な相性も良いGoに関しては、Go推進グループが新設され、普及の後押しをしています。Go推進グループは、社内勉強会の開催を通したGoの学習サポート、Goでサービスを始めるにあたって必要になるテンプレの提供、Go関連で困ったときに相談できる場所(駆け込み寺)の提供、マイクロサービス関連の相談を行っています。