Slide 1

Slide 1 text

スピーカー名 DartによるBFF構築・運用 〜 Dart Frog × Melos 〜 もぐもぐ / K9i

Slide 2

Slide 2 text

自己紹介

Slide 3

Slide 3 text

もぐもぐ ↓こんなの

Slide 4

Slide 4 text

もぐもぐ - Ryotaro Onoue - なんでもぐもぐにしたのか覚えてません - 食べるのは好きです - ゆめみのFlutterエンジニア - 2023年4月に新卒として入社 - Flutter/Dart歴 3年

Slide 5

Slide 5 text

もぐもぐ - 地震関連のアプリ開発してます - 今年中にアプリストアでリ リース予定

Slide 6

Slide 6 text

K9i

Slide 7

Slide 7 text

K9i - Kota Hayashi - K9iはK8s(Kubernetes)とかL10n(Localization)と同じ感じ - Kota->Tako->🐙 - K9iはケーナインアイだがいいづらいので、林呼び推奨 - ゆめみのFlutterリードエンジニア - 1社目:Androidなど(この時期に趣味でFlutterをはじめた) - 2社目:Flutter - 3社目:今年の5月からゆめみ - Flutterは4年目くらい

Slide 8

Slide 8 text

K9i - RiverpodのChangelogに稀に生息

Slide 9

Slide 9 text

会社の紹介

Slide 10

Slide 10 text

株式会社ゆめみ - 公式アカウントの大喜利で有名😅

Slide 11

Slide 11 text

ゆめみFlutterギルド - イベントやっとります

Slide 12

Slide 12 text

アジェンダ

Slide 13

Slide 13 text

アジェンダ(1/3) 1. Dartバックエンドの世界 a. Dartのおさらい b. Dartバックエンドフレームワークの紹介 c. BFFとは 2. プロジェクトの背景 a. ゆめみ参入の経緯 b. バックエンドの構成変更 c. Flutter向けBFFの方針 前半

Slide 14

Slide 14 text

アジェンダ(2/3) 3. 技術スタックの紹介 a. Flutterチーム担当領域のプロジェクト構成 b. Dart Frog解説 c. Melos解説 4. 実践した感想 a. Dockerのつらみ b. [TODO] 後半

Slide 15

Slide 15 text

アジェンダ(3/3) 5. Liveデモ a. [TODO] 6. まとめ 後半

Slide 16

Slide 16 text

1. Dartバックエンドの世界

Slide 17

Slide 17 text

Dartのおさらい

Slide 18

Slide 18 text

Dartとは - Googleが開発 - 2011年10月10日に登場

Slide 19

Slide 19 text

Dartのこれまで(超ダイジェスト) - JavaScriptの代替となることを目的に作られた - 2011年末までにVMがChromeに統合される予定だった - 普及は進まず2015年にはChrome統合を断念 - Skyフレームワーク(Flutterの前身)がJavaScriptの変わりとなる言語と 探していたところDartと出会う - 2015年にSkyがDartをはじめて導入 - 以降Flutterとともに成長し今に至る

Slide 20

Slide 20 text

Dartバックエンドという選択肢 - Flutterの普及に伴いバックエンドもDartで開発したい欲求 - 言語を統一することで様々なメリット - 同じメンバーがフロントエンドもバックエンドも開発 - コードの共有・再利用 - ツール・ライブラリの共通化 - etc…

Slide 21

Slide 21 text

Dartバックエンド フレームワークの紹介

Slide 22

Slide 22 text

Aquaduct - 概要 - 懐かしかったので紹介(知ってたら古参?) - Stable Kernelが2018年に開発 - 2021年に開発中止されリポジトリはPublic archive - Conduct - AquaductのFork - 活発に開発されてはなさそう?(最終更新半年前)

Slide 23

Slide 23 text

Serverpod - Serverpod社が開発するFlutter向けのアプリサーバー - トップページに「The missing server for Flutter」とありFlutterを 強く意識している - 2021年に発表され、2023年1月31日に1.0になった - CLIでプロジェクトを作成するとFlutterアプリとバックエンドが両方作成さ れる - 後述するDart Frogなどに比べ多機能な印象

Slide 24

Slide 24 text

