Slide 1

Slide 1 text

ホットペッパービューティーにおける モバイルアプリ向けAPIの 
 BFF/Backend分割 Nawate Ippei @JJUG 2019 Spring #jjug_ccc #ccc_c4

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

背景と課題 • API開発のスピードがアプリ改善スピードのボトルネックになっていたため • APIの開発はアプリチームからの依頼ベースで実施されるが、 
 リソース調整などの要因で開発完了まで3ヶ⽉以上かかっていた • アプリチームの開発サイクルはより早く(1ヶ⽉)、API開発スピードがボトルネックに... モバイルアプリ 
 向けAPI Webアプリ API開発依頼 開発完了 (3ヶ⽉~後) アプリチーム(8名) サーバサイドチーム(数⼗名) モバイルアプリ

Slide 13

Slide 13 text

課題に対する打ち⼿ BFF層 Backend層 モバイルアプリ向けAPI 
 (モノリシック) サーバサイドチーム アプリチーム サーバサイドチーム 分割 APIのBFF/Backend分割を実施し 
 アプリチームのリソースでAPIを開発・リリースできる体制を整えることで ボトルネック(API開発スピード)の改善を狙う

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

BFF/Backend分割の⽅針 ① 各層にどう処理を分担させるか ② 層間の通信をどのように⾏うか BFF層 Backend層 ②どう通信? モバイルアプリ向けAPI 
 (モノリシック) 処理A 処理C 処理B 処理D ①どう分担? ? ? ? ?

Slide 16

Slide 16 text

このように分割することに BFF層 Backend層 表⽰要件に関わる処理 業務ロジック アプリ特有の処理 データソース(DB等) 
 のRead/Write REST API • BFFにアプリ特有の処理や表⽰要件に関わる処理を持たせる • BackendはREST APIを提供、BFFは複数のBackend APIを呼び出し結果を集約

Slide 17

Slide 17 text

BFF層 Backend層 モバイルアプリ向けAPI 
 (モノリシック) 分担 処理A 処理C 処理B 処理D ? ? ? ? ① 各層にどう処理を分担するか? 🤔

Slide 18

Slide 18 text

処理分担のポイント • BFFはアプリチームで⾼速に開発できるようにしたい • 開発(変更)の早さ ≒ 意思決定の早さ(特に⼤きな組織では) • すばやく意思決定するには 
 「他チーム・他システムへの依存・影響を⼩さくする」のが⼤事

Slide 19

Slide 19 text

処理分担のポイント • BFFはアプリチームで⾼速に開発できるようにしたい • 開発(変更)の早さ ≒ 意思決定の早さ(特に⼤きな組織では) • すばやく意思決定するには 
 「他チーム・他システムへの依存・影響を⼩さくする」のが⼤事 アプリチームで変更の意思決定が完結する処理をBFFに持たせる

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

BFF/Backend分割イメージ - Before モバイルアプリ向けAPI 
 (モノリシック) サーバサイドチーム アプリチーム 表⽰要件に関わる処理 • プレゼンテーションロジック • 表⽰要件に合わせたデータ集約 業務ロジック データソース(DB, 検索エンジン) 
 のRead/Write アプリ特有の処理 • アクセストークンの管理など

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

画⾯単位で作るとだめなのか? 🤔 • ӈͷը໘Ͱ͸3ͭͷ"1*ΛฒྻͰݺͼग़͢ • ⼀度の呼び出しで取得できたほうが 
 通信回数も少なくなる • 処理の並列度も下がるのでアプリも楽?

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

技術選定 BFF Backend ⾔語 Kotlin 1.3 AdoptOpenJDK 11 アプリケーションフレームワーク Sprint Boot2 
 Spring5系(WebFlux) Sprint Boot2 
 Spring5系(WebMVC)

Slide 49

Slide 49 text

技術選定 BFF Backend ⾔語 Kotlin 1.3 AdoptOpenJDK 11 アプリケーションフレームワーク Sprint Boot2 
 Spring5系(WebFlux) Sprint Boot2 
 Spring5系(WebMVC)

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

BFFの技術選定の振り返り • 「ほんとにアプリチームでAPI開発できるのか?」という懸念はあったが、 
 問題なく開発できそうなことがわかってきている • ほとんどKotlinとReactorの知識だけで書ける • Springは下回りさえ整えてしまえば、API実装で意識することはほぼない • 特にAndroidエンジニアにとってはかなりハードルが低そう • iOSエンジニアについては要検証... • 実際Androidエンジニアに実装してもらったが 
 「これならいけそう」という感想を得ている 👏

Slide 54

Slide 54 text

BFFの技術選定の振り返り • Kotlin x Springは違和感なく開発できている 😄 • 「KotlinだからSpringが活かせない」ということは全くない • 「SpringだからKotlinが活かせない」とういことも全くない • 個⼈的に気に⼊ってるポイント • SpringはNonnull/Nullableがしっかりアノテートされているので、 
 KotlinのNull安全性が活きる 💪 • Spring公式提供の拡張関数群も充実 • 今後は、spring-fu/kofuのようなDSLにも期待

Slide 55

Slide 55 text

技術選定 BFF Backend ⾔語 Kotlin 1.3 AdoptOpenJDK 11 アプリケーションフレームワーク Sprint Boot2 
 Spring5系(WebFlux) Sprint Boot2 
 Spring5系(WebMVC)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

APIにおけるプレゼンテーション層の扱い ユースケースの再利⽤性を考慮する必要がない • APIエンドポイントの単位がユースケースと1:1で対応する • Controller(プレゼンテーション層)とUsecase(アプリケーション層)を 
 密結合気味に作ってもデメリットが⼩さい プレゼンテーション層はアプリケーション層に統合する形で設計

Slide 63

Slide 63 text

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を返す

Slide 64

Slide 64 text

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); }

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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) }

Slide 71

Slide 71 text

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)を呼び出して結果を集約していく

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

実は今の体制が最適? • 課題を踏まえると、今の体制が最適なのでは?という気持ちもある • BFF層の開発オーナーをAPIチームとして 
 「アプリチームがBFF APIにコミットする⽂化や仕組み」を作るほうが効果的では? • 模索中... アプリチーム(8名) モバイルアプリ Backend API BFF API APIチーム Pull Request

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

• こういった前提を踏まえると 
 「参照のためのDBリソースを増やす = リードレプリカのスケールアウト」 
 がBFF/Backend構成のキモなのではないか?と思える。 • ちなみに、ホットペッパービューティーではOracle DBを利⽤しているため 
 スケールアウトが難しい 😅(※ インスタンス課⾦のため) • Backendレスポンスをキャッシュするなど、別の負荷対策が重要になってくる 余談:BFF/Backend構成はリードレプリカのスケールアウトがキモ?

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

WE ARE HIRING

Slide 82

Slide 82 text

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