■ 内容 ・Reactで地図上にタクシーをゴリゴリ描画する方法(大橋)p.4 ~ ・最近の推しフロントエンド構成(鈴木)p.46 ~
■ YouTube https://www.youtube.com/watch?v=kG81x8E-LM8&t=180s
■ connpass https://jtx.connpass.com/event/293119/
View Slide
© GO Inc. 2GO株式会社についてCO2削減・タクシーEV化
© GO Inc.タイムテーブル319:00-19:05 オープニング19:05-19:35 Reactで地図上にタクシーをゴリゴリ描画する方法(大橋)最近のフロントエンド構成(鈴木)19:35-19:40 クロージング19:40 終了
Reactで地図上にタクシーをゴリゴリ描画する方法GO株式会社 大橋 平和(@lighttiger2505)
© GO Inc. 5自己紹介大橋平和(@lighttiger2505)▪ GO株式会社▪バックオフィス基盤3グループ(タクシー会社様の管理画面)▪ グループマネージャー▪ サーバーサイドエンジニア▪好きな言語: Golang▪好きなエディタ: Vim(Neovim)▪ 最近、生の歓びを感じること▪ARMORED CORE VI FIRES OF RUBICONで対戦用の機体をアセンブルすること
© GO Inc. 6目次1.タクシーアプリ『GO』の管理画面と地図描画2. Reactで地図描画するときの技術選定3. 地図に大量のマーカーを描画するためのTIPS
© GO Inc.話さないこと技術的な深掘りを優先するため、以下の話は割愛しますが、実際の利用時には、各自確認をお願いします。▪ 地図のライセンスおよび料金▪ 使用するライブラリのライセンス7
© GO Inc.1. タクシーアプリ『GO』の管理画面と地図描画8
© GO Inc. 9タクシーアプリ『GO』の管理画面タクシーアプリ『GO』にて配車される車両や、タクシー運転手様の情報を登録するためのマスター管理
© GO Inc. 10タクシーアプリ『GO』の管理画面タクシーアプリ『GO』から、タクシー運転手様が受けた配車の履歴
© GO Inc. 11今回の主題「リアルタイム運行管理」タクシー車両の位置情報およびステータス(いまお客様を乗せているかどうかなど)をリアルタイプにマップ表示
© GO Inc.リアルタイム運行管理の要件▪ 大きなタクシー会社様が快適に使える▪タクシー車両3~4000程度の描画が高速にできる▪ マップ上に操作可能なピンなどを配置したい▪地点登録をしてそこにジャンプをするなどの便利機能がある▪ 地図検索や住所検索などをしたい▪駅や建物などを検索してジャンプしたりなどする12
© GO Inc.2. Reactで地図描画するときの技術選定13
© GO Inc. 14Reactで地図描画するときの技術選定の要素1. ベースマップ(タイルレイヤー)a.地図の画像の提供元。Google MapsやMapboxなど2. マップライブラリa.地図の描画を制御し、ベースマップの上にビジュアライズ要素を追加するためのライブラリ。Leafletやdeck.glなど3. Reactラッパーa.マップライブラリをReactのコンポーネントとして扱うためのライブラリ。react-leafletやreact-map-glなど
© GO Inc. 15要素は階層構造になっているReactReactラッパーマップライブラリベースマップ
© GO Inc. 16ベースマップA. Google Mapsa.言わずと知れたGoogle社の提供する地図B. Mapboxa.Mapbox社の提供する開発者向けのカスタマイズ可能な地図C. OpenStreetMapa.コミュニティベースでメンテナンスされるオープンライセンスの地図D. ArcGISa.地理情報システム開発では世界有数の技術力を持つESIR社の提供する地図
© GO Inc. 17ベースマップのイメージGoogle Maps Mapbox OpenStreetMap
© GO Inc. 18マップライブラリA. Leafleta.昔からあるシンプルなライブラリ。コミュニティにてメンテB. Maps JavaScript APIa.Google公式提供のライブラリ。GitHubにリポジトリはないがGoogleMapの直接利用時には意識的に読み込みC. Mapbox GL JSa.Mapbox公式提供のライブラリ、WebGLベースで描画D. deck.gla.大規模データセット用に開発されたWebGLベースのライブラリ。Uberが運営のvisglというオープンソースコミュニティが開発
© GO Inc. 19マップライブラリを選ぶときの注意点(1)マップライブラリ 利用可能なベースマップLeafLet, deck.gl Google MapsMapboxOpenStreetMapArcGISMaps JavaScript API Google MapsMapbox GL JS MapboxOpenStreetMapArcGISマップライブラリごとに選択可能なベースマップがある
© GO Inc. 20マップライブラリを選ぶときの注意点(2)描画の方式によって描画速度がかなり違う▪ マップライブラリがWebGLの描画に対応しているかは要チェック▪Mapbox GL JSとdeck.glはWebGL描画を明記▪ このあと、更に詳しく話します
© GO Inc. 21Reactラッパーマップライブラリ ReactラッパーLeafLet PaulLeCam/react-leafletMaps JavaScript API googlemaps/react-wrapperJustFly1984/react-google-maps-apiMapbox GL JS visgl/react-map-glalex3165/react-mapbox-gldeck.gl 公式にReactフレンドリーを謳おり、マップライブラリにReactラッパーが同梱
© GO Inc. 22Reactラッパーを選ぶときの注意点▪ Reactラッパーを最初に選ぶとベースマップの選択が不可▪「Reactラッパーを選ぶ」=「マップライブラリを選ぶ」なので、その時点で選択可能なベースマップが確定▪「React 地図」でGoogle検索すると、Reactラッパーを導入しよう。から始まる記事があるので注意▪ 個人運営か企業運営かは確認▪deck.glやreact-map-glはvisglというコミュニティによってメンテ▪ 企業運営ならば良いというわけではない▪ TypeScriptサポートがあるか確認
© GO Inc. 23極論するとReactラッパーはなくてもよいが▪ Reactラッパーを使わず直接マップライブラリを使う手もある▪Mapbox GL JSは公式サイトでReactから直接利用するチュートリアルを公開▪ ReactアプリでMapbox GL JSを使う▪ 直接利用しても、結局自前でReactコンポーネント化することになる。メンテナンスされているReactラッパーがあ場合、利用するほうが無難
© GO Inc. 24「GO管理画面」の技術選定は?種類 選択 採用理由ベースレイヤー Mapbox Mapbox GL JSにした結果、Mapboxほぼ一択。会社全体だとGoogle Mapsも使っているので、Mapbox GLJS採用しなければ選ぶのは可能だった。マップライブラリ Mapbox GL JS Leafletと比較してWebGLによる描画速度が大きな要因。当時deck.glを知らないため比較検討していない。今なら有力な選択肢。Reactラッパー visgl/react-map-gl サポートにMapbox公式がクレジットされている(visglにはMapboxも参画している)かつ使いやすいため、現状MapboxのReactラッパーならばかなり有力な選択肢。
© GO Inc.3. 大量のマーカーを描画するためのTIPS25
© GO Inc. 26描画を軽くするためのポイント1. 描画の方式を高速なものにする1.1.DOM操作を伴わない描画をする1.2.WebGLを用いた高速な描画をする2. 描画の回数を減らす1.描画の方式を高速なものにする 2.描画の回数を減らす時間軸
© GO Inc.話さないことReactのメモ化については一般的な話なので割愛27
© GO Inc.1.1. DOM操作を伴わない描画をする28
© GO Inc. 29マーカーとレイヤー(概要)▪ マップライブラリにはマップ上にピンを置く機能がある▪ すべてではないが、多くのマップライブラリにはピンの置き方には種類があり、以下の2種類が存在する▪マーカー▪ HTML要素としてブラウザで描画(DOMの要素追加)▪レイヤー▪ マップの中で描画(DOM変更なし)
© GO Inc. 30マーカーとレイヤー(図示)マーカーはアイコン一つずつを描画し、レイヤーは全アイコンを含めた一枚の絵を地図上に描画するマーカーマーカーマーカーマーカーマーカー レイヤー
© GO Inc. 31マーカーとレイヤー(メリット・デメリット)種別 マーカー レイヤーメリット ● 実装が簡単○ クリックイベントの追加、ポップアップの追加などが容易● HTMLなので見た目のカスタマイズをCSSでできる● 大量のデータの高速描画が可能デメリット ● 大量に配置するとパフォーマンスが悪化する● 実装が難しい○ 座標情報をGeoJSON形式に変換するなど手間がかかる○ 画像を描画するならマップ側にロードが必要○ クリックイベント追加などマップに独自の方法で追加が必要
© GO Inc.1.2. WebGLを用いた高速な描画をする32
© GO Inc. 33「GO管理画面」のライブラリ選択は以前はこうだった種類 選択 採用理由ベースレイヤー Mapbox 適当マップライブラリ Leaflet 適当Reactラッパー PaulLeCam/react-leaflet 適当
© GO Inc. 34マーカーを大量配置したら遅くなったので調査「leaflet too many marker」のGoggle検索結果を3日眺めた結果、マーカー描画の速度改善の解決策を見つけた1. DOM要素の変更があるマーカーではなくレイヤー(Vector Layers)に切り替えるa.これで解消しなかった理由は次スライド2. クラスター表示にするa.一応これも導入している3. 高速な描画を行うための外部プラグインを導入し、プラグインの提供するレイヤー上で描画a.個人が提供するプラグインに依存するのは抵抗があった
© GO Inc. 35クラスター表示の例
© GO Inc. 36レイヤー描画にすれば、どのマップライブラリも早いのか▪ Leafletのパフォーマンス問題の調査をするなかで一つの記事と出会う▪Leaflet versus Mapbox GL performance▪ Mapbox GL JSとLeafletの同一条件のパフォーマンステスト記事● 唆るぜこれは
© 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を維持していた
© GO Inc.2. 描画の回数を減らす38
© 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}...]
© GO Inc. 40タクシー位置情報の更新で再描画される対象タクシー車両の現在地を表示しているマップ現在マップに表示されている車両の一覧選択車両の詳細stateタクシー車両の現在地を表示しているマップタクシー車両の現在地を表示しているマップタクシー車両の現在地を表示しているマップタクシーの位置情報が更新されると、同時に3つのビューの再描画が走る
© GO Inc. 41何の対策もしない状態の描画回数タクシー車両タクシー車両タクシー車両「GO管理画面」フロントエンド1秒間に数回の再描画数秒に1度、位置情報を送信全体で25000RPS上位30社14000RPS位置情報収集サーバーstate数秒に1度、位置情報を送信全体で25000RPS上位30社14000RPS数秒に1度、位置情報を送信全体で25000RPS上位30社14000RPSフロントエンドとWebSocketで接続し、位置情報を送信し続ける
© GO Inc. 42対策をした場合の描画回数動態収集サーバーMap state123受け取った動態をID別に格納し、常に最新の動態だけを持つMapを作る再描画が負荷にならない程度のインターバルを設けて、定期的に配列に変換配列をstateとして、更新すると再描画が走る
© GO Inc.まとめ43
© GO Inc. 44まとめ(2. Reactで地図描画するときの技術選定)▪ Reactで地図描画をするなら技術選定に注意▪最初にReactラッパーを選択すると、ベースマップを変更できない▪ 「Reactラッパーの選択」=「ベースマップの選択」▪ マップライブラリによってベースマップの選択肢が限られる▪マップライブラリによって高速な描画方式をサポートしていないことがあるので注意
© GO Inc. 45まとめ(3. 地図に大量のマーカーを描画するためのTIPS)▪ 地図上にアイコンを大量表示するなら描画方式に気をつける▪各種イベントが容易に追加でき、見た目もいじりやすいマーカーか、高速描画できるが実装が難しいレイヤーかを考える▪ライブラリ次第では描画方式が古く、大量のアイコン表示がそもそも無理なものもある。大量のアイコン描画が必要になるかはよく考える▪ そもそも描画する回数を減らせば負荷は減る。バッファリングして減らせるなら減らそう
最近のフロントエンド構成Fumita Suzuki46
© GO Inc. 47自己紹介プロフィール写真正方形にトリミングした写真を「図形に合わせてトリミング」で円形にすると真円になるGO株式会社エンジニア / Suzuki Fumita略歴 最初に入った受託系企業で官公庁のR&D案件を何回かやったのち、スタートアップ業界に。2021年6月にGOに入社。現在はタクシー事業者向けの管理画面開発に注力。1児の父。趣味は船釣り。@maikii_chan
© GO Inc.今日話すこと1. 「GO管理画面」とは?2. 使用技術3. やってよかったこと4. 後悔していること48
© GO Inc.「GO管理画面」とは?タクシーアプリ『GO』において、タクシー会社の事務所などで使われる管理画面。タクシーの現在地や配車の履歴、お金まわりの情報が確認できる。約2年くらい前から開発している。フロントエンドはReact(+TypeScript)。バックエンドはGo言語。社内には他にも沢山の「管理画面」がある。49
© GO Inc.使用技術ーライブラリ50React v17Reactイベントの登壇資料なので当たり前か。バージョン18に上げたいけど腰が重くてできてない。React Router v5定番のやつ。v6にしたい。
© GO Inc.使用技術ービルドツールなど51Vitecreate-react-appからviteに移行した。環境変数の書き方が変わるくらいしかハマりポイントはなかった気がする。create-react-appと比べたら爆速でいい感じ。Storybook開発初期に導入してhygenでテンプレートを生成するように整えたが、布教が足りずあまり活用できていない。
© GO Inc.使用技術ーUI系ライブラリ52MUI(material-ui) v5言わずと知れた大御所ライブラリ。デカい上に複雑なライブラリだが、管理画面に必要なコンポーネントはほぼ全部揃っている。開発もそこそこ活発。TypeScriptもサポートしている(当たり前か)。EmotionCSSinJS系のライブラリ。MUIは内部で使うスタイリングソリューションを選択することができ、GO管理画面ではEmotionを使っている。react-hook-form + yupフォームは全部react-hook-formとyupで書いてある。yup.InferTypeでschemaから型を作っている。
© GO Inc.使用技術ーテストツール53VitestJestと互換性のあるユニットテストツール。単純に速いJestというだけではなく、Rust-likeなIn-source testingができたりする。Cypress有名なE2Eテストツール。多機能で便利。CI側で落ちたりしてるとデバッグがめんどくさい。今だったらPlaywrightも良さそう(並列テストがやりやすいらしい)。
© GO Inc.後悔していることプロダクト開始直後にStoryBookを導入したことメンテナンスがつらい。ライブラリの依存関係が多く、Chromaticと合わさって巨大ななにかができてきてる。ただのコンポーネント集が欲しいだけならreact-cosmosとかでも良さそう。https://reactcosmos.org/パフォーマンスを測定する仕組みを作ってないある日Lighthouseのスコアを見たらパフォーマンスのスコアが67点だった。90点以上はキープしてたい。54
© GO Inc.やってよかったことAtomic DesignをやめたそもそもMUIを使っているので過剰な設計な気がしてきた。今は/components配下にほぼフラットに配置している。webpackからviteにしたビルドやHMR速い。ビルド時間が約1/3になった。内部でやっていることは複雑そうだけど導入は簡単。55
© GO Inc.おしまい!気になることがあればなんでも質問してください!56
© GO Inc. 57技術全般 X(Twitter)@goinc_techtalkAI関連 X(Twitter)@goinc_ai_techThank You!We Are Hiring!
© GO Inc.文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください