見出し画像

【令和トラベル】 NEWT iOSの新規開発における技術選定 2021年版

※これは「あたらしい旅行を、デザインする」でおなじみの令和トラベルのNEWT(ニュート)アドベントカレンダー3日目の記事です。昨日はPMのまがらさんが、明日はCHROのたむさんが担当です。

自己紹介

はじめまして、令和トラベル iOSエンジニアの松井 (@ippo_012) です。

令和トラベルには、グルメECのTASTE LOCALをお手伝いしていたのをきっかけに、今年の5月に1人目のエンジニアとしてジョインし、NEWTのiOSを担当しています。
インタビューしていただいたので、詳しくはそちらへ!

NEWT(ニュート)は「スマートに海外旅行を予約する」プロダクトです。一番最初はホテル・航空券・その他アクティビティや保険等を組み合わせたパッケージツアー(正式名称は募集型企画旅行)を提供します。

旅行予約領域にはShopifyのような便利なプラットフォームが存在しないため、基本フルスクラッチで検索、在庫管理、料金カレンダー、予約、旅程管理等を作る必要があり、なかなか大掛かりなプロダクトです。
プロダクトの概要については 弊社プロダクトマネージャーのふじさんが紹介しているので、そちらもご覧ください。

この記事では、NEWT iOSの新規開発における技術選定について、紹介したいと思います。

チームについて

技術選定の話をする前に、チームについて紹介させてください。
NEWT iOSは2021年12月時点で、フルタイム 1名(松井)、PP(※プロパートナー)さん2名、合計3名のiOSエンジニアとプロダクトマネージャー、デザイナー、その他のエンジニアで開発しています。
コミュニケーションツールは主に以下を使用しており、基本的にフルリモート体制で開発を行なっています。

チャット: Slack
ドキュメント x タスク管理: Notion
ソースコード管理: GitHub
デザイン, ワイヤーフレーム: Figma, Miro
オンラインMTG: Zoom, Google Meet

※令和トラベルでは、副業など業務委託でジョインしている方をプロパートナーさんと呼んでいます。

使用している主な技術

詳細の説明をする前に現在使用している主な技術を一覧にしています。2021年12月時点で以下のような技術を使用しています。

開発言語: Swift
UIフレームワーク: SwiftUI(一部UIKit)
アーキテクチャ: The Composable Architecture(TCA)
その他のフレームワーク: Apollo iOS, apple/swift-format
パッケージ管理: Swift Package Manager
API: GraphQL
認証: Firebase Authentication
決済: Stripe
CI/CD: Bitrise, TestFlight

技術選定の観点

NEWTは前述の通り、「スマートに海外旅行を予約する」プロダクトです。初期はパッケージツアーの提供だけですが、今後様々な機能を実装することを想定しています。そのため、技術選定にはスケールのしやすさ等も考慮に入れています。

またDX担当のまがらさんが紹介しているように、令和トラベルではテクノロジーに投資することを重要視しています。

・アーキテクチャ設計やデータモデリングは妥協せず最善な形を探求する
・技術選定はもちろんコードクオリティも追求する
・それでいて大胆にアップデートし続ける仕組みと勇気を持つ

その上で今回は、次のような観点をもとに技術選定を行いました。

技術的観点
・生産性が高いこと
・保守性があること
・スケーラビリティがあること
・テストがしやすいこと
人的観点
・社内のスキルセットに合っているか
・コミュニティが発展していくか、人材が増えるかどうか
・技術的にチャレンジングかどうか

その他に次のような条件があります。

・選定時期は2021年2月〜4月ごろ
・選定時点で、iOS、Androidのフルタイムエンジニアがそれぞれ1名 + PPさんもそれぞれ1名ずつ在籍

今回は技術選定した中で、次の4つを紹介したいと思います。

① ネイティブ or クロスプラットフォーム
② SwiftUI or UIKit
③ アーキテクチャ
④ CI / CD

① ネイティブ or クロスプラットフォーム

完全に0からの立ち上げだったので、まずはネイティブとクロスプラットフォーム(主にFlutter)の比較検討を行いました。

ネイティブ

Pros
・ネイティブAPIや、新機能を自由に使用できる
・OSに則したユーザー体験を提供できる
・SwiftUIの登場により、Developer Experienceは良くなっている
・Swiftは高機能な言語
・公式であること
Cons
・開発リソースが多く必要になり、開発スピードは遅くなる