Shelf - Dartチームによって開発されているサーバーフレームワーク - 0.1.0は2014年に公開 - Shelf本体は軽量 - 複数のShelf用パッケージを組み合わせて使うモジュール方式 - shelfのリポジトリだけでも複数のパッケージが存在

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

Dart Frog - VGV(Very Good Ventures)が開発しているサーバーフレームワーク - 開発元がFlutter界隈で有名なので注目されている - 2022年に発表され、2023年8月2日に1.0.0になった - Shelfをベースに構築されている、Shelf同様軽量 - こちらも複数パッケージを組み合わせるモジュール方式 - Shelfをより便利に使えるような機能がある - 技術スタック紹介の章で説明

Slide 27

Slide 27 text

BFFとは

Slide 28

Slide 28 text

BFFとは - BFF(Backend For Frontend) - 初めて名前を聞くと言う人もいるかも? - フロントエンド(アプリ含む)とバックエンドの中間に置かれるサーバー - ???

Slide 29

Slide 29 text

BFFの例1:バックエンドが複数

Slide 30

Slide 30 text

BFFの例2:フロントエンドが複数

Slide 31

Slide 31 text

BFFとは - メリット - APIの集約 - 複数のバックエンドを一つのAPIでフロントエンドに提供 - 特定のフロントエンドに特化 - WebにはGraphQL、アプリにはREST - 開発言語も対応するフロントエンドと揃えたりできる - デメリット - 開発コスト - 複雑・冗長

Slide 32

Slide 32 text

2. プロジェクトの背景

Slide 33

Slide 33 text

ゆめみの参入の経緯

Slide 34

Slide 34 text

参入プロジェクト - 介護・看護分野の企業と労働者のマッチングサービス - PMF(プロダクトマーケットフィット)の段階 - フロントエンドは3種類存在 - 企業用Webフロントエンド - 労働者用Webフロントエンド - 労働者用モバイルアプリ(これを担当)

Slide 35

Slide 35 text

参入前のプロジェクトのメンバー - バックエンド、PMなど:顧客企業の方がフルタイム稼働 - ゆめみはクライアントワーク - Webフロント:ゆめみのフロントメンバー(別チーム)が日中稼働 - モバイルアプリ:副業メンバーが夜間など不規則な稼働

Slide 36

Slide 36 text

参入前の課題 - モバイルアプリの開発メンバーが不規則な稼働 - クライアント企業の方とコミュニケーションがとりづらい - 思うようにモバイルアプリ開発が進んでいなかった - Flutter・Dart得意なメンバー不在 - 全体的に負債の塊 - ゆめみのFlutterギルド参入で課題を解決したい - 今年8月〜

Slide 37

Slide 37 text

バックエンドの構成変更

Slide 38

Slide 38 text

バックエンドの構成変更 - プロジェクト参入次点でバックエンドの構成変更が進行中 - PMF期に生じた負債の解消

Slide 39

Slide 39 text

元々の構成

Slide 40

Slide 40 text

元々の構成 旧バックエンドは元々モバイルアプリ 用に作られたが、Webからも使われ るようになってしまう 特定のフロントエンドのための分岐と うで複雑に

Slide 41

Slide 41 text

目的とする構成

Slide 42

Slide 42 text

目的とする構成 フロントエンドごとに BFFを作り、特定 のフロントエンドのためのロジックを 移譲 旧バックエンドは廃止

Slide 43

Slide 43 text

Flutter向けBFFの方針

Slide 44

Slide 44 text

Flutterチームの担当

Slide 45

Slide 45 text

Flutter向けBFFの方針 - 実は作り途中のBFFがあったが… - 色々と課題… - 廃止されるまでは旧バックエンドも部分的に使う - Dartで統一 - Jsonをやり取りするクラスをクライアントと共通化 - せっかく新規に作るので気になる技術を試す - Dart Frog、Melos - 賛否有りそうだけど大事

Slide 46

Slide 46 text

Flutter向けBFFの方針

Slide 47

Slide 47 text

Flutter向けBFFの方針 旧バックエンドを当分は直接利用 いずれは消える

Slide 48

Slide 48 text

Flutter向けBFFの方針 初期リリースでは一部のエンドポイン トラップ(とりあえず動かすため)

