Slide 1

Slide 1 text

Cookpad Summer Internship 2022 15-day Tech Course 〜 サーバーサイド編 〜 2022-08-17

Slide 2

Slide 2 text

@satoshi-sanjo (講師) @nekketsuuu (TA) @hiromu-miyazaki (TA) メディアプロダクト開発部 マーケティングサービス開発グループ (toB 向けサービスの開発) 大阪出身 買物プロダクト開発部 流通基盤プロダクト開発グループ EC プラットフォームの流通基盤を作っています 普段は Ruby を書いています 好きな言語は OCaml です レシピサービス開発部 エンジニアリンググループ wangan チーム レシピサービスの基盤っぽいこと やってます。

Slide 3

Slide 3 text

今日のゴール ● BFF、 GraphQL について概念を理解する ○ 今クックパッドでホットなテーマ ● Rails のコードを見て、どこをどう読めばいいかわかるようになる ○ OJT で一度は Rails のコードを読むことになるはず ● 楽しいサマーインターンにする! ○ みんなで仲良く ○ 社員も一緒に仲良くしてくれるとうれしい

Slide 4

Slide 4 text

タイムテーブル ● 10:00 ~ 12:00 講義 ● 12:00 ~ 13:00 お昼 ● 13:00 ~ 15:00 ハンズオン ● 15:00 ~ 17:30 課題 ● 17:30 ~ 18:00 解説

Slide 5

Slide 5 text

iOS の講義で使った API を実際に作ります ● minirecipe ○ レシピ一覧・詳細 ● minihashtag ○ ハッシュタグ投稿 ● 2つのサービスを束ねる API(BFF) ○ クライアントからのリクエスト先を1つにします ○ 2つのサービスに直接リクエストを投げていたのは大変だったはず 作るもの

Slide 6

Slide 6 text

作るもの モバイル
 BFF minirecipe DB REST
 minihashtag DB REST


Slide 7

Slide 7 text

講義で扱う技術要素 ● BFF ● GraphQL ● Ruby ● Rails

Slide 8

Slide 8 text

BFF

Slide 9

Slide 9 text

BFF (Backend for Frontend) とは ● API Gateway パターンの一つ ● フロントエンドと各種マイクロサービスとの間に位置し、フロ ントエンドに返すレスポンスを組み立てる係 ○ 各種サービスの呼び出しを管理 ○ 各種サービスのレスポンスを結合 ● バックエンドとフロントエンドの複雑性を排除するための役 割

Slide 10

Slide 10 text

クライアントから直接通信 Microservice A Microservice B Microservice C モバイル
 PC Web


Slide 11

Slide 11 text

API Gateway pattern API Gateway Microservice A Microservice B Microservice C モバイル
 PC Web


Slide 12

Slide 12 text

BFF モバイル
 BFF - mobile Microservice A PC Web
 BFF - PC Microservice B Microservice C

Slide 13

Slide 13 text

BFFが必要になった背景 - 課題 ● バックエンド視点での課題
 ○ クライアントの多様化の流れ
 ● クライアント視点での課題
 ○ Microservices の流れ


Slide 14

Slide 14 text

● デスクトップが主流だった時代 → モバイルも出てきた
 ● クライアントによって特性が異なる
 ○ PC Web: 画面が大きくて、安定したネットワーク通信が可能
 ○ モバイル(アプリ、Web): 画面が小さくて、ハードウェアリソースに制限
 ● 利用シーンや UI も違うので、必要な情報が異なる
 クライアントの多様化の流れ 昔 近年 etc.

Slide 15

Slide 15 text

● 全種類のクライアントに対して、出し分けをする汎用 API を作るのは大 変
 ○ 各種クライアントに対応するためのロジックの複雑化 
 ○ 影響範囲の肥大化
 ■ 共有しているコードを変更すると各種クライアントにも影響がある 
 ■ 複数のチームに影響のある変更だと 
 ● チームをまたがった調整が必要になる 
 ● コミュニケーションが大変になる
 クライアントの多様化の流れ

Slide 16

Slide 16 text

