エンジニアの篠塚(@shinofumijp)です。株式会社FiNC Technologies(以下「FiNC」)にてサーバーサイドの開発を主に担当しています。
今でこそFiNCは「マイクロサービスの採用」を打ち出して、40を超えるマイクロサービス、50人以上のエンジニア組織となりましたが、サービスの開始当初はもちろん1つのサービス、数名のエンジニアしかいませんでした。FiNCが現在のアーキテクチャに至るまでにさまざまな課題に直面し、技術的にも組織的にも変革をする必要がありました。
本記事では、FiNCがどのような選択や歴史を経て現在の姿に至ったのかを紹介します。
※2018年12月にRails Developer Meetup ( https://techplay.jp/event/702297 )というRuby/Railsエンジニアのイベントにて話した内容を元に構成しています( 「FiNCでの5年間に渡る マイクロサービスの育て方」)。
FiNCアプリって?
私たちが開発しているFiNCアプリについて簡単に説明します。
FiNCアプリはヘルスケアに特化したモバイルアプリケーションです。アプリのダウンロード数は現在では460万を超え、2018年にはApp Store、Google Playにてヘルスケア&フィットネス部門のダウンロード数で1位を獲得※しました。
FiNCアプリが提供する具体的なサービス例としては、歩数・体重・睡眠・食事などのライフログの記録を行うことができ、記録を通してデータが溜まると、アプリケーションバックエンドのアドバイスエンジンが学習し、よりパーソナライズされた健康サポートがAIで受けられるようになります。
また、このFiNCアプリのプラットフォームとして、サブスクリプションや、美と健康商品を取り扱うECサービスも提供しています。
横文字も多く並んでごちゃっとしてしまったのでまとめると、要するにヘルスケアドメインにおいて多面的にサービス提供を行なっているプラットフォームアプリ(図1)です。
※日本国内App Store/ Google Play「ヘルスケア&フィットネス」カテゴリにおける直近1年間(2017年11月〜2018年10月)の合算です。/出展:App Annie
どのようにFiNCアプリの開発は始まったのか
私は5年前の2014年にFiNCに入社しました。入社当時はまだFiNCアプリは生まれておらず、エンジニアもいませんでした。
FiNCアプリの開発の歴史は2013年に遡ります。2013年当時、私は大学院に身を置きつつ、現FiNCの代表取締役 CTOの南野や友人らとともに自分たちでシステム開発の会社を営んでおりました。その会社で受託案件として受けたのがFiNCアプリの開発でした(図2)。
このように受託開発としてスタートしたFiNCアプリの開発ですが、サービス内容やFiNCの未来の構想を溝口(FiNC代表取締役 CEO)から聞いているうちに、解決しようとしている問題の大きさや、溝口の人柄に惹かれてしまい、「システムを納品しておしまい」ではなく「プロダクトとして成長させたい」という思いがとても強くなり、前職のメンバーもろともFiNCに入社し開発を継続することに至りました。
最初のサービスこんなの
最初にリリースしたのは「FiNC ダイエット家庭教師」と呼ばれるサービスです(図3)。このサービスはモバイルWebのサービスとして2014年3月にリリースしました。
サービス内容はダイエットをしたいお客様に対して、1対1で専門家の先生がついてダイエットをサポートするというものです。「ダイエットをサポートするサービス」というとなんとなくうさんくさい感じがしますが (最初にサービス説明を受けたときに私はそう思いました)、食事、運動、睡眠を改善するためのアドバイスをし、健康な生活習慣を手に入れるための支援をする、そして成人病などの病気を未然に防ぐ、というのがサービスとしての狙いです。
2014年、サービスリリース時点のアーキテクチャ
Railsサービスが1つある、という感じです。アーキテクチャと呼べるのかどうかすら怪しいです(図4)。
なぜマイクロサービス化をしたのか?
「FiNC ダイエット家庭教師」の開発中に溝口と話す機会がありました。溝口からは、ジムのトレーナーの経験を通して日本の健康課題を目の当たりにしたこと、健康課題を解決するためにまずは1対1のダイエット指導を通した生活習慣改善に取り組むが、まだまだ解決すべき問題は山積みであるということを聞きました。健康指導を行うことが可能なプロフェッショナル人材と機会の不足、各種検査へのアクセシビリティの低さ、信頼性の低い健康情報の氾濫、健康商品の入手困難さ、孤独死やコミュニティの重要性、法人従業員の不定愁訴と生産性の低下、などなど。そして、これらの問題を解決するためのサービスを提供し、ヘルスケアのプラットフォームを構築したいという旨を聞きました。
この話を受けて、今のエンジニア人数だけでは到底不可能だし、1つのアプリケーションでこれらのサービスを提供するのは困難であると感じました。そこで、それぞれのサービスは別の人が開発して、それらのサービス同士がAPIなどで連携し合うような将来のアーキテクチャイメージをぼんやりと思い描き始めました。不勉強で恥ずかしいのですが、2014年当時、私はマイクロサービスという言葉を知りませんでした。当時構想していたものは現在のアーキテクチャよりももっと粗雑で適当なものでしたし、それが原因で様々な罠を踏むことになりました(伏線)。
2014年後半〜2015年、サービスの成長期
この時期は事業の拡大とそれに伴うサービスの追加が行われました。新しく提供したサービスは遺伝子検査結果閲覧サービス、法人向けサービス、ECサービス、専門家の教育サービス、などです。
サービスが増加すると、それぞれのサービス間で共通で扱いたい機能が出てきたので、それらを基盤サービスとして切り出すことも行いました。認証基盤やレコメンデーション基盤です(図5)。
レコメンデーション基盤サービスは早すぎる汎用化の罠にはまってしまい、様々なアプリケーションのドメイン知識を必要とした神サービスとなってしまいました。神サービスの問題点には、サービスオーナーが不明瞭になりメンテされづらいことや、影響範囲がわかりづらいことや、独立したデプロイが困難になる、などが挙げられます。レコメンデーション基盤は2018年にリアーキテクトを行いました。
2016年〜2017年、本格的なマイクロサービス化
2017年3月のFiNCアプリ正式ローンチに向けて、エンジニア採用やサービスの拡大が加速します。タイムラインやチャットなどの機能単位でのサービスの切り出しが行われたり、サービスと呼応したチームの作成が行われました。歩数・体重・睡眠・食事などのライフログを管理するサービスとそのサービスを担当するライフログチーム。健康記事の配信を行うサービスと、そのサービスを担当するメディアチーム。サブスクリプション事業のためのサービスとサブスクリプションチームといった具合に。
この時期には急なサービス拡大に伴う問題が発生しました。
顕在化した課題とその対応
まず1つは、最初に「FiNC ダイエット家庭教師」を実装した本体サービスが肥大化し、神アプリケーションとなってしまったことです。元から存在したサービスということもあり、クライアントアプリとの密結合なところも多くありました。クライアントアプリ側でAPIを集約するのが大変な場合に、本体サービスで集約を行うこともありました。またクライアントアプリのUI制御にもこのサービスのAPIを利用することもありました。
この問題に対しては、バックエンドサービスがよりリソース指向なAPIを提供するための技術選定と、それらのAPIを集約するためのBFF(Backend For Frontend)の導入を行いました。
次に、アプリケーション間のデータ同期が密結合になってしまうことがありました。これも神サービスの形を変えたものではあります。具体的には「ユーザが退会した」といったイベントが起きた際に、そのイベントの影響を受けるサービスに対してAPIを通して通知を行うといったアーキテクチャになっていました。これでは当然新しいサービス追加があったときにスケールしなくなってしまいます。
この問題に対応するためにPubSubを用いたイベントドリブンアーキテクチャを採用しました(図7)。このことにより「イベント通知を受け取りたいサービス」がイベントをオブザーブするような依存関係になったので、イベントが発生するサービスは影響範囲を知らなくてもよくなり、疎結合を保つことができるようになりました。
イベントドリブンアーキテクチャの採用までの歴史はFiNC エンジニアのota42yの資料(「マイクロサービスにおける非同期アーキテクチャ」)をご覧いただければと思います。
最後に、サービス拡大に伴い全体観が見えづらくなったり、仕組みが追いつかないために開発体験が悪くなるなどして、結果としてエンジニアのモチベーションが下がるといったことが起きました。おそらくサービスの急成長を経験したことのある方からするとよくある話なのではないかと思います。
この問題に対しては重要なマネジメント課題として取り組むことにしました。この取り組みについてはFiNC VPoEの清水の資料(「カイカクジャーニー ~ スタートアップが必ずぶつかる課題と開発チームのメジャーバージョンアップ ~」)にも書かれておりますのでご参考していただければと思います。
2018年、グロースを行うためのリアーキテクト
サービスのローンチが終わり、一通りのベースとなる機能ができた後には、よりアプリを利用してもらうためのグロースが重要になります。グロースさせたい機能が既存の大きいサービスに入っていたり、あるいは複数のサービスにまたがってしまっていると、施策の実行と仮説検証のサイクルが遅くなってしまいます。
そのため2018年からはグロースを行いたい機能を新しくサービスに切り出すといったリアーキテクトを行いました。具体的でわかりやすい事例としてアプリのオンボーディングをマイクロサービス化した例をFiNC エンジニアの近藤がブログに書いてありますので紹介いたします( https://link.medium.com/CEyLR1so5T / 「半年で250回のリリース!? FiNCアプリのオンボーディングMicroserviceの裏側」)。
その他にも先述したBFFや、レコメンデーション基盤のリアーキテクトも行いました。BFFのリアーキテクトはFiNC エンジニアの森の資料にも書いてあります(「Server-side Kotlin for Frontend」)。
今後はチームの粒度とサービスの粒度が一致していないサービスを統廃合して新しいサービスにするといったことも計画しています。
最後に
そんなこんなで現在のアーキテクチャに至ります。ただ、もちろん現在のアーキテクチャも完璧なわけではありません。また、あくまでマイクロサービスアーキテクチャもスケールするサービスと組織のための手段だったので、別のアーキテクチャを採用することもありえます。
今後は、さらにスケールするアーキテクチャと組織にするためにDevSecOpsの推進、よりパーソナライズされたアプリ体験のための機械学習適用範囲の拡大、サービス間連携の新しい仕組みの導入などを行なう予定です。その他にも予定している技術的なチャレンジや組織的なチャレンジはまだたくさんあります。
山積みになっている日本の健康課題をFiNCというヘルスケアプラットフォームを通して解決するためには、まだまだ行うことがあり、アーキテクチャの改善も引き続き必要になります。
そういった変化を楽しみながら、一緒に問題を解決してくれる仲間をFiNCでは募集しています。
▼Railsエンジニア(Server)
▼SRE
▼iOS
▼Android