Slide 1

Slide 1 text

少人数でサービスをすばやく 開発するためのRails活用事例 @Rails Developers Meetup 2019 pixiv Inc. Yusuke Otawa @tawachan39 2019.3.22

Slide 2

Slide 2 text

自己紹介 ● 大多和祐介(tawachan / @tawachan39) ● ピクシブ株式会社(福岡オフィス) ● 東京出身だけれど転職を機に福岡へ Iターン ○ 福岡Iターンとか興味ある人はお声がけ頂けると嬉し い! 2 tawachan

Slide 3

Slide 3 text

● 少人数でフットワーク軽くサービスを開発する方法としての事例 ● 弊社のサービス(pixiv chatstory)PJにおける知見がベース ● 新しくサービスを始めるときのアーキテクチャ ○ スピードを上げつつある程度コードの質が担保される開発 ○ チームの構成とかではなくあくまでエンジニアリングの部分 ○ サービス的な質はまた別の話...。 ● サーバーサイド(Ruby on Rails)の話が中心 今回話すこと 3

Slide 4

Slide 4 text

のアーキテクチャ 4 API Server Web/PWA iOS CDN

Slide 5

Slide 5 text

新規サービス開発において だいたいエンジニアが考える(た)こと ● この処理なんか動いてない、どうにかしなきゃ ... ● 仕様が変わるときにエンジニア間で共通認識を持つのが大変 ... ● アクセスが集中してレスポンスが遅くなっている ... ● 捌ききれなくなって500返してる... 5

Slide 6

Slide 6 text

なんかつらい 6

Slide 7

Slide 7 text

● ユーザーやUXのこと ● 様々なデータの取得 ● 取得したデータの解析 ● サービスの改善や目指すべき状態 新規サービス開発において エンジニアが考えたいこと 7

Slide 8

Slide 8 text

どうにかしたい 8

Slide 9

Slide 9 text

どうにかしてみた! 9

Slide 10

Slide 10 text

目次 10 1. Railsアプリケーションの位置付け 2. 実行環境 3. 開発の工夫

Slide 11

Slide 11 text

Railsは APIサーバーに使用 11

Slide 12

Slide 12 text

クライアントは多種多様 ● ウェブ ○ 普通のウェブ ○ PWA ● スマホアプリ ○ ネイティブ ○ クロスプラットフォーム ● スマートスピーカー ● その他 ○ Slack ○ LINE… etc 12

Slide 13

Slide 13 text

● アプリを作っていたけれど、やっぱりウェブのほうがいいかも ... ● クロスプラットフォームでのアプリは辛いからネイティブで書き換える ... ● ウェブだけでなくアプリも必要になった ... サーバーサイドよりもクライアントサイドのほうがライフサイクルが速くなっている → クライアントサイドの変更にサーバーサイドが引きづられるのはよくない クライアントは書き換えるかも 13

Slide 14

Slide 14 text

● クライアントによって返すものが異なるのはそもそもどうなのか ○ ウェブだったらHTML ○ でも非同期でのリクエストだったら JSON ○ アプリなら常にJSON ● クライアントが増えてパターンが増えてくると見通し悪い ○ DRYにしづらくなる ● → バックエンドはデータの登録、管理、取得が責務 バックエンドはデータが責務 14

Slide 15

Slide 15 text

● メリット ○ ウェブ用とアプリ用の2種類のエンドポイントを用意する必要がなくなる ■ →共通化できる ○ その他のクライアントにも対応しやすい ● デメリット ○ セッション管理や認証周りがちょっと手間になる ○ フロントの分リポジトリや用意する環境が増える RailsはAPIサーバーに使用 15

Slide 16

Slide 16 text

APIサーバーなら 別の言語でもよい...? 16

Slide 17

Slide 17 text

結局Railsが最強でした 17

Slide 18

Slide 18 text

なぜRailsなのか 18

Slide 19

Slide 19 text

● Migrationも含めてModel層はよしなに力が群を抜いて強い ○ 他の言語に代案がない... ○ Go言語のBeegoは良さそうだったけれど... ● RDBを使うならRailsを使いたい Active Recordがどうしても一番便利 19

Slide 20

Slide 20 text

● 開発できる人が多い ○ 社内でもキャッチアップしている人が多い ○ 社内で情報共有もできる ● エコシステムや知見が揃っている ○ ググればすぐわかる、妙に詰まることがない ○ 社内でも知見を得られる 開発スピードが出る 20

Slide 21

Slide 21 text

サーバーのデプロイ場所 21

Slide 22

Slide 22 text

● Herokuなら状況に合わせて融通がきく ○ Dyno増やす/強くできる ○ すぐにスケールできる ○ プランによってはオートスケーリングもできる ○ DBもアドオンなのでGUIでポチるだけで建てられる ● PaaS最高!!! Herokuに全部おまかせ 22

Slide 23

Slide 23 text

● Herokuでそれなりに環境を揃えても1ヶ月あたり数百ドル ● エンジニアに換算したら数人日 ○ 自前でやるならたった数人日で完結しないとペイしない ○ そもそも人手があるわけでもない ● 積極的にHerokuに任せていけば、人手も残るしコストも下がる!! エンジニアが一番高い 23

Slide 24

Slide 24 text

でもレスポンスが遅い... 24 ● US/EUリージョンのみ ○ 物理的な距離で単純にレスポンスが遅い ○ (エンタープライズ版で東京リージョンが出てはいる) ● レスポンスの速さはユーザー体験に直接影響する ● でもHerokuの便利さは捨てたくない...