Microservices の流れ ● Monolith → Microservices になってきた
 ● クライアントの複雑化
 ○ Microservices の種類・インタフェースの管理 
 ■ どういうサービスがどういうインタフェースを持っているのか 
 ■ 変更があったときの互換性をどうするか 
 ■ 複数サービスに直接にリクエストする場合はラウンドトリップタイムの問題も 
 ○ 各 Microservice から得たデータの集約 
 ■ 例: iOS 講義でやったレシピに紐づくハッシュタグの取得、レシピとの結合ロジック 
 ● 攻撃サーフェスが大きくなる
 ○ モバイルから呼び出すには Microservices を Internet に公開する必要がある 


Slide 17

Slide 17 text

BFF ● 1種類のクライアントに特化した層 
 ○ BFF が各種サービスにリクエストを投げて、情報を集約してクライアントに返す 
 ○ クライアントのユースケースに特化したレスポンスを組み立てる 
 ● クライアント・バックエンドの差異を吸収 
 モバイル
 BFF - mobile PC Web
 BFF - PC モバイルチーム PC Web チーム

Slide 18

Slide 18 text

● クライアントは裏側のマイクロサービスに関知しなくて済む 
 ○ リクエスト先が BFF のみだけで済むし、一回のリクエストで済む 
 ○ マイクロサービスのリプレースや仕様変更などがしやすい 
 ● クライアント・バックエンドの責務が明確になる 
 ○ クライアントは BFF から受け取ったデータを表示する(ユーザー体験) 
 ○ バックエンドは要求されたデータを BFF に返す(データの管理) 
 ○ BFF がバックエンドからデータを集めて加工し、クライアントが求める形で提供する(システム間 の差異を吸収する)
 ● 単一のゲートウェイパターンと比べて BFF はシンプルに作ることができる 
 ○ クライアント特化、ユースケース特化なので、汎用性を考える必要がない 
 ● その他様々なメリット(認証、キャッシュ、etc. ) 
 BFF - メリット

Slide 19

Slide 19 text

BFF - デメリット ● 管理するアプリケーションが増える 
 ○ クライアントを開発するチームが管理する場合は、不慣れなサーバーサイド(BFF)を管理するこ とになる
 ● ロジックが重複する
 ○ iOS 向けの BFF、Android 向けの BFF で同じロジックを書くことになる 
 ■ モバイルアプリ BFF として共有する選択肢もある 
 ■ が、実際は微妙に異なることも多いので、まったく同じになるとは限らない 
 


Slide 20

Slide 20 text

クックパッドにおける BFF ● Orcha
 ○ モバイルアプリ ( iOS, Android ) 向け BFF
 ○ Java 製
 ○ https://techlife.cookpad.com/entry/2019-orcha-bff 
 ● next-cookpad-api
 ○ スマートフォン Web 向け BFF
 ○ node.js 製
 ○ https://techlife.cookpad.com/entry/2020/12/01/093000 


Slide 21

Slide 21 text

● Orcha ○ iOS アプリ向けの新規機能を検証したい ○ 新規サービスとして追加 ■ 検証なので撤退の可能性あり ■ 既存サービスは巨大で修正コスト高 ○ iOS からのリクエスト回数を増やしたくない ○ → 前段にオーケストレーション層を用意して、そこでレスポンスを加工する ● next-cookpad-api ○ Web Frontend モダン化プロジェクト ○ API 経由で各種リソースにアクセスするようになった ○ 複数のサービスを呼び分けるのは大変なので BFF を用意 BFF 導入背景 Orcha: https://techlife.cookpad.com/entry/2019-orcha-bff next-cookpad-api: https://techlife.cookpad.com/entry/2020/12/01/093000

Slide 22

Slide 22 text

BFF - クックパッドの場合 BFF - Orcha Microservice A PC web
 cookpad_all/cookpad (rails) (BFF じゃない) Microservice B SP web
 BFF - next-cookpad アプリ(iOS, Android)
 アプリ、SPweb に BFF が一つずつ。 PCweb はシンプルな Rails で別サービスも呼んでいる pantry (recipe API) 共有DB

Slide 23

Slide 23 text

小話 - BFFの開発体制 BFF - Orcha Microservice A PC web
 cookpad_all/cookpad (rails) (BFF じゃない) Microservice B SP web
 BFF - next-cookpad アプリ(iOS, Android)
 pantry (recipe API) 共有DB レシピサービス開発部がオーナーで 複数チームに分かれて開発している (他部署も必要に応じて開発) マイクロサービスは様々あり、一部はレシピサービス開 発部が管理しているものもある

