production.log

株式会社リブセンスでエンジニアをやっている星直史のブログです。

ReactNative版Snapmartアプリ開発の舞台裏

概要

先日、SnapmartのスマホアプリをReactNative + Expoで実装を行いました。

texta.pixta.jp

ピクスタ開発ブログに書いた内容だと、カッコ良いところしか書けなかった気がするのと、協力してくれた方々について全く触れることができなかったので、この記事では「当時の心境や協力してくれたみなさんの活躍など」に触れながら、自分視点で書こうと思います。 そのため、誰かのためになるような書き方ではないので、チラ裏思い出日記くらいに思っていただければと思います。

2018年11月末

スナップマート社に関わり始めたのは2018年11月末あたりからでした。
代表には「スマホアプリのAndroid版を作って欲しい」という話を聞きました。*1

当時の自分

自分は、バックエンド(Rails)、Webフロントエンド(React)、インフラ(AWS)と、Webに関しては一通り手を動かせるスキルは持ち合わせていました。
これらの領域、個別具体的なスキルの習得は、

  1. アンテナを張る
  2. 特定の技術の戦国時代をゆっくり眺める
  3. 戦国時代を駆け抜けた特定の技術がデファクトスタンダードとなる
  4. デファクトスタンダードとなった技術を習得する

という感じで、「最新の技術動向は追いかけるけど、習得は安定化されてから」といった具合でした。
ただ、Webについては比較的カバー範囲は広めですが、スマホアプリの開発ができないことがずっとコンプレックスになっていました。

4年前の自分

もっと突っ込んで話すと、時を遡ること2015年8月。
ピクスタでメインエンジニアとしてやっていた頃、スマホプロジェクトに携わることになりました。(当時は自分のスキルはRailsしか書けませんでした)
当時はSwift 2.x系だったのですが、この偶発的機会を活かすべく、学習にかかろうとしたのですが、様々な理由から断念しました。

  • Xcodeの扱い方がわからない。故にSwiftを学ぶモチベーションが湧かない
  • 同プロジェクト内にiOSアプリ開発経験豊富なエンジニアがいる
  • Knowledge Transferを目的にSwiftを触ることもできたが、自分がSwift実装した場合にスマホプロジェクトを完遂させる自信がなかった

上記の点を考慮して、iOSアプリ開発経験豊富なエンジニアに任せることにしました。外野から見てもこの意思決定は合理的だと思います。 しかし、開発中もずっと「自分もSwift書きたいなぁ〜」と思っていました。自分で意思決定しながら、開発中に後悔し始めていました。

まぁ、簡単にいうと、失敗を恐れて、自分ができる範囲で気持ちよく実装することを選択したわけです。
そのプロジェクトは多少スケジュールが押したものの、成功と呼べるものになりました。
ただ、その中で、逃げの選択をした自分に対して激しい怒りと失望をしたのを今でも覚えています。

そんなこんなで舞い込んできたスマホアプリプロジェクト。
依然としてスマホアプリ開発の知識は0でしたが、このチャンスを逃したら後悔することは自明であるため、二つ返事で「やります」と返答しました。

あと、色々言い訳をして逃げるような状況を作りたくないというか、、退路を断つために「3ヶ月くらいでイケるんじゃないですかね」と、各方面に風聴しました。*2
自分は心の中でやり切ると決めたことは、完全勝利を収める以外の着地は考えられないので、自らを奮い立たせることができました。

2018年12月

12月は主に技術選定と、技術調査を行ないました。
ピクスタ開発ブログでも書いた、あるべき姿と現状の乖離を埋めるためにReactNativeを選定したってやつです。

技術選定

技術選定する際も、公式ドキュメントやAPIの充実具合、そこからくる実現可能性はみるのですが、

  • ReactNativeは日本語の情報が皆無
  • 不具合が多数存在している
  • 不具合に遭遇した場合はIssue, Pull Request, Release Note, feature branchなどを読まなければならない
  • 自分は英語が読めない/(^o^)\

