Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割 / JJUG2019Spring

Recruit
PRO
December 13, 2022

ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割 / JJUG2019Spring

Recruit
PRO

December 13, 2022
Tweet

More Decks by Recruit

Other Decks in Technology

Transcript

  1. ホットペッパービューティーにおける
    モバイルアプリ向けAPIの

    BFF/Backend分割
    Nawate Ippei @JJUG 2019 Spring #jjug_ccc #ccc_c4

    View Slide

  2. ⾃⼰紹介
    • Nawate Ippei
    • リクルートライフスタイル
    • 2016/04に新卒⼊社
    • ⼊社してからずっとホットペッパービューティー
    • 仕事内容
    • 2016/04 ~ 2018/01 Androidエンジニア
    • 2018/01 ~ サーバサイドエンジニア
    https://twitter.com/sakuna63
    https://github.com/sakuna63

    View Slide

  3. リクルートライフスタイルについて
    「ちょっとした毎⽇を提供し、ひとりひとりの⽣活を豊かにする」を
    実現するために様々なサービスを提供。

    View Slide

  4. ホットペッパービューティーについて
    国内最⼤級のヘアサロン・リラク&ビューティサロンの検索・予約サイト
    年間約9800万回の予約が⾏われる(2019/05時点)

    View Slide

  5. 今⽇のお話について
    • モバイルアプリ向けAPIを2つのAPI層(BFF層/Backend層)に分割した取り組み

    についてお話しします
    • 現在進⾏系で分割中です 👷 🚧(約100本中、28本のAPIが新構成に移⾏済み)
    • 新構成のAPIを利⽤したアプリがつい先⽇(5/13)リリースされました
    • なので保守・運⽤の経験に基づいて語れることはほぼありません
    🙇
    • ࠓ೔͸෼ׂ։͔࢝ΒϦϦʔε·Ͱͷؒʹಘͨ஌ݟΛڞ༗͠·͢

    View Slide

  6. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  7. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  8. BFFとは何か?
    • BFF = Backends For Frontends
    • マイクロサービスアーキテクチャの1つ
    • FrontendとAPI Serviceの間に位置するBackendサーバ
    • 個々のサービスが提供するAPIを集約し、Frontendに特化したレスポンスを返す
    API Service
    API Service
    API Service
    JSON
    HTML
    CSS, JS
    BFF for Web
    BFF for App
    Search

    Engine
    Mobile App
    Browser

    View Slide

  9. 今回のBFFの⽤途:システムの関⼼事の分離
    • 表⽰処理を⾏う層(SOE)とデータを管理する層(SOR)の分離
    • BFFは前者
    • 本発表のBFF/Backend分割はこの⽤途に近い
    BFF

    (for SOE)
    Monolithic
    Backend
    Backend

    (for SOR)
    Frontend Frontend

    View Slide

  10. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  11. API開発スピードの⾼速化
    BFF/Backend分割の⽬的

    View Slide

  12. 背景と課題
    • API開発のスピードがアプリ改善スピードのボトルネックになっていたため
    • APIの開発はアプリチームからの依頼ベースで実施されるが、

    リソース調整などの要因で開発完了まで3ヶ⽉以上かかっていた
    • アプリチームの開発サイクルはより早く(1ヶ⽉)、API開発スピードがボトルネックに...
    モバイルアプリ

    向けAPI
    Webアプリ
    API開発依頼
    開発完了
    (3ヶ⽉~後)
    アプリチーム(8名) サーバサイドチーム(数⼗名)
    モバイルアプリ

    View Slide

  13. 課題に対する打ち⼿
    BFF層 Backend層
    モバイルアプリ向けAPI

    (モノリシック)
    サーバサイドチーム アプリチーム サーバサイドチーム
    分割
    APIのBFF/Backend分割を実施し

    アプリチームのリソースでAPIを開発・リリースできる体制を整えることで
    ボトルネック(API開発スピード)の改善を狙う

    View Slide

  14. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  15. BFF/Backend分割の⽅針
    ① 各層にどう処理を分担させるか
    ② 層間の通信をどのように⾏うか
    BFF層 Backend層
    ②どう通信?
    モバイルアプリ向けAPI

    (モノリシック)
    処理A
    処理C
    処理B
    処理D
    ①どう分担?




    View Slide

  16. このように分割することに
    BFF層 Backend層
    表⽰要件に関わる処理
    業務ロジック
    アプリ特有の処理
    データソース(DB等)

    のRead/Write
    REST API
    • BFFにアプリ特有の処理や表⽰要件に関わる処理を持たせる
    • BackendはREST APIを提供、BFFは複数のBackend APIを呼び出し結果を集約

    View Slide

  17. BFF層 Backend層
    モバイルアプリ向けAPI

    (モノリシック)
    分担
    処理A
    処理C
    処理B
    処理D




    ① 各層にどう処理を分担するか? 🤔

    View Slide

  18. 処理分担のポイント
    • BFFはアプリチームで⾼速に開発できるようにしたい
    • 開発(変更)の早さ ≒ 意思決定の早さ(特に⼤きな組織では)
    • すばやく意思決定するには

    「他チーム・他システムへの依存・影響を⼩さくする」のが⼤事

    View Slide

  19. 処理分担のポイント
    • BFFはアプリチームで⾼速に開発できるようにしたい
    • 開発(変更)の早さ ≒ 意思決定の早さ(特に⼤きな組織では)
    • すばやく意思決定するには

    「他チーム・他システムへの依存・影響を⼩さくする」のが⼤事
    アプリチームで変更の意思決定が完結する処理をBFFに持たせる

    View Slide

  20. 処理分担の基準
    BFF層 Backend層
    表⽰要件に関わる処理
    • プレゼンテーションロジック
    • 表⽰要件に合わせたデータ集約
    業務ロジック
    アプリ特有の処理
    • アクセストークンの管理など
    データソース(DB, 検索エンジン)

    のRead/Write

    View Slide

  21. 補⾜:表⽰要件に合わせたデータ集約
    データA, B, Cを

    まとめて表⽰したい!

    (表⽰要件)
    表⽰要件に合わせて、複数のデータをAPIが⼀つに集約して返すこと
    API
    A
    B
    C
    API
    A B C
    API
    A B C
    集約
    モバイルアプリ

    View Slide

  22. • 「予約」「メニュー」「クーポン」を同時に表⽰
    • これらは独⽴したデータ
    予約⼀覧
    予約
    予約先サロンのメニューとクーポン
    補⾜:表⽰要件に合わせたデータ集約の例

    View Slide

  23. 補⾜:表⽰要件に合わせたデータ集約の例
    • 「予約」「メニュー」「クーポン」を同時に表⽰
    • これらは独⽴したデータ
    • APIが↓↓のように集約して返している
    予約⼀覧
    予約
    予約先サロンのメニューとクーポン
    "reservations": [


    {


    "coupons": [


    ...


    ],


    "menus": [


    ...


    ]


    }


    ]

    View Slide

  24. BFF層 Backend層
    どう通信?
    ② 層間でどのように通信するか? 🤔

    View Slide

  25. Backend
    BFF/Backend構成におけるデータ集約
    • BFFは複数のBackend APIを組み合わせてデータを集約する
    • ⾃由に組み合わせられるよう、Backend APIは再利⽤しやすい粒度(REST)で作成
    BFF A
    B
    C
    API
    A B C
    API
    A B C
    モバイルアプリ
    集約
    REST API

    View Slide

  26. BFF/Backend分割イメージ - Before
    モバイルアプリ向けAPI

    (モノリシック)
    サーバサイドチーム
    アプリチーム
    表⽰要件に関わる処理
    • プレゼンテーションロジック
    • 表⽰要件に合わせたデータ集約
    業務ロジック
    データソース(DB, 検索エンジン)

    のRead/Write
    アプリ特有の処理
    • アクセストークンの管理など

    View Slide

  27. BFF/Backend分割イメージ - After
    サーバサイドチーム
    アプリチーム
    BFF層 Backend層
    REST API
    表⽰要件に関わる処理
    • プレゼンテーションロジック
    • 表⽰要件に合わせたデータ集約
    業務ロジック
    データソース(DB, 検索エンジン)

    のRead/Write
    アプリ特有の処理
    • アクセストークンの管理など

    View Slide

  28. 分割⽅針の振り返り
    処理分担の基準について
    • 基本的に、この基準で迷いなく開発できている 👍
    • ⼀点悩んだところがあったので次のスライドで紹介
    • BFFの開発スピードが早くなるかはこれから検証 🧐(保守・運⽤が始まったばかりなので)
    BackendのAPI粒度(REST)について
    • 参照系のBackend API(GET)の四分の⼀(24本中6本)がBFF API間で再利⽤できている 👍
    • 逆に更新系の Backend API(POST, PUT, DELETE)はBFF APIと1:1で対応することがほとんど

    View Slide

  29. 分割⽅針の振り返り
    処理分担の基準について
    • 基本的に、この基準で迷いなく開発できている 👍
    • ⼀点悩んだところがあったので次のスライドで紹介
    • BFFの開発スピードが早くなるかはこれから検証 🧐(保守・運⽤が始まったばかりなので)
    BackendのAPI粒度(REST)について
    • 参照系のBackend API(GET)の四分の⼀(24本中6本)がBFF API間で再利⽤できている 👍
    • 逆に更新系の Backend API(POST, PUT, DELETE)はBFF APIと1:1で対応することがほとんど

    View Slide

  30. 悩みどころ:プレゼンテーションと業務の境界
    • ホットペッパービューティーは掲載システム
    • クライアントが⼊稿したデータをユーザに表⽰している
    ⼊稿システム
    ⼊稿データ
    掲載 ⼊稿
    サロン(クライアント)
    ユーザ

    View Slide

  31. 悩みどころ:プレゼンテーションと業務の境界
    • ドメインモデルが表⽰制御のプロパティを持つことがある
    • 例えば「値段にチルダ(~)をつけるフラグ」というのがある
    • こういったときのテキスト加⼯処理など、どの層に持たせるべきか悩む 🤔
    • ϓϨθϯςʔγϣϯϩδοΫͱଊ͑Δ΂͖͔、業務ロジックと捉えるべきか...
    public class Price {


    private int value;


    /**


    * 値段にチルダ(~)を付けるかどうかのフラグ


    */


    private boolean tildaSuffixRequired;


    }

    View Slide

  32. 悩みどころ:プレゼンテーションと業務の境界
    • 結論:「⼊稿ドメインの処理 = 業務処理」と解釈することにしている
    • なので、上記に該当する処理はBFF層ではなく、Backend層に持たせている

    View Slide

  33. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  34. API設計
    BFF層 Backend層
    API粒度 アプリのユースケース単位 REST
    APIバージョニング する しない

    View Slide

  35. API設計
    BFF層 Backend層
    API粒度 アプリのユースケース単位 REST
    APIバージョニング する しない

    View Slide

  36. アプリのユースケース単位とは? 🤔
    • 右画⾯で⾔う⾚枠の単位
    • これらの単位でAPIを作成
    ネイルカタログ特集を⾒る
    ネイルデザインランキングを⾒る 新着ネイルデザイン

    を⾒る
    ネイルカラーを⾒る
    ネイルテイスト

    を⾒る
    ネイルシーンを⾒る

    View Slide

  37. 画⾯単位で作るとだめなのか? 🤔
    • ӈͷը໘Ͱ͸3ͭͷ"1*ΛฒྻͰݺͼग़͢
    • ⼀度の呼び出しで取得できたほうが

    通信回数も少なくなる
    • 処理の並列度も下がるのでアプリも楽?

    View Slide

  38. 画⾯単位で作る難点
    Fault Tolerance観点
    • ⼀部の不安定なBackend APIに、BFF API全体のパフォーマンスや成否が引きずられる
    アプリからの使いやすさ
    • キャッシュ要件の異なるリソースが混ざるときなど、ハンドリングが複雑になる
    • etc...

    View Slide

  39. 画⾯単位で作る難点
    Fault Tolerance観点
    • ⼀部の不安定なBackend APIに、BFF API全体のパフォーマンスや成否が引きずられる
    アプリからの使いやすさ
    • キャッシュ要件の異なるリソースが混ざるときなど、ハンドリングが複雑になる
    • etc...
    このような事情も踏まえてユースケース単位で作成している

    View Slide

  40. API設計
    BFF層 Backend層
    API粒度 アプリのユースケース単位 REST
    APIバージョニング する しない

    View Slide

  41. RESTにこだわり過ぎないことが⼤事
    集約処理をBackend(SQL)でやったほうが圧倒的に楽なときはBackendに任せる
    • 異なるリソースまたいだソート + ページネーション処理など
    API全体のパフォーマンス影響が⼤きいとき
    • API版のN+1問題は必ず避ける(BFFの⽤途に合わせてBackend APIを作る)
    • リソースのうち、計算負荷の⾼いプロパティはBFFから任意取得できるようにする
    • Backend APIに
    fi
    eldsパラメータを設けるなど

    View Slide

  42. RESTにこだわり過ぎないことが⼤事
    集約処理をBackend(SQL)でやったほうが圧倒的に楽なときはBackendに任せる
    • 異なるリソースまたいだソート + ページネーション処理など
    API全体のパフォーマンス影響が⼤きいとき
    • API版のN+1問題は必ず避ける(BFFの⽤途に合わせてBackend APIを作る)
    • リソースのうち、計算負荷の⾼いプロパティはBFFから任意取得できるようにする
    • Backend APIに
    fi
    eldsパラメータを設けるなど
    BFFとBackend、互いの歩み寄りが⼤事 💪

    View Slide

  43. API設計
    BFF層 Backend層
    APIの粒度 アプリの使いやすい粒度 REST
    APIバージョニング する しない

    View Slide

  44. BFFのAPIバージョニング
    • モバイルアプリ向けAPIは後⽅互換性のサポートが必要
    • アプリはユーザがアップデートしない限り、古いバージョンが使われ続ける
    • よって、古いバージョンのAPIも使われ続ける可能性がある
    • バージョン指定はAcceptヘッダで⾏う⽅式を採⽤
    • Accept:application/vnd.hpb-app-BFF.v1.0+json


    • バージョンアップは限局分岐(APIごと)で実施

    View Slide

  45. API設計
    BFF層 Backend層
    APIの粒度 アプリの使いやすい粒度 REST
    APIバージョニング する しない

    View Slide

  46. BackendのAPIバージョニング
    • バージョニングはしないで、後⽅互換性が壊れるときはBFFと連携して対応する思想
    • 社内のシステムから呼ばれるAPIなので、こういった選択肢が取れる
    • "後⽅互換性サポートコスト"と"チーム間のコミュニケーションコスト"のトレードオフ
    • 組織構成や規模に合わせて選ぶと良い

    View Slide

  47. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  48. 技術選定
    BFF Backend
    ⾔語 Kotlin 1.3 AdoptOpenJDK 11
    アプリケーションフレームワーク
    Sprint Boot2

    Spring5系(WebFlux)
    Sprint Boot2

    Spring5系(WebMVC)

    View Slide

  49. 技術選定
    BFF Backend
    ⾔語 Kotlin 1.3 AdoptOpenJDK 11
    アプリケーションフレームワーク
    Sprint Boot2

    Spring5系(WebFlux)
    Sprint Boot2

    Spring5系(WebMVC)

    View Slide

  50. BFF層の技術選定のポイント
    アプリチームのエンジニアが開発する
    • できるだけアプリエンジニアの使い慣れた技術を選ぶと良い
    BFFは1エンドポイントにつき複数のBackend APIを並列に呼び出す
    • I/O待ちが多い
    • Non-Blocking I/Oの扱えるフレームワークを選ぶと良さそう

    View Slide

  51. BFFの⾔語選定
    • ⾔語はアプリエンジニアの使い慣れたものにしたいのでKotlinかSwiftの⼆択
    • サーバサイドSwiftはまだあまり聞かないのでリスキー 😨
    • KotlinならサーバサイドJavaの資産を活⽤できる! 🙆
    • 組織的にもJava(JVM)の開発・運⽤知⾒が多い 🙆
    Kotlinを採⽤!

    View Slide

  52. BFFのフレームワーク選定
    • ⾔語はKotlinでフレームワークは実質Spring⼀択で考えた
    • ⾔語にこだわらなければnode.jsやGolangも候補だった
    • Springは5.0からKotlinを正式にサポート 🙆
    • Spring WebFluxならNon-Blocking I/Oのサポートも 🙆
    • Spring WebFluxはReactorの学習コストが懸念だが、

    AndroidチームがRxJavaを利⽤していたので⼤丈夫そう 🙆
    Spring WebFluxを採⽤!

    View Slide

  53. BFFの技術選定の振り返り
    • 「ほんとにアプリチームでAPI開発できるのか?」という懸念はあったが、

    問題なく開発できそうなことがわかってきている
    • ほとんどKotlinとReactorの知識だけで書ける
    • Springは下回りさえ整えてしまえば、API実装で意識することはほぼない
    • 特にAndroidエンジニアにとってはかなりハードルが低そう
    • iOSエンジニアについては要検証...
    • 実際Androidエンジニアに実装してもらったが

    「これならいけそう」という感想を得ている 👏

    View Slide

  54. BFFの技術選定の振り返り
    • Kotlin x Springは違和感なく開発できている 😄
    • 「KotlinだからSpringが活かせない」ということは全くない
    • 「SpringだからKotlinが活かせない」とういことも全くない
    • 個⼈的に気に⼊ってるポイント
    • SpringはNonnull/Nullableがしっかりアノテートされているので、

    KotlinのNull安全性が活きる 💪
    • Spring公式提供の拡張関数群も充実
    • 今後は、spring-fu/kofuのようなDSLにも期待

    View Slide

  55. 技術選定
    BFF Backend
    ⾔語 Kotlin 1.3 AdoptOpenJDK 11
    アプリケーションフレームワーク
    Sprint Boot2

    Spring5系(WebFlux)
    Sprint Boot2

    Spring5系(WebMVC)

    View Slide

  56. Backendの技術選定
    • あまりこった検討はなし
    • Java
    • 要員確保の観点
    • 組織的にもJavaエンジニアが多い 🙆
    • Spring Boot + Sprint WebMVC
    • 社内事例のあった技術スタックを素直に採⽤

    View Slide

  57. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  58. ソフトウェアアーキテクチャ
    Backend
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    通常のWebアプリ
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    BFF

    View Slide

  59. ソフトウェアアーキテクチャ
    Backend
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    通常のWebアプリ
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    BFF

    View Slide

  60. ソフトウェアアーキテクチャ
    Backend
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    通常のWebアプリ
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    BFF

    View Slide

  61. APIにおけるプレゼンテーション層の扱い
    APIではプレゼンテーション層が薄くなる
    • Viewとユーザのインタラクションはないため、そのあたりのハンドリング実装が不要
    • APIのView = レスポンスのJSON(or XML)
    • Java→Viewの変換はJacksonが担うため、⾃前で実装することはほぼない
    プレゼンテーション層はアプリケーション層に統合する形で設計

    View Slide

  62. APIにおけるプレゼンテーション層の扱い
    ユースケースの再利⽤性を考慮する必要がない
    • APIエンドポイントの単位がユースケースと1:1で対応する
    • Controller(プレゼンテーション層)とUsecase(アプリケーション層)を

    密結合気味に作ってもデメリットが⼩さい
    プレゼンテーション層はアプリケーション層に統合する形で設計

    View Slide

  63. Backendのアプリケーション層実装例
    @Usecase


    @AllArgsConstructor


    public class ReservationUsecase {


    /**


    * 予約一覧を返却する


    */


    @Nonnull


    public GetReservationResponse getReservations(...) {


    //...


    // GetReservationResponse = レスポンス構造を表すレスポンスDTO(View)


    // Usecase(アプリケーション層)の時点でViewのインスタンスを返却する


    return GetReservationResponse.builder()


    .totalCount(count)


    .reservations(reservationDtos)


    .build();


    }
    • アプリケーション層の時点でView(Json)と対応するDTOを返す

    View Slide

  64. Backendのアプリケーション層実装例
    • ControllerはUsecaseの返り値をResponseEntityにラップして返すだけ
    @RestController


    @AllArgsConstructor


    public class ReservationController {


    private final ReservationUsecase usecase;


    /**


    * 予約一覧を返却する


    */


    @GetMapping


    public ResponseEntity getReservations(...) {


    final var body = usecase.getReservations();


    return ResponseEntity.ok()


    .body(body);


    }

    View Slide

  65. ソフトウェアアーキテクチャ
    Backend
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    通常のWebアプリ
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    BFF

    View Slide

  66. BFFのドメイン層とインフラストラクチャ層
    ドメイン層
    • 業務ロジックがBackendに移譲されるため薄くなる
    インフラストラクチャ層
    • Backendレスポンス→ドメインモデルの変換が必要ないため薄くなる(後述)
    両層ともに薄くなるので1つに統合

    View Slide

  67. BFFにドメインモデルは不要(だと思う)
    "ドメインモデル貧⾎症"になりやすい
    • BFFには業務ロジックが存在しないため
    データモデルとViewの間に作る中間表現としてのメリットが⼩さい
    • Backend層:リレーショナルデータモデル(データモデル)→Java(ドメインモデル)→JSON(View)
    • BFF層:JSON(データモデル)→Kotlin(ドメインモデル)→JSON(View)の変換
    • データモデルの表現⼒(型やデータ構造)が⾼い
    • データモデルとViewのインピーダンスミスマッチも⼩さい

    View Slide

  68. BFFのアーキテクチャ
    アプリケーション層
    • Backendの返すリソースを加⼯し、集約して返す層
    ドメイン層
    • BackendAPIの呼び出しとリソースの返却を⾏う層
    プレゼンテーション層
    ドメイン層
    インフラストラクチャ層
    アプリケーション層
    BFF

    View Slide

  69. アプリケーション層 ドメイン層
    BFFのアーキテクチャ
    Repository
    Repository
    Repository
    Service
    Service Backend API
    リソース
    リソース
    リソース
    リソース
    リソース
    リソース
    集約結果
    集約結果

    View Slide

  70. BFFのドメイン層実装例
    • RepositoryはただAPIを呼んで返すだけ
    • JSON→Kotlin(DTO)間の変換はすべてJacksonが担う
    @Repository


    class HairSalonRepository(private val api: HairSalonApi) {


    @Cacheable(cacheNames = ["publishing"], key = "'/hair-salons/' + #id")


    fun getById(id: String): Mono = api.getHairSalon(id)


    }

    View Slide

  71. BFFのアプリケーション層実装例
    fun getMessageBox(userId: String, salonId: String): Mono =


    clientSalonRepository.getById(salonId)


    .flatMap { clientSalon ->


    salonRepository.getById(salonId)


    .map { it.toDto() } // サロンが掲載中なら掲載情報を使って返却する


    // 非掲載(掲載情報の取得に失敗した)ならサロンボードの登録情報を使って返却する


    .onErrorResume { Mono.just(clientSalon.toDto()) }


    }


    // メッセージの検索と、未読数の取得を行う


    .flatMap { messageRepository.getMessagesBySalonId(userId, salonId) }


    .map { (salon, response) ->


    HairMessageBox(


    total = response.total,


    salon = salon,


    messages = response.messages.map { it.toDto() }


    )


    }
    • Serviceの実装例、複数のAPI(Repository)を呼び出して結果を集約していく

    View Slide

  72. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  73. 現在のAPI開発体制
    • アプリチームによるBFF層の開発体制構築はこれから
    • 現在は層分割を進めてきたメンバがAPIチームとして独⽴
    • アプリチームと共にエンハンス案件実施を⾏っている
    モバイルアプリ

    向けAPI
    Webアプリ
    アプリチーム(8名) サーバサイドチーム(数⼗名)
    モバイルアプリ
    Backend API
    BFF API
    APIチーム

    View Slide

  74. • e.g. Spring Bootのアップデート
    • アプリチームにこれを任せるのはスキル的に難しそう
    • 技術的なサポート体制構築が必要になる
    BFF開発体制構築の課題(1/2)
    アーキテクチャレベルの開発課題への対応が難しい

    View Slide

  75. BFFからBackendにかける負荷に変化があるときは、変更を共有する必要がある
    • 例えば集約するデータが増える(= Backend APIの呼び出しが増える)とき
    Backendチームによるレビュー体制が必要
    • 新しいBackend APIを作る必要はないか?
    • Backendサーバのスケールアップ/アウトは必要ないか?
    BFF開発体制構築の課題(2/2)
    Backendにかかる負荷を無視できない

    View Slide

  76. 実は今の体制が最適?
    • 課題を踏まえると、今の体制が最適なのでは?という気持ちもある
    • BFF層の開発オーナーをAPIチームとして

    「アプリチームがBFF APIにコミットする⽂化や仕組み」を作るほうが効果的では?
    • 模索中...
    アプリチーム(8名)
    モバイルアプリ
    Backend API
    BFF API
    APIチーム
    Pull Request

    View Slide

  77. 前提1:BFFの開発は、DBにかかる負荷を気にせず⾏えると嬉しい
    前提2:BFFの開発で加わる変更の⼤半は参照系
    • 表⽰要件に関するロジックだけをもたせているので
    • つまり参照負荷への対策が⾏うことが重要
    前提3:BFF/Backend構成はSQLチューニングが難しい
    • BackendはREST APIを提供し、BFFはそれを様々な形で組み合わせる
    • そのため、BFFからの使い⽅に合わせたSQLチューニングというのは難しい
    余談:BFF/Backend構成はリードレプリカのスケールアウトがキモ?

    View Slide

  78. • こういった前提を踏まえると

    「参照のためのDBリソースを増やす = リードレプリカのスケールアウト」

    がBFF/Backend構成のキモなのではないか?と思える。
    • ちなみに、ホットペッパービューティーではOracle DBを利⽤しているため

    スケールアウトが難しい 😅(※ インスタンス課⾦のため)
    • Backendレスポンスをキャッシュするなど、別の負荷対策が重要になってくる
    余談:BFF/Backend構成はリードレプリカのスケールアウトがキモ?

    View Slide

  79. アジェンダ
    1. BFFとは何か?
    2. BFF/Backend分割の⽬的
    3. BFF/Backend分割の⽅針
    4. BFF/Backendの設計・実装
    • API設計
    • 技術選定
    • ソフトウェア設計・実装
    5. BFF/Backend構成の開発体制
    6. まとめ

    View Slide

  80. まとめ
    • モノリシックなアプリ向けAPIをBFF層とBackend層に分割しました
    • BFF層の分割⽅針/APIの設計・実装はアプリチームの視点で考えることが重要
    • BFF層をアプリチームで開発できることは理想だが、現実には難しそう
    • 現在模索中...
    • 興味がある⽅、ぜひ議論しましょう 💪

    View Slide

  81. WE ARE HIRING

    View Slide

  82. 🎉
    Ta-da!
    You've read everything there is to read.

    View Slide