Slide 24

Slide 24 text

小話 - BFFの開発体制 レシピサービス開発部
 ● サービス開発チーム(実際はさらに細かくチームが分かれている)
 ○ バックエンドエンジニア
 ○ モバイルエンジニア
 ● 基盤チーム
 ○ バックエンドエンジニア(wanganチーム, lamdmarkチーム)
 ○ モバイルエンジニア(32番館チーム)


Slide 25

Slide 25 text

小話 - BFFの開発体制 BFF - Orcha Microservice A PC web
 cookpad_all/cookpad (rails) (BFF じゃない) Microservice B SP web
 BFF - next-cookpad アプリ(iOS, Android)
 pantry (recipe API) 共有DB それぞれの BFF に 保守運用的な動きをする 基盤チームがいる

Slide 26

Slide 26 text

小話 - BFFの開発体制 BFF - Orcha Microservice A PC web
 cookpad_all/cookpad (rails) (BFF じゃない) Microservice B SP web
 BFF - next-cookpad アプリ(iOS, Android)
 pantry (recipe API) 共有DB バックエンドエンジニアは SP/PC web のフロント含め開発 することが多い

Slide 27

Slide 27 text

小話 - BFFの開発体制 BFF - Orcha Microservice A PC web
 cookpad_all/cookpad (rails) (BFF じゃない) Microservice B SP web
 BFF - next-cookpad アプリ(iOS, Android)
 pantry (recipe API) 共有DB モバイルエンジニアが BFF も開発することもある (最近はバックエンドエンジニアが担当することが多い)

Slide 28

Slide 28 text

BFF 導入後 ● Orcha ○ アプリ向けの BFF としてアプリ開発の生産性向上に貢献している ○ アプリエンジニアとサーバーサイドエンジニア両方が開発 ■ アプリエンジニアには比較的親しみやすい ■ Rails エンジニアは Java に慣れておらず苦戦しがち ○ Orcha の実装が肥大化 ■ 様々なロジックが BFF に集まっている ■ Orcha の責務を再整理して、不適切なロジックは別の層に移せないか検討中 ● next-cookpad-api ○ 開発が活発な画面から移行中 ■ モダンな環境で快適な開発体験(型がある・脱 jQuery) ○ Orcha と技術スタックが大きく異なるのでコンテキストスイッチが大きい ■ Java x REST ↔ Node.js x GraphQL

Slide 29

Slide 29 text

GraphQL

Slide 30

Slide 30 text

GraphQL とは ● クライアント・サーバーがデータをやり取りするときのイン ターフェースの仕様 ● Facebook 発で 2015 年に OSS 化 ● 特徴 ○ クエリ言語を使用してクライアントがほしいデータを指定 して取得できる ○ Schema による型サポート、コード自動生成

Slide 31

Slide 31 text

GraphQL - 具体例 実際に触って試してみましょう https://docs.github.com/ja/graphql/overview/explorer https://github.com/octocat/Hello-World

Slide 32

Slide 32 text

GraphQL - RESTと比較 ● Github API を使って Issue のタイトルとコメント最初の3件を 取ってくる ● REST の場合と GraphQL の場合を比較してみる

Slide 33

Slide 33 text

GraphQL - RESTと比較 ● Issue のタイトルを取得 https://docs.github.com/ja/rest/issues/issues#get-an-issue

Slide 34

Slide 34 text

GraphQL - RESTと比較 ● Issue のコメントを取得 (略) https://docs.github.com/ja/rest/issues/comments#list-issue-comments

Slide 35

Slide 35 text

GraphQL - RESTと比較 https://docs.github.com/ja/graphql/overview/explorer

Slide 36

Slide 36 text

GraphQL - RESTと比較 REST GraphQL レスポンスの形式 返ってくるまで不明 クエリから推測可能 リクエスト回数 欲しいデータのために 複数回リクエストする必要がある 1回のリクエストで 欲しいデータを取得できる 不要なデータ 返ってくる 必要なデータのみ取得できる ※ REST の場合でも OpenAPI や Garage のようにできないことを補填する方法はあります

Slide 37

Slide 37 text

● API の柔軟性を担保したい
 ● API を呼び出すときに仕様書とにらめっこする必要がある
 GraphQL が必要になった背景 - 課題

Slide 38

Slide 38 text