という、不安しかない状況でした。
ただ、それと同時にExpoという開発ツールの存在を知りました。
Expoの公式ドキュメントを見るとAPIが充実していることや、JavaScriptの世界だけで生きることが可能であることがわかりました。
Expoに負んぶに抱っこしてもらえるのであれば、なんだからイケそうな気がしてきたので、このタイミングでスナップマートの代表と役員に「12月中は技術調査をします。これでダメだったらReactNativeはやめる。」ということを話しました。

技術調査

技術調査は、大きく2つ行いました。

  • 既存iOSアプリを模倣するための手段の確立
  • 既存のSnapmartアプリの主要機能をReactNativeで実装していけるか検証

技術調査は、フィジビリティスタディの技術版と考えて良いと思います。
特定の技術について、実行可能性や様々な要因を検証することが目的です。中でもReactを学習したエンジニアが実装していけるかがピクスタ開発部に逆輸入できるかを分けるのではないかと考えていました。
今回の開発においては、上記2点が調査ポイントであると同時に最大の障壁であるわけですが、この2点に「できる」と答えられるのであれば、あとは問題は作業レベルに粒度が下がるため、時間との戦いになります。
問題が時間になっているということは、リリースに対して他に障壁がなく確実に到達できるとも言えるので、この状態をまずは目指しました。

既存iOSアプリを模倣するための手段の確立

ピクスタ開発部ブログで書いたこちらの手段の確立(検証)です。

  • APIサーバーのRoutingを知る
  • 元々存在するSwift製iOSアプリのエミュレーターからlocalに立てたAPIサーバーにリクエストできるようにする
  • リクエストの内容を確認する
  • APIの処理を読む
  • レスポンスの内容を確認する
  • エミュレータ上のアプリの動作を確認する
  • ネイティブの処理を読む

実は、これを検証するだけで12月の半分が過ぎました。
と、いうのも、既存iOSアプリの実装者は既に退職済みであるため、エミュレーターの立ち上げ方がわからず、スマホ側の問題は全て自分で解決していかなければならなかったからです。
一応、iOSアプリのリポジトリのREADME.mdに3行程の導入手順が書き記されていたものの、すんなり動くわけもなく、大量のエラーが発生していました。*3
非常にまずい状況ですね。

ただ、土地勘のないSwift周りのモジュールでも、不思議と、Issue, Pull Request, Release Note, feature branchをひたすら読んだら、徐々に何が問題なのかが分かるようになるんですね。

そして、やっとこさエミュレーターが動いたのが、12月17日週でした。 そこからはRailsの世界の話なので、数日で模倣することが可能であることがわかりました。
ただ、残り4営業日中にもう片方の技術調査をしなければならない状況です。

既存のSnapmartアプリの主要機能を実現できるか検証

時間がないので、世の中がクリスマスムードで煌めいていようが、会社の忘年会が行われていようが、それ横目にひたすら検証です。

こちらは、「既存機能の確認 <=> ReactNative + Expoのドキュメントを読んで実現できるかを小さいアプリを作って検証」をひたすら行いました。

とにかく機能要件を満たせるかが分かれば良いので、見た目はガン無視で進めました。 この時点で主要機能である下記が満たすことができれば、OKとしました。

  • Facebook認証
  • カメラロールから写真選択および、アップロード
  • カメラを使った写真撮影
  • ナビゲーション
  • スワイプ処理
  • Push通知

時間が足りない

とはいえ、時間が圧倒的に足りませんでした。
自分がスナップマートへ関われる時間の比率50%程度(週20時間)でした。

  • 50%: ピクスタの部長業務
  • 50%: スナップマート対応

という感じです。
また、スナップマートの対応は完全にAndroidに集中できるわけはなく、

  • 業務改善タスク(Rails)
  • 業務仕様把握
  • インフラ仕様把握
  • スナップマート開発方針策定
  • 開発フローの是正
  • Android化を見据えたサイト高速化
  • AWSコスト削減
  • 不具合/障害対応
  • エンジニア / デザイナー採用業務
  • アルバイトフォロー