Slide 49

Slide 49 text

3. 技術スタックの紹介

Slide 50

Slide 50 text

Flutterチーム担当領域の プロジェクト構成

Slide 51

Slide 51 text

リポジトリ・パッケージ構成

Slide 52

Slide 52 text

主な利用技術 - Melos - マルチパッケージ構成の管理に利用 - Dart Frog - BFFの実装に利用 - Freezed、JsonSerializable - クライアントとBFFで共有する通信用の型で利用 - 一般的だと思うので解説しません🙏

Slide 53

Slide 53 text

Melos解説

Slide 54

Slide 54 text

マルチパッケージとは - 複数のDartパッケージでプロジェクトを構成する手法 - 機能やレイヤーごとのディレクトリを作るのではなく、パッケージに切 り出す - パッケージごとにリポジトリを作ると管理が大変なため、1つのリポジトリで 複数パッケージを管理するのが一般的 - モノレポともいう

Slide 55

Slide 55 text

マルチパッケージ利点 - 大規模なアプリで機能・レイヤーごとにパッケージを分ける - 関心の分離 - 意図しない依存を防ぎやすい - 共有コードをパッケージに切り出せる - 今回やりたかったこと

Slide 56

Slide 56 text

Melosとは - Dartでのマルチパッケージを支援するコマンドラインツール - Invertaseが開発しており、有名パッケージの開発にも使われている - Riverpod、FlutterFireなどが利用 - Melosの開発にもMelosが使われている - 注意:マルチパッケージならMelos必須というわけではない - 使ってないリポジトリも - Flutter News Toolkit、I/O Flip

Slide 57

Slide 57 text

Melosのはじめかた - グローバルにインストール - dart pub global activate melos - プロジェクトのルートにmelos.yamlを作る - melosのコマンドが使えるようになる

Slide 58

Slide 58 text

Melosの機能 - Commands - Filter - Scripts

Slide 59

Slide 59 text

Commands - モノレポをやりやすくするいくつかのコマンドがある - bootstrap / clean - exec - list - publish - run - version

Slide 60

Slide 60 text

Commands - モノレポをやりやすくするいくつかのコマンドがある - bootstrap / clean - exec - list - publish - run - version これらを紹介

Slide 61

Slide 61 text

bootstrap / clean - 複数パッケージに対してpub get - pubspec_overrides.yamlの用意 - リポジトリ内の依存を相対パスでoverrideして開発中バージョンを使 うようにする - 問題に気づきやすくなるなど利点がある - cleanはbootstrapの逆

Slide 62

Slide 62 text

exec - モノレポ内の複数のパッケージに対して同じコマンドを実行 - これがないと一々ディレクトリ移動してbuild_runner実行みたいにな る - 後述するfilter機能と組み合わせる

Slide 63

Slide 63 text

list - モノレポ内のパッケージをリスト表示 - 依存関係などを簡単に確認

Slide 64

Slide 64 text

publsh - モノレポ内のパッケージをpub.devに公開しやすくするコマンド - アプリ作る分には使わない

Slide 65

Slide 65 text

run - 後述するScripts機能を実行するコマンド

Slide 66

Slide 66 text

version - Conventional Commitsの作法に従っている場合に自動でバージョニン グができる - 「feat: hoge」みたいなcommit - !をつけると破壊的変更としてメジャーバージョンがあがるなどのルー ルがある(feat!: hoge) - tagで前回からの差分を判断 - 手動バージョニングにも使える

Slide 67

Slide 67 text

Filter - Commandsの対象パッケージを絞り込む機能 - melos bootstrap --no-privateなら--no-private部分 - いくつかのフィルターがある - scope:特定の文字列を含むパッケージのみ - depends-on:特定のパッケージに依存してるパッケージのみ - 他にも色々

Slide 68

Slide 68 text

Scripts - melos.yamlにスクリプトを定義しておきrunコマンドで実行できる - よく使うものを登録しておき、CIからも使うと良い感じ

Slide 69

Slide 69 text

Dart Frog解説

Slide 70

Slide 70 text