● 汎用 API は大変
 ○ クライアントの特性によって必要なデータが違う 
 ○ クライアントごとの対応でコードが複雑化 
 ○ 各クライアント用のエンドポイントが必要になったりする 
 ● REST API では必要なデータを取得するためのリクエスト数が多い 
 ○ リソースごとにリクエストが必要
 ○ ラウンドトリップタイム、CPU が問題に 
 ● クライアントの画面特化のエンドポイントを作ると、変化し続ける画面に合わせて API も変 更しないといけない
 ○ UI の微修正でも API の変更が必要 
 API の柔軟性を担保したい

Slide 39

Slide 39 text

● 仕様書を見ながらレスポンスをパースするために型を写経する 
 ○ 例:検索結果画面
 ● nullable / non-null を定義し間違えたりするとアプリがクラッシュする恐れがある 
 仕様書とにらめっこする必要がある

Slide 40

Slide 40 text

● リクエスト時にクライアントが必要なデータを選択して取得できるように
 ● Schema に利用可能な型や操作を定義
 GraphQL が提供したこと

Slide 41

Slide 41 text

● うれしい点
 ○ 一回のリクエストで必要なデータを選んで取ってくることができる
 ○ クライアント、API 双方の柔軟性が向上
 ■ [client] UI の微修正に合わせて API の変更が不要に
 ■ [api] ユースケース特化のエンドポイントを用意しなくていい
 ● 考慮すべき点
 ○ 従来の技術スタックが適用できないケースもある
 ■ ログやメトリクスの収集
 ■ キャッシュ戦略
 ○ パフォーマンス問題への考慮が必要
 ■ 柔軟なクエリによる N+1 問題の対策
 ■ クエリの文字列がリクエストに乗ることでネットワークコストがかかる
 クライアントがデータを選択できるように

Slide 42

Slide 42 text

● クライアントはどういうデータや操作が利用可能なのかを知ることができる
 ○ ドキュメントとして利用可能
 ● Schema を元に、リクエスト・レスポンスの値を検証可能
 ● クライアントコードの自動生成にも利用可能
 
 ● その他の選択肢
 ○ OpenAPI https://spec.openapis.org/ 
 ○ gRPC https://grpc.io/ 
 Schema に利用可能な型や操作を定義

Slide 43

Slide 43 text

● モバイル Web 向けの BFF (next-cookpad) ○ https://techlife.cookpad.com/entry/2020/12/01/093000 ● cookpad mart のドライバー向け Web アプリの API ○ https://techlife.cookpad.com/entry/driver-web-app-in-cookpad-mart-2022 ● 新規サービス「たべドリ」の API 現在のクックパッドでは Garage (GraphQL の前身である Graph API 風)が主流 クックパッドにおける GraphQL

Slide 44

Slide 44 text

● GraphQL はまだ浸透していない ○ user-facing な API の実装は Garage が主流 ○ マイクロサービス間通信は gRPC や REST ● ハードル ○ 既存システムは Garage が主流なので乗り換えコストが高い ■ Garage による選択的フィールド取得、スキーマ生成である程度の要求が 満たせている ○ 既存のロギング、モニタリング、リトライ基盤をそのまま適用できない クックパッドにおける GraphQL

Slide 45

Slide 45 text

GraphQL の基本機能 ● Schema ● Query ● Mutation

Slide 46

Slide 46 text

GraphQL の基本機能 - Schema ● GraphQL の型と操作を定義しているファイル ● Schema を元に、リクエスト・レスポンスの値を検証したり、 クライアントコードの自動生成に利用したりしている ● Schema は手で書く場合と、コードを元に生成する場合があ る ○ 講義で利用する graphql-ruby はコードから Schema ファイルを生 成する

Slide 47

Slide 47 text

GraphQL の基本機能 - Schema

Slide 48

Slide 48 text

GraphQL の基本機能 - Schema ルート型 トップレベルクエリ オブジェクト型 リスト スカラー型 non-null

Slide 49

Slide 49 text

● データを取得するための操作を定義 ● クライアントがほしいデータを宣言的に記述し、取得すること ができる GraphQL の基本機能 - Query Query Response

Slide 50

Slide 50 text

● データに副作用を与える操作を定義 ○ 作成、更新、削除など ● RESTでいうと POST/PUT/DELETE にあたる ○ Query は GET にあたる GraphQL の基本機能 - Mutation