上記の業務を週20時間の制約の中で並行して行う必要があります。
そのため、技術調査は上記が終わってからやっと行えるという感じです。

幸い、自分は平日3時間、休日8時間は自己研鑽を10年間くらい行なっていたことと、残業と深夜対応を物ともしない体力がありました。 そこで、時間を捻出するために可処分時間を全てReactNativeに充てたらどうか?という計画を立ててみました。

平日: (3時間自己研鑽 + 残業4時間 + 所定4時間) * 5営業日 = 55時間 休日: ちょっと多めに12時間 * 土日2日 = 24時間

1週間で79時間をReactNative調査に充てることができる計算になります。
所定8時間で働く人の倍の時間が使えることになります。 そうなると「3ヶ月でリリースします」というのは、普通の人の6ヶ月相当となるのでなんだか勝てるような気がしてきました。
今振り返ると、ピクスタの業務と合わせると作業時間が月400時間近くになるのと、それを4ヶ月継続したのには流石によくやったなと思います。*4*5

2019年1月

年末年始は通常業務が完全停止するのでボーナスタイムです。
通常業務が剥がれる代わりにReactNative調査に時間を割くことができます。
しかし、正月は実家に帰省していたのですが、開発環境が貧弱である為、進捗はあまりでず検証が済みませんでした。*6

スナップマートの週次定例は毎週火曜日に実施するのですが、1月8日(火)はまだリハビリ期間なので、1月15日(火)の定例で技術調査の結果を報告することになります。
この時点でFacebook認証とPush通知は実装方法がよくわかっていませんでした。ただ、両方ともExpoでサポートされているので、実装は不可能ではなさそうでした。
そして迎える1月15日の定例、多少不安がありましたが、大方問題なく動作することがわかっていたのでReactNativeで行くことに決めました。
リリースまでの期間は変えず、3月末です。

最初期のReactNative + Expo版Snapmartアプリ
最初期のReactNative + Expo版Snapmartアプリ

1月以降の実装の大まかな流れは、下記の通りです。

~1月20日: 各種ライブラリ類の整備 ~2月20日: フロントエンド処理の実装 ~3月20日: レイアウトの調整 ~4月20日: 動作確認

ReactNativeは基本的にReactで開発を行うので、1月中はモダンなライブラリを導入していくことにしました。 具体的には下記です。

  • TypeScript
  • Redux
  • axios
  • redux-saga
  • React Navigation

State管理、API処理(非同期処理)、ルーティングさえ最初に整備しておけば、あとは整備されたお作法に則って実装すれば良いという状況を作りました。 基本的にはJavaScriptの世界で実装できるので、特に大きな問題はありませんでした。

2019年2~3月

2019年2~3月は特に大きな変化もなく、12月確立した開発方法(エミューレータ<=>APIのデバッグ)と、1月整備しておいたお作法に則り、粛々と実装を行うのみです。
だいたいそうだと思いますが、数画面実装を行えば勝手がわかるので淡々と実装するだけのマシーンになります。そのため、大量のタスクをモチベーションを下げずに長時間実装を行うのには、コツが必要です。
一人で実装していて、方向を見失うことはまずないと思いますが、全部で70画面くらいあるのでタスク管理はしました。

  • 全体のタスク量
  • 現在消化したタスク量
  • 今週タスクすべきタスク量
  • 日進率の乖離

これらを管理するのは当たり前として、
自分は易きに流れるので、自分の気を引き締める為にタスク管理を通して自分を管理下に置きました。

Androidアプリ開発に使っていたTrello
Androidアプリ開発に使っていたTrello

期間中、合計1,244件のカードを対応しました。 最初は全てのカードがTodoに存在するので、その数に圧倒されましたが、2~3週間もすれば自分が1週間でどれほどのカードをDoneにできるか、何時間でどれくらいの処理が書けるのかが把握できてきます。
この情報さえ把握できれば、バーンダウンチャートを作成することが可能なので、現在の状況や進捗を的確に把握し実装完了までの見込みを話すことができました。