Slide 25

Slide 25 text

CDNで解決! 25

Slide 26

Slide 26 text

● APIサーバーが返すJSONをCDNでキャッシュ ○ AWSのCloudFrontを使用 ● 東京リージョンのCDNで処理できるものはかなり速い 東京でキャッシュすれば実質東京 26

Slide 27

Slide 27 text

でもキャッシュ事故は怖い... 27

Slide 28

Slide 28 text

CDNでのキャッシュ前提のAPI設計 ● 誰でも見れる public なエンドポイント ○ どのユーザーがAPI を叩いても値は同じ ○ 処理内で current_user を使わない ● 認証状態によってユーザー固有の情報を返すエンドポイント ○ API を叩くユーザーによって値が変わる ○ 処理内で current_user を使う 28

Slide 29

Slide 29 text

# examples_controller.rb before_action :require_api_key, only: [:create, :destroy, :update] before_action :optional_api_key, only: [:index, :show] before_action :cdn_cache_long, only: [:index, :show] def index @examples = Example.all end … def create @examples = current_user.examples.create!(example_params) end … キャッシュの機構の例 29

Slide 30

Slide 30 text

キャッシュの機構の例 # application_controller.rb def require_api_key raise StandardError, 'require_api_key not allowed after cdn_cache called' if @cdn_cache_called @require_api_key_called = true @current_user = User.find_by(api_key: api_key) unless api_key.blank? render json: { error: 'Api-Keyが有効ではありません ' }, status: :unauthorized unless @current_user end def cdn_cache(s_maxage) raise StandardError, 'cache not allowed' if @require_api_key_called @cdn_cache_called = true expires_in(0, 's-maxage': s_maxage, public: true, must_revalidate: true) end def current_user raise StandardError, 'current_user not allowed' unless @require_api_key_called @current_user end 30

Slide 31

Slide 31 text

ヒューマンエラーは どうしても起こる (”気をつける”だけでは解決しない) 31

Slide 32

Slide 32 text

仕組みで 解決していくことが 重要 32

Slide 33

Slide 33 text

手軽に速くデータを返せる APIサーバーになりました 33

Slide 34

Slide 34 text

でも、フロントからは まだ使いづらい 34

Slide 35

Slide 35 text

API のドキュメント 見るの面倒ですよね 35

Slide 36

Slide 36 text

データの管理が責務なら スマートに受け渡しまでしたい 36

Slide 37

Slide 37 text

Swaggerを導入 37

Slide 38

Slide 38 text

● API開発を補助してくれるオープンソースのツール群 ● OpenAPI形式 ● 様々なツールがある ○ Swagger UI ○ Swagger Codegen ○ Swagger Editor Swaggerとは 38

Slide 39

Slide 39 text

swagger_path '/api/stories/{url_hash}' do operation :get do key :summary, 'url_hashを指定してストーリーを取得 ' parameter do key :name, :url_hash key :in, :path key :description, 'storyのurl_hash' key :required, true key :type, :string end response 200 do key :description, 'ok' schema do key :'$ref', :StoryResponse end end end swagger-blocksでRubyで記述 39

Slide 40

Slide 40 text

ブラウザで一覧が見れる (Swagger UI) 40

Slide 41

Slide 41 text

● 誰でも見れるAPIドキュメントになる ● コードベースでドキュメントが管理できる ○ ExcelとかSpreadsheetで書く必要なし ● 実際にAPIも叩ける Swagger UIのいいところ 41

Slide 42

Slide 42 text

● クライアントが使うコードが生成できる ○ 型情報 ○ SDK(リクエストを飛ばす部分) ● メジャーな言語には対応 ○ Swift ○ Kotlin ○ Java ○ TypeScript(Fetch, Angular… etc) ○ … and more 42 Swagger Codegenでコード生成

Slide 43

Slide 43 text

● 型情報とリクエストを生成できる ● 目測で型合わせをする必要がなくなる!!!! ● サーバー・クライアントで齟齬が生まれてこない ○ インターフェースの不一致によるバグはここで完全に塞ぐ ○ 変更もすぐに自動生成して反映できる ● 各クライアント固有の処理の実装に多くの関心が払える 43 Swaggerのいいところ

Slide 44

Slide 44 text

● swagger-blocksでドキュメントを書いていくのが手間 ● この手間を払ってもお釣りがくるありがたさ(チームメンバーの声) Swaggerの大変なところ 44

Slide 45

Slide 45 text

手軽に速くデータを返せて クライアント開発者にも優しい APIサーバーになりました 45

Slide 46

Slide 46 text

少人数でフットワーク軽く サービスを開発する方法としての事例 46

Slide 47

Slide 47 text

少人数でもスピードを上げつつある程度のコードの質を担保したい 1. RailsをAPIサーバーに使う 2. インフラはHerokuにお任せ 3. CDNでレスポンスも爆速に 4. Swaggerでクライアント開発者にも優しく 今回のおさらい 47

Slide 48

Slide 48 text

本質的なことに集中して ユーザーに価値を届けていきましょう 48

Slide 49

Slide 49 text

49 ● pixiv chatstoryのiOSアプリをReact Native(Expo)でリニューアルしました! ○ https://inside.pixiv.blog/tawachan/6254 ● pixiv chatstory の PWA としての取り組み ○ https://speakerdeck.com/ikasoumen/pixiv-chatstory-false-pwa-tositefalseq u-rizu-mi 【参考】フロント周りの話ができなかったので 関連記事をよろしければ