Dart Frog(再掲) - VGV(Very Good Ventures)が開発しているサーバーフレームワーク - 開発元がFlutter界隈で有名なので注目されている - 2022年に発表され、2023年8月2日に1.0.0になった - Shelf上に構築されており、Shelf同様軽量 - こちらも複数パッケージを組み合わせるモジュール方式 - Shelfをより便利に使えるような機能がある - 技術スタック紹介の章で説明

Slide 71

Slide 71 text

Dart Frogのはじめかた - グローバルにインストール - dart pub global activate dart_frog_cli - DartのコマンドラインツールなのでMelosと同じ - dart_frog create my_project - 最低限のDart Drogのコード - dart_frog devですぐ動く

Slide 72

Slide 72 text

Dart Frogの基本機能・特徴 - ホットリロード対応 - ファイルベースルーティング - 便利なクラス - Middleware - DI - テストの容易性

Slide 73

Slide 73 text

ファイルベースルーティング - ディレクトリ構成がそのままルーティングに対応する - ”/”と”/hello”のエンドポイントに対応させる場合 - 画像のどちらか - 競合したらビルド失敗等で分かる

Slide 74

Slide 74 text

エンドポイントの追加方法 - もちろん手動でファイルを追加すればできるが - コマンドで追加も可能 - dart_frog new route "/hello"

Slide 75

Slide 75 text

追加直後のエンドポイント - RequestContextを受け取ってResponseを返す関数

Slide 76

Slide 76 text

エンドポイントの追加方法 - もちろん手動でファイルを追加すればできるが - コマンドで追加も可能 - dart_frog new route "/hello" - dart_frog_cliのコマンドはMasonで実現されている - Masonはテンプレートからコードを生成するDartツール - ファイルベースルーティングなのはテンプレートからの生成との 相性が良いからかも?

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

便利なクラス - Dart FrogはShelfのクラスをラップして便利にしている - 先程のRequestContext

Slide 79

Slide 79 text

RequestContext

Slide 80

Slide 80 text

RequestContext - 内部的にshelfのRequest

Slide 81

Slide 81 text

body、jsonなどよく使うであろうメソッ ドが事前に用意されている

Slide 82

Slide 82 text

Middleware - ディレクトリごとに配置でき、サブディレクトリ含めて前処理を行える

Slide 83

Slide 83 text

Middleware - handlerのuseにMiddleware(requestLogger)を渡す - 用途 - ロガー - 共通のエラー処理 - DI

Slide 84

Slide 84 text

Middlewareのチェイン - useはMiddlewareを受 け取りHandlerを返すの でチェインできる

Slide 85

Slide 85 text

補足:Shelfのリソースを活用

Slide 86

Slide 86 text

DI - providerというMiddlewareでDIできる

Slide 87

Slide 87 text

DI - middlewareでこうして

Slide 88

Slide 88 text

DI - 利用側はRequestContextから取得

Slide 89

Slide 89 text

テストの容易性 - プロジェクト初期化次点でmock_tailが追加されている

Slide 90

Slide 90 text

テストの容易性

Slide 91

Slide 91 text

テストの容易性 RequestContextはmocktailでモッ ク

Slide 92

Slide 92 text

テストの容易性 onRequest関数をテストすれば良い

Slide 93

Slide 93 text

テストの容易性 expectで確認!で完了

Slide 94

Slide 94 text

もぐもぐタイム

Slide 95

Slide 95 text

4. 実践した感想

Slide 96

Slide 96 text

サンプルコード - 実際のソースコードを見せることはできないので、簡素化したサンプルプ ロジェクトを作成しました - GitHub Repository Search APIの検索結果をBFFでキャッシュします - https://github.com/YumNumm/dart-frog-github-repository-se arch - 後でライブデモをするので そこで詳しくお話します

Slide 97

Slide 97 text

サンプルコード

Slide 98

Slide 98 text

1. バックエンド と BFF のクライアントを同じように実 装できた - アプリがBFFを叩く部分 と BFFがバックエンドAPIを叩く部分で同じパッ ケージを使った - 実装が似ているのでキャッチアップしやすい - retrofitを利用してクライアントを実装しました

Slide 99

Slide 99 text

2. API型定義の取り方 - 実際の案件では、 Flutter App と BFF のリポジトリが別 - Flutter Appは BFFのリポジトリにある 型定義へ依存している - どうするねん!

