見出し画像

「Web版ツーリングサポーター」リリースの裏側 ~技術スタック編~

こんにちは、キャプテンです。
ナビタイムジャパンで二輪車(バイク・自転車)向けのWebサービス開発を担当しています。

当社では2014年よりスマートフォン向けアプリとして『ツーリングサポーター』を提供してまいりましたが、このたび 4/29(木)に"Web版ツーリングサポーター"をリリースいたしました。
今回はWeb版『ツーリングサポーター』の技術スタックにフォーカスしてお話させていただきます。

『ツーリングサポーター』とは

当社が提供するバイク専用のナビゲーションアプリです。

  • 原付から大型自動二輪まで各排気量に応じたルート検索・音声案内

  • おすすめのツーリングロードや、ルート保存機能によるツーリングの計画

  • 走行ログやバイクのメンテナンス・カスタマイズの記録

  • 複数人でツーリングをする時に役立つ「マスツーリング」

などツーリングライフをサポートするバイク乗りのためのアプリとなっています。

Web版『ツーリングサポーター』について

ツーリングに関わる行動を分類すると下記の3つのフェーズに大別できます。

  1. 計画(ルート作成)

  2. 走行(音声案内・マスツーリング)

  3. 振り返り(走行ログ、メンテナンス・カスタマイズの記録)

今回リリースしたWeb版『ツーリングサポーター』では、走行フェーズを最大限楽しんでもらうために、計画・振り返りフェーズに特化してサービスを提供していきます。

開発背景

以下のような課題を抱えており、それらを解決する一つの手段としてWeb版『ツーリングサポーター』の開発が決定しました。

課題1. バイク乗り向けのルート作成ツールが存在しない

ロードバイク等のサイクリング向けのルート作成ツールは国内外含めて複数存在しています。
一方、バイク乗りのためのツーリング向けルート作成ツールは調査した結果、国内向けでは存在していない状態でした。(2021年夏時点)

課題2. ルート計画の操作はスマホの画面では難しい

スマホアプリ版でルート作成を行う際に、
・地図を俯瞰して見ることが難しい
・指で操作するため、狙った地点にピンを設定できない
といった課題がありました。


技術スタック

ものすごくざっくりとしたシステム構成を紹介します。
前段にフロントエンドアプリがあり、BFF(Backends for frontends)サーバを挟んで、データベースや社内共通APIや外部のAPI(CMS等)からリソースを取得する一般的な構成で稼働しています。

簡易システム構成図

画像にある通り、フロントエンドアプリと BFF サーバで採用している技術スタックは以下のような構成になっています。

フロントエンド

  • ベース言語: TypeScript

  • フレームワーク: Next.js(React)

BFFサーバ

  • ベース言語: Kotlin

  • フレームワーク: Spring Boot


フロントエンドの技術選定

TypeScript

昨今のフロントエンド開発ではTypeScriptが主流であることと、型定義の恩恵を受けられることで複数人による開発をより安全に進められることが主な採用理由です。

Next.js(React)

肌感覚ではありますが、当社では Nuxt.js(Vue.js)を採用しているプロダクトのほうが多いです。
そのため、技術スタックを Vue.js に寄せることも検討していました。
ですが、以下の理由により Next.js を採用することにしました。
※ 技術選定時点で Nuxt 3 は未発表

  • CSR / ISR / SG / SSR という多様な配信方法をとることができる

  • babel, webpackなどの複雑化・属人化しやすい部分が Next.js によって隠蔽化されている

  • Next.js, Reactともに技術記事・ドキュメントの量、他社における採用事例も多く、Reactを取り巻くコミュニティも活発に動いている

Svelte, WebComponents はプロダクション環境で採用するには時期尚早だと判断して今回の採用候補としてはあげませんでした。

APIの型定義

HTTPクライアントラッパーとして aspida を採用しました。
aspida はファイルシステムベースで型定義を記述することで、型安全にAPIリクエストを行えるHTTPクライアントラッパーです。
BFFサーバ側でJSON形式で出力されるAPI仕様書(Open API)を openapi2aspida を利用して一括生成を行っています。