Flutter

Pros
・iOS, Androidを同時に開発できる
・ホットリロード等の機能により、Developer Experienceが非常に良い
・Google製であること
Cons
・ネイティブAPIや新機能の使用に一定の制限がある
・パフォーマンスはネイティブに比較すると劣る(改善されており、問題になるのは稀)
・動作は擬似シュミレーションのため、若干違和感がある(気付く人は稀)

結果

前提、個人でFlutterの開発経験もあり、Flutterに対しては非常に好印象を持っています。開発体験は圧倒的に良く、開発速度、Flutter自体の成長速度も魅力的なのでFlutter案も濃厚だったのですが、

  • カスタマー体験を追求するために、要求された仕様に対して、制限なく実現できる状態にしておきたかった

  • 選定時点で、iOS、Androidのフルタイムエンジニアがそれぞれ1名在籍しており(PPさんもそれぞれ1名ずつ)、スキルセットはネイティブに強みがあった

ことや、
懸念である開発速度が落ちる点に関して、宣言的であるSwiftUIを利用することで、部分的に担保することができると判断し、
最終的にネイティブを選択しました。

とはいえクロスプラットフォームに関しては、今後も注視する予定です。実際、NEWTでは部分的にWebViewを活用することで、擬似的にクロスプラットフォームを実現しています。

WebViewを活用する方法は、以下の記事が参考になります。
メルカリShopsのためのWebViewの技術

将来的に部分的な導入や、新規のアプリ開発では、積極的に検討することを視野に入れています。

② SwiftUI or UIKit

前述の通り、宣言的UIであるFlutterと比較検討していたこともあり、UIフレームワークとして、SwiftUIとUIKitの比較検討を行いました。

SwiftUI

Pros
・宣言的なため、直感的に書くことができる
・UIの実装や変更を素早くできる
・アニメーションの実装が簡単にできる
・Appleが提供する新しいソリューションであり、今後も発展が期待できる

Cons
・APIの変更が多い
・未対応のAPIが存在する
・上記に関連してターゲットは現実的に最低でもiOS14以上にする必要がある

UIKit

Pros
・安定している
・今までの知見や事例がたくさん存在する
Cons
・命令的で直感的でない

結果

開発サイクルを高速化したい、また技術的なチャレンジングという点で会社として宣言的UIにベットしたかったこともあり、SwiftUIを選択しました。
iOS14以上をターゲットにすることへチームの合意が取りやすかったこと、UIKitを呼び出すのがそこまで困難ではない(ライフサイクルが異なるので適宜検証は必要)ことも後押しになっています。
Swiftの発展を考えると、2年後くらいにSwiftUIもデファクトになっている可能性も考慮しました。

実際に使ってみて、UI実装に関してはかなり高速に実装をすることができています。プレビューもあり、Developer Experienceは非常に上がっていると感じます(プレビューは不安定な部分も多いですが)。また他の宣言的UIを利用したことのある人にとって、SwiftUIのコードは理解しやすいと思われます。

とはいえ、想定していたとおり荒削りな部分も存在します。
WebViewに対応していないことや、画面遷移、特にPop To Root等の指定した画面へ直接遷移する実装は難しく、ベストなソリューションを模索している状況です。
またFirebase AnalyticsのScreen Eventが自動で送られず、必要な画面に実装して送る必要があるといったライブラリにおける懸念点も存在します。

③ アーキテクチャ

SwiftUIを導入するということで、相性の良さそうなMVVMとThe Composable Architecture(TCA)の比較検討を行いました。

TCA

Pros
・単方向のデータフローで状態変化が明確になる
・依存関係を扱うための仕組みが存在し、テスタブルな構成になっている
・機能をモジュール分割しやすい構成になっている
pointfreeco/isowords等のサンプルプロジェクトが充実している
Cons
・OSSに依存してしまう
・ボイラープレートが多くなってしまう
・学習コストが高い

MVVM

Pros
・実装がシンプルになる
・学習コストが低い
・OSSに依存することなく、実現できる
Cons
・モデル設計やデータの受け渡し方を考える必要がある

結果

最終的に、ある程度レールが敷かれた状態で開発を行いたかったこともあり、TCAを選択しました。