Slide 100

Slide 100 text

2. API型定義の取り方

Slide 101

Slide 101 text

2. API型定義の取り方 - bff_api_typesをpub.devで公開すれば良いんじゃ!? → インシデント確定演出 - git submoduleで置いて、path packageとして扱う → 微妙 - pubspec.yamlのgit packageとして扱う → git経由の依存関係 よござんす👍

Slide 102

Slide 102 text

API型定義の取り方 - bff_api_typesをpub.devで公開すれば良いんじゃ!? → インシデント確定演出 - git submoduleで置いて、path packageとして扱う → チョット汚い - pubspec.yamlのgit packageとして扱う → よござんす👍 CI環境どうする!? - actions/checkoutでAppのコードをクローンしている - BFFのレポジトリはクローンできない

Slide 103

Slide 103 text

2. API型定義の取り方 - GitHub Deploy Keyのすゝめ - Deploy Keyとは? - 単一リポジトリへのアクセス(R, R/W)を許可するSSHキー - サーバ上でプロジェクトを起動するためのもの - publicな部分をリポジトリに privateな部分をサーバに配置 - ユーザに紐づかないため、管理が楽 cf. https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/managing-deploy-keys

Slide 104

Slide 104 text

2. API型定義の取り方 - GitHub Deploy Keyのすゝめ - GitHub Actions内で SSHのprivate keyを展開 - SSHできる用意をしてあげる - flutter pub get ヨシ👍

Slide 105

Slide 105 text

3. Docker を使う - Docker とは? - 仮想マシン(VM)とは違い、コンテナという単位でアプリケーションを実 行できる - Dockerfileを書くことでコンテナビルド方法をコードで記述できる (IaC: Infrastracture as Code) - クラウドでもローカルでも実行できる - 実行環境依存のものを減らすことができる https://aws.amazon.com/jp/docker/ より

Slide 106

Slide 106 text

3. Docker を使う - プロジェクトでAWS Fargate上でデプロイする必要があった - 環境に依存せずにローカルでデバッグできるようにしたかった

Slide 107

Slide 107 text

OrbStackのススメ (余談) - Docker DesktopとWSLの代替品 - macOSでDocker ContainerとLinux マシンを動かすことができるApp - Docker Desktopを使うよりも高速・軽量・シンプル https://orbstack.dev/ - 個人利用であれば無料、 商用利用は$8/month per user - macOS専用

Slide 108

Slide 108 text