aspida と openapi2aspida の採用により、BFFサーバ側でレスポンス内容に変更が生じた際も下記のようなコマンド一つで更新することができるので、型の定義ミスによる修正など諸々の実装コストを最小限に抑えることができています。

npx openapi2aspida -i http://localhost:8080/api-docs

その他の採用したライブラリ


BFF サーバの技術選定

Kotlin

以下の理由からベース言語として Kotlin を採用しました。

  • Kotlinの特徴としてよく挙げられる利点(Null Safety、Immutability等)

  • 社内のサーバサイド言語として採用ケースが増えており、知見もある程度溜まっている

  • 『ツーリングサポーター』開発チームのメンバーほとんど全員が Kotlin に触れた経験がある

    • 近年の新卒入社者は研修期間中に必ず Kotlin を利用

  • 社内の既存資産は Java で書かれたものが多く、Java のライブラリを取り込み・再利用することで実装コストを低減した上で効率よく開発を進めることができると判断したため

Spring Boot

こちらも Kotlin を採用した理由と近いですが、以下の理由で採用しました。

  • 社内での採用ケースが増えている

  • DI(依存性注入)コンテナが優秀。テストしやすい

  • Springコミュニティ、エコシステムの強さ

開発で苦労したこと / 困ったこと

Springは覚える事が多くて、難しい

Kotlin を書くのは新卒研修以来でしたが、サーバサイドで Java を書き続けていたことから苦労することはあまりありませんでした。

むしろ、Spring 周りで覚えることが多く苦労しました。

  • そもそもアノテーションの数が多い

  • @Bean@Componentの違いは何?@Service, @Repositoryの具体的な違いは?といった疑問

などなど知ってしまえば簡単ですが、調べて使うことにそこそこの時間を費やしてしまいました。

基本的に Spring Boot Reference Documentation に目を通すことで疑問点は概ね解消できます。
アノテーションについては、リファレンスにも網羅的に記述しているページは存在しなかった(存在していたらご指摘いただけると幸いです。)ので、先人たちのまとめ記事を読んでざっくりとした理解をしながら、org.springframework.stereotype パッケージ配下に存在するアノテーション実装の Javadoc に目を通すことで疑問を解消していきました。

プライベートで技術検証のために Spring WebFlux を用いてアプリケーションの構築をしてみましたが、WebFlux はさらに覚えることが多く、より時間がかかりそうです。

Open APIのための定義方法に若干の癖がある

Spring BootではControllerクラスのメソッド引数でクエリパラメータ等の定義を行います。
併せてOpen API仕様書のために@Parameterアノテーションを用いて、情報を付与していました。このアノテーションのSchema定義でミスをするとaspida で取り込んだ時にパラメータが出力されません。

Schema に対して文字列で Data Type を指定する必要があります。

https://swagger.io/docs/specification/data-models/data-types/

文字列で指定するため、存在しない・誤りのある Data Type を指定しても IDE は警告を出してくれません。
Spring Boot側ではビルドエラーも実行時エラーも発生しない上に、openapi2aspida も特に警告・エラーが出なかったため、しばらく気づくことができませんでした。



今後の展望

Web版『ツーリングサポーター』では現在、ルート作成に関する機能のみ提供しています。
将来的には、

  • スマートフォンアプリ版に存在するすべての機能のキャッチアップ(※ スマートフォンに依存する機能を除く)

  • 『ツーリングサポーター』のユーザー以外のバイク乗りが、ツーリングを行う際に参考にしてくれるようなコンテンツプラットフォーム

となることを目指して開発を進めていきます。

バイクに乗る方の一助になれれば幸いです。
これからも『ツーリングサポーター』をよろしくお願いいたします!

Web版『ツーリングサポーター』はこちら

Web版『ツーリングサポーター』に関するご意見はこちらへ 

お願いいたします。