実際に使ってみて、型にはまった開発はチーム間での齟齬が少なく快適であり、良かったと感じています。依存部分もモックの差し替え、テスト環境への切り替えが簡単にできたりと、TCAらしさが感じられます。
TCA自体は積極的に開発されているので、今のところOSSリスクはそこまで感じていません。
またTCAの直接的な恩恵ではありませんが、pointfreeco/isowordsに倣ったモジュール分割やプロジェクト構成は、非常にチーム開発がしやすく、かつXcodeプロジェクトがスッキリするのでここも良かった点でした。
今のところ、Swift Package Managerのみでパッケージ管理を実現できています。

モジュール分割について、詳しくは以下の記事が参考になります。
isowordsに学ぶプロジェクト構成
大規模なマルチモジュール開発をSwiftPackageに移行して運用してみた

デメリットとしてはやはり想定どおりボイラープレートは多くなってしまいました。とはいえ、ここに関しては自動生成等で対処可能かとは思っています。
またレスポンスキャッシュをTCAのストアに格納しているので、Apollo iOSのキャッシュストアの恩恵を受けきれていない点や、Apollo iOSに付随するコードジェネレーターが生成するモデルがEqutableに準拠していないことで、直接的にTCAで扱えない点などに課題を感じています。
前者はフロントエンドにおけるRedux + GraphQLでも同じような議論があり、結論開発者が扱いたい状態はほぼレスポンスキャッシュであり、コンポーネントに状態を閉じるシンプルな構成の方が良いと言われることが多くなっているので、ここに関してはアーキテクチャ再考の余地はあるのかなと考えています。

④ CI / CD

CI環境はモバイルアプリに対して強みのある、Bitriseを選択しています。Androidも同様の環境です。

アプリの配布は、Firebase Distribution等を利用するのではなく、今回TestFlightの内部テスター配布を使用しました。
内部テスター配布は最大100名App Store Connectのチームメンバーにベータ版を審査なしで配布できる仕組みです。App Store Connectに配布対象のユーザーを招待する必要がありますが、面倒な構成が必要でなく、非常に手軽です。
また、実行はSlack Botからブランチを選択することで行えるように構築しています。

TestFlightでの内部テスターへの配信は、以下の記事が参考になります。
Ad hoc配信をやめてTestFlightで配信する

現状CI環境はテストとアプリの配布用に利用しているだけなので、Bitrise + TestFlightのみのシンプルな構成になっています。

これからやっていきたいこと

前述の通り、現在の技術選定に関して、いくつか課題は存在しているので、適宜改善していきたいです。
今後も技術選定に関しては、妥協せず成長に応じて適切にアップデートしていく必要があると考えています。

また、ふじさんのnoteにも記載されていますが、令和トラベルでは、Be Inclusiveをバリューにかかげ、DI&Bプロミスを定めており、すべての旅行者に受け入れられて使いやすいプロダクト作りを目指すことを非常に重視しています。
そのためには次のような対応をしていくことが必要です。

  • アクセシビリティへの対応

  • 多言語化対応

  • 頻繁なワーディングの変更に対応できる基盤の確立

この辺りはまだまだ知見もリソースも足りないので、積極的に投資していかなければいけないと考えています。

おわりに

この記事では、NEWT iOSの新規開発における技術選定について紹介しました。まだまだ課題も多く、発展途上ではありますが、参考にしていただけると嬉しいです。
またAndroid、バックエンド、フロントエンドに関しての紹介記事が後日発表されますので、興味のある方は読んでみてください。

スペシャルサンクス
今お手伝いしていただいているPPさんたち、今までお手伝いしていただいたTake OffされたPPさんたち
フルタイムのiOSエンジニアが自分1人なのでいつも非常に助かっています🙌

※令和トラベルでは、卒業のことをTake Offと呼んでいます。

ここから採用PR

令和トラベルでは一緒にNEWTを作ってくれる方を募集しています!

  • 「あたらしい旅行を、デザインする」ことに挑戦したい方

  • 令和トラベル・NEWTの技術に興味を持っていただいた方

  • 旅行が好きな方

上記に興味のある方、ぜひぜひコンタクトお待ちしています!

Meety開設したので、お気軽にお声がけください!

Twitterも定期的につぶやいたりしているので、よければフォローしていただけると嬉しいです!

Twitter:https://twitter.com/ippo_012

🐢おまけ🐢

おまけで、僕のおすすめのTASTE LOCALの商品、出羽屋さんの月山山菜そばを紹介させてください!年越しそばにぴったりです!