Slide 51

Slide 51 text

GraphQL の基本機能 - Mutation Mutation Query Mutation Schema Response

Slide 52

Slide 52 text

● Universal BFF
 ○ BFFの共通化
 ○ BFFの数が増えるにつれて重複した実装 が増える課題感
 
 ● GraphQL Federation
 ○ BFFにロジックをかかずに設定だけでカ バー
 ○ マイクロサービスが増えるにつれて BFF の実装が肥大化する課題感
 BFF と GraphQL https://www.apollographql.com/docs/apollo-server/ から引用 https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2 から引用

Slide 53

Slide 53 text

Ruby

Slide 54

Slide 54 text

Ruby の特徴 ● すべてがオブジェクト ○ 整数も Integer というクラスのインスタンス ■ 42.class => Integer ■ 42.times { puts "Hello World!" } ● 動的型付け ○ Ruby 3.0 から静的型解析の仕組みも導入 ● 非常に柔軟 ○ やろうと思えば Ruby のコアな部分さえ変更可能 https://www.ruby-lang.org/ja/about/

Slide 55

Slide 55 text

クックパッドにおける Ruby ● レシピサービスやcookpad mart など全社的に利用 ○ マイクロサービス化で様々な言語が適材適所で利用さ れているが、ユーザー向けサービスだと Ruby が多い ● 2名のフルタイム Ruby コミッターが在籍

Slide 56

Slide 56 text

ライブラリ ● gem と呼ばれる ○ gem install xxx でインストールできる ● bundler というツールで依存関係を管理 ○ Gemfile に利用する gem を記載 ○ bundle install で依存関係を解決してインストール ○ Gemfile.lock で利用しているバージョンを固定 ● bundle exec xxx で bundler で管理している gem を利用し て、コマンドを実行できる

Slide 57

Slide 57 text

Rails (Ruby on Rails)

Slide 58

Slide 58 text

Rails の特徴 ● Ruby 製の Web アプリケーションフレームワーク ● Rails Way という Rails のおすすめ開発方法を提供 ○ Rails というレールに乗れば、生産性が向上する ○ レールから外れると、大変なことが多い ● Rails の規約 ○ 繰り返しを避けよ(Don't Repeat Yourself: DRY) ○ 設定より規約が優先(Convention Over Configuration) ● MVC パターン https://guides.rubyonrails.org/getting_started.html

Slide 59

Slide 59 text

● ソフトウェアを処理 (M)、表示 (V)、入力伝達 (C) の3つに責 務を分割するパターン ● Model ○ データと手続き(ビジネスロジック)を表現する要素 ● View ○ モデルのデータを利用して、ユーザーに向けて描画する(Webの場 合は HTML を生成する) ● Controller ○ リクエスト(入力)を受けて、モデルやビューを呼び出す MVC パターン

Slide 60

Slide 60 text

Rails の処理の流れ クライアント
 Controller View DB Model Router 1. クライアントがリクエストする 2. URI に基づいて Router がどの Controller を呼び出すかを判断する 3. Controller がリクエストされた内容に基づいて、 Model や View を呼び出す a. Model は紐づく DB からデータを取得したり、データの処理を行う b. View は与えられた Model を利用して、クライアントに表示する内容を組み立 てる 4. Controller が View が組み立てた結果をクライアントに返す

Slide 61

Slide 61 text

● ハンズオン ○ rails ○ graphql-ruby ● 実際に使ってみて理解を深めましょう! ○ Rails や GraphQL の概観の理解が重要です ■ なんのためにどこにコードを書くのか ■ それぞれがどういう役割なのか ○ 文法など細かいことは本質じゃないので気にしすぎなくて大丈夫です 講義パートここまで

Slide 62

Slide 62 text

参考リンク ● BFF ○ https://samnewman.io/patterns/architectural/bff/ ○ https://www.thoughtworks.com/insights/blog/bff-soundcloud ○ https://docs.microsoft.com/ja-jp/dotnet/architecture/microservices/architect-micro service-container-applications/direct-client-to-microservice-communication-versus-t he-api-gateway-pattern ● GraphQL ○ https://graphql.org/learn/ ○ https://book.productionreadygraphql.com/ ○ https://www.apollographql.com/docs/

Slide 63

Slide 63 text

おわり