見せることができない状態

先述の通り、開発の進め方は処理の実装 => レイアウトの調整 => 動作確認と進めていく予定でした。
しかし、この進め方は不確実性の排除を第一に目的とした実装順序です。 そのため、自分以外の者はレイアウト調整が終わり、デバイスを用意し終えた後の動作確認の段階にならなければ、成果物が見えません。
開発者しか進捗がわからない完全ブラックボックス状態なので「本当に実装できているのか?進捗は虚偽ではないか?」と思われかねません。

幸いにして、スナップマートの代表や開発時に連携するメンバーは、自分の進捗報告を信じて待ってもらったのには本当に助かりました。
もし、進捗を事細かに報告しなければならない状態(雑務が増えた状態)であれば、時間を浪費してしまうことや、モチベーションが低下していたのかもしれません。

今回はこの進め方がたまたまうまくいったことは重々承知ではあるのですが、

  • PJの特性
  • 周りの方々の自分に対する信頼

がうまく噛み合った結果だと思います。 スナップマートの代表が「早く見せて」「いつ動かせるの?」と、一切口出ししなかったのにはシビれました。最高でした。

2019年3~4月

3月末から4月は実装が終わり、いよいよ動作確認です。 当初、自分がテストシナリオを作成して、メンバーに対応してもらうと考えていたのですが、実装の多さからテストシナリオを書く余力(時間)が残っていませんでした。

というより、月400時間前後を仕事に関連することを行なっていると、流石に疲労がピークとなり、気力もなくなりかけていました。
そんな状態だったので、テストシナリオの作成が滞ってしまいボトルネックになりかけていました。その状況を救ってくれたのはスナップマートのWebディレクターの方でした。
「テストシナリオが今の自分では作れなさそう」ということを申し出るまえにその方が一気に作り上げてくれました。
これにはとても救われました。
その方の当事者意識やガッツ溢れる姿をみて、自分にも活力が湧いてきたことを今でも覚えています。

3月末から4月上旬にかけてのラストスパート
3月末から4月上旬にかけてのラストスパート

GitHubのコミット数を可視化すると、上記の通り3月末から4月上旬にかけての追い込みがわかります。

インターン生が大活躍した動作確認

テストシナリオは400件弱の項目がありました。
また、異なるAndroidバージョンで実機による確認を行いたかったので、4端末で確認することにしました。

  • 6.1
  • 7.0
  • 7.1
  • 8.0

1デバイスあたり400件全て確認するので、合計1,600件のテストです。
この膨大な量を一人で短期間でこなすのは困難であるため、Webディレクター、インターン2名の計3名に応援をお願いしました。

この3名が非常に粘り強く、責任感ある3名でした。
自分が決めた無理のあるリリーススケジュールに対して、前向きに取り組んでくれました。
休日に対応してくれていることを褒めるわけではないですし、自分が休日に開発を行なっていることを彼等彼女等は知っているので、それが圧力になったのは本当に申し訳ないと思っているのですが、プライベートの時間を削ってまで対応をしてくれました。

この3名の頑張りがなければ、予定通り実装が終わらなかったのではないかと思います。
本当に感謝しかありません。

Webディレクターの柔軟な意思決定とラストスパート

彼ら彼女らの動作確認のおかげで、短期間で不具合を発見することができました。
その数、140件でした。一瞬怯みそうになりましたが、3ヵ月全ての機能を自分一人で実装していたので、プログラムが全て頭の中にロードされている状態でした。
この状態になると、不具合の内容をみた瞬間に、どのファイルの何が原因で不具合が起きているから、どのように修正するかが瞬時に判断できるようになります。
そのため、多少量が多くとも1件あたりの難易度が低いので、ほぼ瞬殺対応することができました。

