$30 off During Our Annual Pro Sale. View Details »

GO TechTalk #22 Reactで描くタクシーアプリ『GO』の世界

GO Inc. dev
September 12, 2023

GO TechTalk #22 Reactで描くタクシーアプリ『GO』の世界

■ 内容
・​​Reactで地図上にタクシーをゴリゴリ描画する方法(大橋)p.4 ~
・最近の推しフロントエンド構成(鈴木)p.46 ~

■ YouTube
https://www.youtube.com/watch?v=kG81x8E-LM8&t=180s

■ connpass
https://jtx.connpass.com/event/293119/

GO Inc. dev

September 12, 2023
Tweet

More Decks by GO Inc. dev

Other Decks in Programming

Transcript

  1. View Slide

  2. © GO Inc. 2
    GO株式会社について
    CO2削減・タクシーEV化


    View Slide

  3. © GO Inc.
    タイムテーブル
    3
    19:00-19:05 オープニング
    19:05-19:35 Reactで地図上にタクシーをゴリゴリ描画する方法(大橋)
    最近のフロントエンド構成(鈴木)
    19:35-19:40 クロージング
    19:40 終了

    View Slide

  4. Reactで地図上にタクシーを
    ゴリゴリ描画する方法
    GO株式会社 大橋 平和(@lighttiger2505)

    View Slide

  5. © GO Inc. 5
    自己紹介
    大橋平和(@lighttiger2505)
    ▪ GO株式会社

    バックオフィス基盤3グループ(タクシー会
    社様の管理画面)
    ▪ グループマネージャー
    ▪ サーバーサイドエンジニア

    好きな言語: Golang

    好きなエディタ: Vim(Neovim)
    ▪ 最近、生の歓びを感じること

    ARMORED CORE VI FIRES OF RUBICONで対
    戦用の機体をアセンブルすること

    View Slide

  6. © GO Inc. 6
    目次
    1.タクシーアプリ『GO』の管理画面と地図描画
    2. Reactで地図描画するときの技術選定
    3. 地図に大量のマーカーを描画するためのTIPS

    View Slide

  7. © GO Inc.
    話さないこと
    技術的な深掘りを優先するため、以下の話は割愛しますが、
    実際の利用時には、各自確認をお願いします。
    ▪ 地図のライセンスおよび料金
    ▪ 使用するライブラリのライセンス
    7

    View Slide

  8. © GO Inc.
    1. タクシーアプリ『GO』の
    管理画面と地図描画
    8

    View Slide

  9. © GO Inc. 9
    タクシーアプリ『GO』の管理画面
    タクシーアプリ『GO』にて配車される車両や、
    タクシー運転手様の情報を登録するためのマスター管理

    View Slide

  10. © GO Inc. 10
    タクシーアプリ『GO』の管理画面
    タクシーアプリ『GO』から、
    タクシー運転手様が受けた配車の履歴

    View Slide

  11. © GO Inc. 11
    今回の主題「リアルタイム運行管理」
    タクシー車両の位置情報およびステータス(いまお客様を乗せ
    ているかどうかなど)をリアルタイプにマップ表示

    View Slide

  12. © GO Inc.
    リアルタイム運行管理の要件
    ▪ 大きなタクシー会社様が快適に使える

    タクシー車両3~4000程度の描画が高速にできる
    ▪ マップ上に操作可能なピンなどを配置したい

    地点登録をしてそこにジャンプをするなどの便利機能がある
    ▪ 地図検索や住所検索などをしたい

    駅や建物などを検索してジャンプしたりなどする
    12

    View Slide

  13. © GO Inc.
    2. Reactで地図描画するときの
    技術選定
    13

    View Slide

  14. © GO Inc. 14
    Reactで地図描画するときの技術選定の要素
    1. ベースマップ(タイルレイヤー)
    a.
    地図の画像の提供元。Google MapsやMapboxなど
    2. マップライブラリ
    a.
    地図の描画を制御し、ベースマップの上にビジュアライズ要素を
    追加するためのライブラリ。Leafletやdeck.glなど
    3. Reactラッパー
    a.
    マップライブラリをReactのコンポーネントとして扱うためのラ
    イブラリ。react-leafletやreact-map-glなど

    View Slide

  15. © GO Inc. 15
    要素は階層構造になっている
    React
    Reactラッパー
    マップライブラリ
    ベースマップ

    View Slide

  16. © GO Inc. 16
    ベースマップ
    A. Google Maps
    a.
    言わずと知れたGoogle社の提供する地図
    B. Mapbox
    a.
    Mapbox社の提供する開発者向けのカスタマイズ可能な地図
    C. OpenStreetMap
    a.
    コミュニティベースでメンテナンスされるオープンライセンスの
    地図
    D. ArcGIS
    a.
    地理情報システム開発では世界有数の技術力を持つESIR社の提供
    する地図

    View Slide

  17. © GO Inc. 17
    ベースマップのイメージ
    Google Maps Mapbox OpenStreetMap

    View Slide

  18. © GO Inc. 18
    マップライブラリ
    A. Leaflet
    a.
    昔からあるシンプルなライブラリ。コミュニティにてメンテ
    B. Maps JavaScript API
    a.
    Google公式提供のライブラリ。GitHubにリポジトリはないが
    GoogleMapの直接利用時には意識的に読み込み
    C. Mapbox GL JS
    a.
    Mapbox公式提供のライブラリ、WebGLベースで描画
    D. deck.gl
    a.
    大規模データセット用に開発されたWebGLベースのライブラ
    リ。Uberが運営のvisglというオープンソースコミュニティが開

    View Slide

  19. © GO Inc. 19
    マップライブラリを選ぶときの注意点(1)
    マップライブラリ 利用可能なベースマップ
    LeafLet, deck.gl Google Maps
    Mapbox
    OpenStreetMap
    ArcGIS
    Maps JavaScript API Google Maps
    Mapbox GL JS Mapbox
    OpenStreetMap
    ArcGIS
    マップライブラリごとに選択可能なベースマップがある

    View Slide

  20. © GO Inc. 20
    マップライブラリを選ぶときの注意点(2)
    描画の方式によって描画速度がかなり違う
    ▪ マップライブラリがWebGLの描画に対応しているかは要
    チェック

    Mapbox GL JSとdeck.glはWebGL描画を明記
    ▪ このあと、更に詳しく話します

    View Slide

  21. © GO Inc. 21
    Reactラッパー
    マップライブラリ Reactラッパー
    LeafLet PaulLeCam/react-leaflet
    Maps JavaScript API googlemaps/react-wrapper
    JustFly1984/react-google-maps-api
    Mapbox GL JS visgl/react-map-gl
    alex3165/react-mapbox-gl
    deck.gl 公式にReactフレンドリーを謳おり、マップライブラリ
    にReactラッパーが同梱

    View Slide

  22. © GO Inc. 22
    Reactラッパーを選ぶときの注意点
    ▪ Reactラッパーを最初に選ぶとベースマップの選択が不可

    「Reactラッパーを選ぶ」=「マップライブラリを選ぶ」なの
    で、その時点で選択可能なベースマップが確定

    「React 地図」でGoogle検索すると、Reactラッパーを導入しよ
    う。から始まる記事があるので注意
    ▪ 個人運営か企業運営かは確認

    deck.glやreact-map-glはvisglというコミュニティによってメン

    ▪ 企業運営ならば良いというわけではない
    ▪ TypeScriptサポートがあるか確認

    View Slide

  23. © GO Inc. 23
    極論するとReactラッパーはなくてもよいが
    ▪ Reactラッパーを使わず直接マップライブラリを使う手も
    ある

    Mapbox GL JSは公式サイトでReactから直接利用するチュート
    リアルを公開
    ▪ ReactアプリでMapbox GL JSを使う
    ▪ 直接利用しても、結局自前でReactコンポーネント化する
    ことになる。メンテナンスされているReactラッパーがあ
    場合、利用するほうが無難

    View Slide

  24. © GO Inc. 24
    「GO管理画面」の技術選定は?
    種類 選択 採用理由
    ベースレイヤー Mapbox Mapbox GL JSにした結果、Mapboxほぼ一択。会社全
    体だとGoogle Mapsも使っているので、Mapbox GL
    JS採用しなければ選ぶのは可能だった。
    マップライブラリ Mapbox GL JS Leafletと比較してWebGLによる描画速度が大きな要
    因。当時deck.glを知らないため比較検討していない。
    今なら有力な選択肢。
    Reactラッパー visgl/react-map-gl サポートにMapbox公式がクレジットされている
    (visglにはMapboxも参画している)かつ使いやすい
    ため、現状MapboxのReactラッパーならばかなり有力
    な選択肢。

    View Slide

  25. © GO Inc.
    3. 大量のマーカーを
    描画するためのTIPS
    25

    View Slide

  26. © GO Inc. 26
    描画を軽くするためのポイント
    1. 描画の方式を高速なものにする
    1.1.
    DOM操作を伴わない描画をする
    1.2.
    WebGLを用いた高速な描画をする
    2. 描画の回数を減らす
    1.描画の方式を高速なものにする 2.描画の回数を減らす
    時間軸

    View Slide

  27. © GO Inc.
    話さないこと
    Reactのメモ化については一般的な話なので割愛
    27

    View Slide

  28. © GO Inc.
    1.1. DOM操作を伴わない描画をする
    28

    View Slide

  29. © GO Inc. 29
    マーカーとレイヤー(概要)
    ▪ マップライブラリにはマップ上にピンを置く機能がある
    ▪ すべてではないが、多くのマップライブラリにはピンの
    置き方には種類があり、以下の2種類が存在する

    マーカー
    ▪ HTML要素としてブラウザで描画(DOMの要素追加)

    レイヤー
    ▪ マップの中で描画(DOM変更なし)

    View Slide

  30. © GO Inc. 30
    マーカーとレイヤー(図示)
    マーカーはアイコン一つずつを描画し、レイヤーは全アイコ
    ンを含めた一枚の絵を地図上に描画する
    マーカー
    マーカー
    マーカー
    マーカー
    マーカー レイヤー

    View Slide

  31. © GO Inc. 31
    マーカーとレイヤー(メリット・デメリット)
    種別 マーカー レイヤー
    メリット ● 実装が簡単
    ○ クリックイベントの追加、
    ポップアップの追加などが
    容易
    ● HTMLなので見た目のカスタマイ
    ズをCSSでできる
    ● 大量のデータの高速描画が可能
    デメリット ● 大量に配置するとパフォーマンス
    が悪化する
    ● 実装が難しい
    ○ 座標情報をGeoJSON形式に変換
    するなど手間がかかる
    ○ 画像を描画するならマップ側にロー
    ドが必要
    ○ クリックイベント追加などマップに独
    自の方法で追加が必要

    View Slide

  32. © GO Inc.
    1.2. WebGLを用いた高速な描画をする
    32

    View Slide

  33. © GO Inc. 33
    「GO管理画面」のライブラリ選択は以前はこうだった
    種類 選択 採用理由
    ベースレイヤー Mapbox 適当
    マップライブラリ Leaflet 適当
    Reactラッパー PaulLeCam/react-leaflet 適当

    View Slide

  34. © GO Inc. 34
    マーカーを大量配置したら遅くなったので調査
    「leaflet too many marker」のGoggle検索結果を3日眺めた
    結果、マーカー描画の速度改善の解決策を見つけた
    1. DOM要素の変更があるマーカーではなくレイヤー
    (Vector Layers)に切り替える
    a.
    これで解消しなかった理由は次スライド
    2. クラスター表示にする
    a.
    一応これも導入している
    3. 高速な描画を行うための外部プラグインを導入し、プラ
    グインの提供するレイヤー上で描画
    a.
    個人が提供するプラグインに依存するのは抵抗があった

    View Slide

  35. © GO Inc. 35
    クラスター表示の例

    View Slide

  36. © GO Inc. 36
    レイヤー描画にすれば、どのマップライブラリも早いのか
    ▪ Leafletのパフォーマンス問題の調査をするなかで一つの
    記事と出会う

    Leaflet versus Mapbox GL performance
    ▪ Mapbox GL JSとLeafletの同一条件のパフォーマンステスト記事
    ● 唆るぜこれは

    View Slide

  37. © GO Inc. 37
    『Leaflet versus Mapbox GL performance』要約
    ▪ 地図上に大量のドットをアニメーションさせるサンプル
    プログラムを2018年の15インチMacBook Proで実行して
    検証

    LeafLetで300個のドットを動かしたらFPSは30まで落ち、700
    個のドットを動かしたらFPSは1桁台になった
    ▪ Leafletには高速描画オプションがあるが、ONにしても1000個の
    ドットでFPSは1桁台になった

    Mapbox GL JSで2000個のドットを動かしたがFPSは安定して60
    を維持していた

    View Slide

  38. © GO Inc.
    2. 描画の回数を減らす
    38

    View Slide

  39. © GO Inc. 39
    車両を表示するためのタクシー位置情報の中身
    state
    [
    {
    "driver_app_kit_id": 1000536,
    "office_id": 1000673,
    "latitude": 33.627787102874215,
    "longitude": 130.41376251671505,
    "azimuth": 21.879079818725586,
    "timestamp": 1693517317,
    "datetime": "2023-08-31T21:28:37.741Z",
    "meter_status": "unladen",
    "active_status": "normal",
    "business_status": "no_signal",
    "speed": 0.5939096331596374
    }
    ...
    ]

    View Slide

  40. © GO Inc. 40
    タクシー位置情報の更新で再描画される対象
    タクシー車両の現在地を
    表示しているマップ
    現在マップに
    表示されている車両の一覧
    選択車両の詳細
    state
    タクシー車両の現在地を
    表示しているマップ
    タクシー車両の現在地を
    表示しているマップ
    タクシー車両の現在地を
    表示しているマップ
    タクシーの位置情報が更新
    されると、同時に3つの
    ビューの再描画が走る

    View Slide

  41. © GO Inc. 41
    何の対策もしない状態の描画回数
    タクシー
    車両
    タクシー
    車両
    タクシー
    車両
    「GO管理画面」
    フロントエンド
    1秒間に数回の再描画
    数秒に1度、位置情報を送信
    全体で25000RPS
    上位30社14000RPS
    位置情報収
    集サーバー
    state
    数秒に1度、位置情報を送信
    全体で25000RPS
    上位30社14000RPS
    数秒に1度、位置情報を送信
    全体で25000RPS
    上位30社14000RPS
    フロントエンドとWebSocketで接
    続し、位置情報を送信し続ける

    View Slide

  42. © GO Inc. 42
    対策をした場合の描画回数
    動態収集
    サーバー
    Map state
    1
    2
    3
    受け取った動態をID
    別に格納し、常に最
    新の動態だけを持つ
    Mapを作る
    再描画が負荷になら
    ない程度のインター
    バルを設けて、定期
    的に配列に変換
    配列をstateとして、
    更新すると再描画が走る

    View Slide

  43. © GO Inc.
    まとめ
    43

    View Slide

  44. © GO Inc. 44
    まとめ(2. Reactで地図描画するときの技術選定)
    ▪ Reactで地図描画をするなら技術選定に注意

    最初にReactラッパーを選択すると、ベースマップを変更できな

    ▪ 「Reactラッパーの選択」=「ベースマップの選択」
    ▪ マップライブラリによってベースマップの選択肢が限られる

    マップライブラリによって高速な描画方式をサポートしていない
    ことがあるので注意

    View Slide

  45. © GO Inc. 45
    まとめ(3. 地図に大量のマーカーを描画するためのTIPS)
    ▪ 地図上にアイコンを大量表示するなら描画方式に気をつ
    ける

    各種イベントが容易に追加でき、見た目もいじりやすいマーカー
    か、高速描画できるが実装が難しいレイヤーかを考える

    ライブラリ次第では描画方式が古く、大量のアイコン表示がそも
    そも無理なものもある。大量のアイコン描画が必要になるかはよ
    く考える
    ▪ そもそも描画する回数を減らせば負荷は減る。バッファ
    リングして減らせるなら減らそう

    View Slide

  46. 最近のフロントエンド構成
    Fumita Suzuki
    46

    View Slide

  47. © GO Inc. 47
    自己紹介
    プロフィール写真
    正方形にトリミングした写
    真を「図形に合わせてトリ
    ミング」で円形にすると真
    円になる
    GO株式会社
    エンジニア / Suzuki Fumita
    略歴 最初に入った受託系企業で官公庁のR&D案件を何回かやったのち、ス
    タートアップ業界に。2021年6月にGOに入社。現在はタクシー事業者向け
    の管理画面開発に注力。1児の父。趣味は船釣り。
    @maikii_chan

    View Slide

  48. © GO Inc.
    今日話すこと
    1. 「GO管理画面」とは?
    2. 使用技術
    3. やってよかったこと
    4. 後悔していること
    48

    View Slide

  49. © GO Inc.
    「GO管理画面」とは?
    タクシーアプリ『GO』において、タクシー会社の事務所などで使われる
    管理画面。タクシーの現在地や配車の履歴、お金まわりの情報が確認で
    きる。約2年くらい前から開発している。
    フロントエンドはReact(+TypeScript)。
    バックエンドはGo言語。
    社内には他にも沢山の「管理画面」がある。
    49

    View Slide

  50. © GO Inc.
    使用技術ーライブラリ
    50
    React v17
    Reactイベントの登壇資料なので当たり前か。バージョン18に上げたいけど
    腰が重くてできてない。
    React Router v5
    定番のやつ。v6にしたい。

    View Slide

  51. © GO Inc.
    使用技術ービルドツールなど
    51
    Vite
    create-react-appからviteに移行した。環境変数の書き方が変わるくらいし
    かハマりポイントはなかった気がする。create-react-appと比べたら爆速
    でいい感じ。
    Storybook
    開発初期に導入してhygenでテンプレートを生成するように整えたが、布教
    が足りずあまり活用できていない。

    View Slide

  52. © GO Inc.
    使用技術ーUI系ライブラリ
    52
    MUI(material-ui) v5
    言わずと知れた大御所ライブラリ。デカい上に複雑なライブラリだが、管理
    画面に必要なコンポーネントはほぼ全部揃っている。開発もそこそこ活発。
    TypeScriptもサポートしている(当たり前か)。
    Emotion
    CSSinJS系のライブラリ。MUIは内部で使うスタイリングソリューションを
    選択することができ、GO管理画面ではEmotionを使っている。
    react-hook-form + yup
    フォームは全部react-hook-formとyupで書いてある。yup.InferTypeで
    schemaから型を作っている。

    View Slide

  53. © GO Inc.
    使用技術ーテストツール
    53
    Vitest
    Jestと互換性のあるユニットテストツール。単純に速いJestというだけでは
    なく、Rust-likeなIn-source testingができたりする。
    Cypress
    有名なE2Eテストツール。多機能で便利。CI側で落ちたりしてるとデバッグ
    がめんどくさい。今だったらPlaywrightも良さそう(並列テストがやりやす
    いらしい)。

    View Slide

  54. © GO Inc.
    後悔していること
    プロダクト開始直後にStoryBookを導入したこと
    メンテナンスがつらい。ライブラリの依存関係が多く、Chromaticと合
    わさって巨大ななにかができてきてる。ただのコンポーネント集が欲し
    いだけならreact-cosmosとかでも良さそう。
    https://reactcosmos.org/
    パフォーマンスを測定する仕組みを作ってない
    ある日Lighthouseのスコアを見たらパフォーマンスのスコアが67点だっ
    た。90点以上はキープしてたい。
    54

    View Slide

  55. © GO Inc.
    やってよかったこと
    Atomic Designをやめた
    そもそもMUIを使っているので過剰な設計な気がしてきた。今は
    /components配下にほぼフラットに配置している。
    webpackからviteにした
    ビルドやHMR速い。ビルド時間が約1/3になった。内部でやっているこ
    とは複雑そうだけど導入は簡単。
    55

    View Slide

  56. © GO Inc.
    おしまい!
    気になることがあればなんでも質問してください!
    56

    View Slide

  57. © GO Inc. 57
    技術全般 X(Twitter)
    @goinc_techtalk
    AI関連 X(Twitter)
    @goinc_ai_tech
    Thank You!
    We Are Hiring!

    View Slide

  58. © GO Inc.
    文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください

    View Slide