はじめに
こんにちは。レバレジーズ株式会社システム本部の田中です。
2022年11月から新規事業の立ち上げメンバーとして開発業務に携わっており、2023年6月にレバクリをリリースしました。社内では初となる大規模かつ決済を伴うtoCサービスであり、様々な挑戦をしながら開発を進めてきました。
レバクリは「あなたの自宅をクリニックにする」をコンセプトに、オンラインで診療予約、診察、決済が完結し、自宅に薬が届くオンライン診療プラットフォームサービスです。「医療のあり方を変え、日本の医療における問題解決の主体者となる」ことをミッションとし、提携している医療機関と連携しながら、患者と医療機関の双方への最適な体験を提供できるサービスの実現を目指しています。
レバレジーズではエンジニア一人ひとりが要件定義などの上流から実装まで幅広く担当することはもちろん、マーケティングやデザイン、オペレーションなど様々な領域の業務に関わることがあります。特に新規事業の開発においてはエンジニアに限らず少人数チームで始まることが多いため、エンジニアとしてではなく立ち上げメンバーとして様々なことに主体的に取り組むことができます。この記事では新規事業『レバクリ』の開発にあたって私が取り組んだことについて、以下二つの観点で紹介していきたいと思います。
- 技術的側面
- プロダクトマネージメント的側面
レバレジーズでの新規開発でエンジニアがどのように活躍、成長できるのか、どんな形で貢献できるのか、少しでもイメージが鮮明になると幸いです。
サービスやチームの特徴をベースとした自由な技術選定
技術選定といえば、新規事業のプロダクト開発の際の醍醐味の1つだと思います。レバレジーズでは技術選定は各チームに任されているので、事業の特性やチーム構成、メンバーの経験などをベースに行うことができます。
今回、レバクリ開発チームでは「最速でのリリース」と「開発者体験」を考えた技術選定を行いました。チーム発足からリリース予定まで7ヶ月あまりと短かったことから、できるだけ開発速度が出せるように、またチームメンバーの開発体験をできるだけ高めることができるようにという意図でした。
言語
言語はフロントエンド、バックエンドともにTypeScriptを採用しました。
選定理由はかなり一般的な部分になりますが、
- 社内でも標準技術となりつつある
- 実装時に型チェックが効いてエラーを未然に防げる
- フロントエンド、バックエンドで同じ言語が使える
ことが挙げられます。
フロントエンド
TypeScriptで開発できるFWとしてNext.jsを採用しました。
Next.jsはFWの大きな特徴として
- ReactベースでTypeScriptとの相性がいい
- アップデートやリリースが高頻度でコミュニティも活発
- キャッシュ戦略やReact Server Component対応など、高パフォーマンスのアプリケーションを実装するためのベストプラクティスが用意されている
ことが挙げられます。
また、私自身入社してから1年半Next.jsを使ったサービスの開発をしていたため、新規プロジェクトへのスムーズな導入が期待できたことがありました。他にNext.jsの経験があるチームメンバーはいませんでしたが、VueやNuxtの経験はあったため順応にさほどコストがかからないと判断しました。
技術面の特徴としては
- bulletproof-reactベースのディレクトリ構成
- featuresディレクトリ内で機能ごとに分けることで、機能間の結合を避けて無駄な共通化を考えずに開発速度を高めることができる
- GraphQL Code GeneratorとApollo Clientを組み合わせてデータ取得を実装
- バックエンドのスキーマ定義から型を生成できる
- 自動生成されたApollo ClientのHooksを使ってデータ取得処理やキャッシュ管理の実装工数を削減
- App Routerを一部導入
- v13.4でstableになったことを受け、一部の機能でApp Routerを採用
といった具合です。
バックエンド/API
TypeScriptで開発できるNestJS、APIはGraphQLを採用しました。
NestJSは
- TypeScriptで開発されたFW
- GraphQLと相性がいい
- Express(もしくはFastify)がベースで実装手法が近い
- 拡張性を残しつつ、FWとしてほしい機能が一通り揃っている
といった特徴があります。私自身はTypeScriptでのバックエンド開発経験がほとんどなく、Expressを少し触ったことがある程度でしたが、ドキュメントが充実していて実装方法に癖があまりないのでスムーズに実装に入ることができました。
GraphQLは
- 単一のエンドポイントで1リクエストから複数リソースを取得できる
- 取得する内容をフロントエンドで指定できる
- バックエンドで定義したスキーマを型としてそのままフロントエンドで使うことができる
特徴があり、ページ数が多く、同じデータを複数箇所で使ったり少し形を変えて取得したりするプロダクトの特性にフィットしていると判断しました。また、バックエンドとフロントエンドで型が一致することは開発者体験を非常に向上させるものとなりました。
技術面の特徴としては
- オニオンアーキテクチャベース
- NeverThrowを使って型安全にエラーハンドリング
- try-catchでエラーに型がつかない問題をResult型を返すことで解消する
- ORMとしてPrismaを採用
- 多機能ではないが、直感的で実装が簡単なNode.js用のORM
- GraphQLのN+1問題も解消してくれる
といった具合です。
社内スタッフ向けCMS
記事などの動的コンテンツの管理にはStrapiというHeadless CMSを採用しました。
Headless CMSというとあまり聞いたことがなかったり、知っていても使ったことはない方も多いかもしれませんが、表示部分(Head)以外の管理画面機能やデータ配信機能(API)を備えたものです。SEO流入獲得のために記事ページを展開する上でCMSの開発は必須ですが、リソースや保守を考えて0からの自作は避けたかったため、カスタマイズ性は確保しつつ実装を最小限に抑えられるCMSを探していました。
Strapiは
- TypeScriptに対応している
- オープンソースなので無料で構築できる
- REST apiもGraphQL apiもどちらも利用可能
という特徴があります。自前で環境構築が必要ではありますが、料金がかからずコードを書けば簡単にカスタマイズや拡張ができる点からStrapiを選択しました。
Strapiについて詳しく書くと長くなるので省略しますが、社内利用に制限されていて機能も最低限の管理画面とAPIが必要な程度だったため、想定よりも手軽に運用に持っていくことができました。
外部サービス
認証に関しては、有名なIDaaSとしてCognitoやAuth0、Firebase Authenticationがありますが
- 料金が比較的安い
- Firebase Authentication < Cognito < Auth0
- インフラをAWSで構築しているので親和性が高い
- セキュリティ的な懸念があまりない
- Firebase Authenticationには登録しているユーザーが特定できる問題がある
といった特徴からCognitoを採用しました。フロントエンドはAmplifyと組み合わせることで簡単に実装できるのと、サーバーの処理もAWS Admin SDKを使ってシンプルに実装が可能でした。また、AWSでインフラを構築しているので権限周りの設定も楽に行うことができました。CognitoとAmplifyを合わせた実装については別のスライドで簡単に説明しているのでそちらも合わせてご覧ください。
決済プラットフォームはStripeを採用しました。実装するサービスやプロダクトの特徴によって大きく変わってくるので一概にはいえませんが、StripeはAPIが充実しており開発者向けのドキュメントも豊富なため、高いカスタマイズ性を求める場合に非常に相性がいいです。
ユーザー体験を第一に考えてサービス設計を主導
技術選定はもちろんですが、新規事業の立ち上げメンバーとしてサービス設計も主導しました。オンライン診療事業としては大きな競合が2社ありました。それらのサービスの機能やフローを分析した上で必要な機能を洗い出し、より良いユーザー体験を届けるためにどうしたらいいか、どの機能がクリティカルで優先すべきかを整理しました。そして、最適なユーザー体験を第一にサービス設計を主導しました。
ここでは特に設計に工夫をしたtoCのメールアドレス認証とtoBの診療画面について紹介します。
メールアドレス認証
メールアドレス認証自体は機能として一般的ですが、社内の他サービスでは導入しているものが少なく、導入してCVRが下がった例もあったため、メールアドレス認証を入れるべきかどうかの議論からスタートしました。
レバクリは基本的に登録したメールアドレスを使ってユーザーとサービス側がコミュニケーションをとる場面が多く、ログイン時のIDとしても使用する場合があるのでメールアドレスが存在しなかったり誤って入力されてしまうことはサービス運営上大きな障壁となります。また、セキュリティ面でもなりすましや第三者にメールが届いてしまうリスクにつながります。医療に関係するサービスであるため、受診歴や問診の回答内容が流出してしまうと大きな問題になってしまいます。ユーザーに安全にサービスを使用してもらうためにもメールアドレス認証は有効な手段でした。
エンジニアとしてはセキュリティリスクを最小限に抑えるためにメールアドレス認証が必要と判断しましたが、事業サイドのCVRにおける懸念がある以上、セキュリティリスクを説明して理解を得る必要があります。以下のようなフローチャートを作成し、リスクを最小限に抑えるためのパターンについて提示した上で、認証を挟むポイントとしてどこがベストか議論をしました。
レバクリには複数の機能がありますが全て診療の予約が起点となります。言い換えると診療を予約するまでは流出がクリティカルになるような情報やなりすます機会はないため、診療予約が完了するまでにメールアドレスが認証できていれば最低限のセキュリティ要件を満たすことができます。ユーザー登録に必要な情報を登録してもらい、最後に予約を確定するタイミングにメールアドレス認証を要求するステップに工夫しました。
toB診察画面
診察を行う医師やクリニックの事務作業を行うスタッフが使用する画面をtoB画面と呼んでいます。toB画面も診察の一覧表示や診察、薬の発送に関する画面など複数の機能が存在していますが、事業の状況やチーム構成によってユーザーが変化する可能性があります。例えば一人で診察から発送まで行う場合と、作業を複数人で分担する場合では導線はもちろん必要な画面の種類や数まで変わってきます。そのため、集客やサービス運営が安定してくるまでに細かい変更が簡単にできるように、あまり作り込まずに最低限の機能を用意してリリースすることを目指しました。
初期のスコープは医師が全て対応するのを基本線として、提携クリニックの医師にヒアリングをしながら設計しました。医師が普段の診察時に使っているシステムについて知見のあるメンバーがほとんどおらず、リファレンスもなかなか見つからずに難しいタスクでしたが、適宜画面の構成や機能についてすり合わせたり、プロトタイプを触ってもらってフィードバックを受けながら進めました。
現在はCSチームが設置されたり、作業者の分担があったりと事業の状況も変わってきていて、初期はスコープから外していた検索機能を利用シーンにあった形で実装したりと日々アップデートが行われています。
今後の課題
最後に今後の課題として取り組んでいきたいことについてご紹介します。
開発組織の体制整備
チーム発足からエンジニア正社員2名+業務委託数名で開発を続けており、初期スコープではあらかじめ全て設計してから進めるウォーターフォールの形で開発していました。現在はチームメンバーも徐々に増え、複数機能を並行して設計、開発、リリースするアジャイル開発に近い形になっていますが、整備されているわけではないのでタスクの管理工数の増大やチームとしてパフォーマンスを最大化できていません。社内で導入しているチームが多いスクラム開発を含めて、機能開発を進めながら開発組織の体制も整備していきたいと考えています。
プロダクトとして競合に対する優位性の確立
レバクリはオンライン診療サービスの中では後発になるため、現在は競合のレベルに追いつくための機能開発が中心になっています。着実に機能開発が進んできており、年内には機能として競合に遜色ない状態になる見通しとなっているため、今後は追いついた先で市場1位をとるためにプロダクトの強みを伸ばしていく必要があります。具体的には、予約やオンラインでの診察といった基本機能だけでなく、医薬品の服用をリマインドしたり服用の中での副作用への不安をサポートできるような機能や、診察の結果や自らの健康状態を確認できる機能など、プロダクトとして何度も使ってもらえるような仕組みを作っていくために、ビジネスサイドに食い込んで事業成長に貢献していけたらと考えています。
さいごに
最後までお読みいただきありがとうございました。レバクリを一番選ばれる最高のサービスにしていくことを目指して、これらの課題に取り組み、より強い開発組織を作っていきたいと考えています。現在、私たちと一緒に挑戦してくださるエンジニアを募集しています。ご興味のある方はぜひ採用サイトをご覧ください!