3. Dart FrogのDockerfile 生成 - dart_frog build で build/Dockerfileが生成される - buildコマンドを実行するためには dart_frog が実行できることが前 提 (ホスト環境に依存してはいけない) - build/* をリポジトリに含めると、差分がすごいことになるので含めた くない → 自分でDockerfile書きますわ

Slide 109

Slide 109 text

バイナリをビルドするための Dartコンテナ バイナリを実行するためのコンテナ builder scratch

Slide 110

Slide 110 text

バイナリをビルドするための Dartコンテナ バイナリを実行するためのコンテナ builder scratch ローカルで依存しているライブラリの pubspec.yamlと pubspec_overrides.yaml をコピー ローカルで依存しているライブラリの全体をコピー

Slide 111

Slide 111 text

バイナリを実行するためのコンテナ バイナリをビルドするための Dartコンテナ builder scratch builderで生成されたバイナリをコピーして 実行する

Slide 112

Slide 112 text

5. LIVEデモ

Slide 113

Slide 113 text

LIVEデモ - 実際のソースコードを見せることはできないので、簡素化したサンプルプ ロジェクトを作成しました - GitHub Repository Search APIの検索結果をBFFでキャッシュします - GitHub Personal Access Tokenセット済み -> レートリミット緩和 - 仕様 - GET /api/v1/repository/search : リポジトリ検索 - param: query={検索文字列} - https://github.api.yumnumm.dev にデプロイ済み

Slide 114

Slide 114 text

LIVEデモ

Slide 115

Slide 115 text

LIVEデモ GitHub Repository Search API BFF, App

Slide 116

Slide 116 text

LIVEデモ - dart_frog create - dart_frog create hoge でプロジェクトを作成できる - dart_frog dev で実行 - localhost:8080でアクセスできます - localhost:8181でDevToolへアクセスできます demo/1 Branch

Slide 117

Slide 117 text

LIVEデモ - melos bootstrap - melos bootstrap で pubspec_overrides.yamlが生成される - melos clean でpubspec_overrides.yamlが消える - melos.yamlで記述したbuild_runnerスクリプトを実行できる demo/2 Branch - melos bootstrap で pubspec_overrides.yamlが生成される - melos clean でpubspec_overrides.yamlが消える - melos.yamlで記述したbuild_runnerスクリプトを実行できる

Slide 118

Slide 118 text

LIVEデモ - Dart Frog BFF - dart_frog new route hoge でエンドポイントを作成できる - dart_frog dev で開発サーバを起動 - http://localhost:8080/ でアクセスできる - http://localhost:8181/ でDevToolへアクセスできる - api/v1/repository/search の中身を実装していく demo/2 Branch

Slide 119

Slide 119 text

LIVEデモ - Dart Frog × Docker - docker compose up -d /-build でコンテナを起動 - [OrbStackを利用している場合] http://orb.local でコン テナ一覧を見ることができる - main Branch

Slide 120

Slide 120 text

LIVEデモ - Application - 実際にFlutterアプリからアクセスしてみましょう - App: https://gh-repo-search.yumnumm.dev/ - BFF: https://github.api.yumnumm.dev/ (どちらも 2023/11/11 には閉鎖します ) main Branch

Slide 121

Slide 121 text

6. まとめ

Slide 122

Slide 122 text

1章まとめ:Dartバックエンドの世界 - Dart 12年の歴史 - Chrome統合が失敗しオワコン化? - Sky(現Flutter)に採用され復活 - Flutterの盛り上がりによりDartバックエンドの機運が高まる - ServerPod、Dart Frogなどが盛り上がる

Slide 123

Slide 123 text

2章まとめ:プロジェクトの背景 - Flutterチームが夜間稼働でコミュニケーションなどに課題 - ゆめみ参戦 - PMF期に複雑化したバックエンドの構成変更 - 3つのフロントエンドそれぞれのBFF越しに共通バックエンドを叩く構 成にする - Dart Frog x MelosのBFFつくるぞい

Slide 124

Slide 124 text

3章まとめ:技術スタックの紹介 - マルチパッケージ管理ツールMelosを使ってアプリとBFFでパッケージ共 有 - Melos解説 - 複数パッケージに対してコマンド実行などが便利 - Dart Frog解説 - ファイルベースルーティングとMasonによるコード生成 - Shelfのクラスをラップした便利クラス - テストもやりやすい

Slide 125

Slide 125 text

4章まとめ:実践した感想 - バックエンドとBFFのClient実装がほぼ同じ - BFF API 型定義をApp側と共有することで 保守性向上 - モノレポでローカル依存が多いならではの Dockerfileのつらみ

Slide 126

Slide 126 text

5章まとめ:ライブデモ - 実際のプロダクトにBFFを取り込む過程を紹介 - melos, dart_frog を利用することで、高速に開発を進めることができて いる - Dockerを利用してローカルで開発を行うこともできます

Slide 127

Slide 127 text

告知 - この後同じルームでゆめみスポンサーセッション🥳 通称:モリモリ山トリオ

Slide 128

Slide 128 text

Links - https://ja.wikipedia.org/wiki/Dart - https://zenn.dev/mjhd/articles/680a19ae893c1e - https://github.com/stablekernel/aqueduct - https://serverpod.dev/ - https://pub.dev/packages/shelf - https://dartfrog.vgv.dev/ - https://github.com/felangel/mason - https://blog.codemagic.io/writing-your-backend-in-dart / -

Slide 129

Slide 129 text

Links - https://zenn.dev/overflow_offers/articles/20220418-wha t-is-bff-architecture - https://melos.invertase.dev/ - https://www.conventionalcommits.org/ja/v1.0.0/ - スライド内のサンプルプログラム - GitHub API BFF+App: https://github.com/YumNumm/dart-frog-github-reposi tory-search

Slide 130

Slide 130 text

No content