また、不具合の中でも対処するか判断に迷うものもありました。
それは、下記のような内容です。

  • ReactNativeでは実装ができない
  • 実装に時間がかかる
  • 実装の難易度が高い
  • 完全にiOS版アプリの挙動を模倣できていなくとも、今は問題ない
  • 機能として欠落しているが、まだ必要にならない

これらは、基本的にエンジニアのスキルが高ければ相談するまでもなく対応できるのでしょうが、当時の自分には全て実装することは無理だと感じていました。
そこで、Webディレクターやメンバーと協議をしながら進めることにしました。

ピクスタの開発ブログで、

チーム全体が「ReactNativeでは実装できません」を許容し、柔軟に仕様や要件を変更しながら落とし所を決めていくことが求められます。

と太字にして強調しましたが、上記の意思決定プロセスがチームで自然とできていたので、迅速に取捨選択を行うことができました。
つい完璧を求めてしまい、ずるずるとリリースが伸びることも想定していましたが*7、これほどまで柔軟に変更を許容できるメンバーをみて感服しました。

2019年5月

実装~動作確認~不具合修正は4月15日(月)に完了しました。1月15日(火)本実装開始から、ちょうど3ヵ月くらいの着地です。
実際のリリースは2019年5月7日(火曜)なので、実装完了~リリースまで2週間のタイムラグがありますが、

  • RubyKaigiへの参加
  • ゴールデンウィーク期間中

無理にリリースして上記の期間中にお問い合わせが発生した場合の対応を考えると、ゴールデンウィーク明けに安心してリリースしたいよね。となりました。
もちろん、この2週間はリリース後対応などを行なっていました。駄目押しの実装という感じです。

まとめ

2018年末、スナップマートの代表も「3ヵ月でできるわけがないだろう」と思っていたようですが、自分も同じことを思っていました。

  • 目標を掲げて見つめ続ける
  • 置かれた状況に怯まない
  • 自分ができることを整理して実行する
  • 限界まで懸命に頑張る
  • メンバーに頼る

困難な道のりでも、常にこれを着実に実行することで目標は達成できるものだと身を以て体験できました。
振り返ると、20代最後のチャレンジが人生最大のチャレンジになりました。
全力で取り組んで目標達成できるのは本当に楽しいですね。仕事の醍醐味だと思います。

このリリースが終わったら2ヵ月くらい休むんだ...。とか思っていましたが、休んでいるより自分が作っているサービスを育てている方が何倍も楽しいことにも気づきました。

今後

無事にReactNativeでAndroid版のリリースができました。程なくしてiOSアプリもReactNative製になります。
先に書きましたが、自分は元々Webの世界しか知らなかったわけですが、WebエンジニアでもReactNative + Expoによってスマホアプリ開発が可能だと検証できました。

話が少しだけ飛躍するかもしれませんが、ウチの会社の長期成長戦略として"様々な分野でクリエイティブプラットフォーム"を生み出そうとしています。

pixta.co.jp

近い将来「新規事業ではスマホアプリを最初に作りたい」というビジネス要求は十分にありうるのではないかと考えています。
現在の開発部はWebエンジニアがメインであるため、この要求を迅速に満たすことができない可能性が高いです。
その場合、ただでさえ成功確率の低い新規事業がエンジニアの力量不足による制限プレイでさらに成功確率が低くなってしまいます。
これは許しがたい状況なので、なんとかして突破口を開こうとしたのが、実はこのSnapmartのReactNative実装だと勝手に思っていました。

今なら「新規事業ではスマホアプリを最初に作りたい」に対して「3ヵ月くらいでできるんじゃないですかね?」と答えることができそうです。

*1:意思決定の背景や理由の説明はもちろんありました

*2:これは本当に良くないと思っています

*3:Xcodeも爆発するし大変でした

*4:自分の長所が一生懸命頑張ることです!

*5:自由意思によるものです。エキサイティングな4ヶ月だったので楽しかったです。

*6:こちらも自由意志によるものです。友人が極少であるため。

*7:自分がPOだったらそうなりそう...