20歳の学生が2ヶ月間で外国人クライアントに向けて作ったサービス

Kaaazu
Kaaazu
Dec 20, 2019 · 7 min read

この Story では私( [@kaa_a_zu] ) が、タイに住みながら2ヶ月間で作ったサービスについて書きます。

きっかけ

サービスについて書く前に何故、私がタイに行ったのかについて書きます。

  • (日本から海外)より(海外から日本)の事業の方が成功している気がする= 海外発信のサービスは日本で使われているのに、日本発信のサービスは海外(アメリカなど先進国)で使われていない

2019年夏にこの違和感について考えていました。そんな時に

上記のような、手島さんの ツイートが TL に流れてきました。海外で働いたら何かが分かるかも知れないと思い、一切の迷いなく、リプを送っていた事を覚えています。ありがたい事に招いていただいて10月からタイ- バンコクでの生活が始まりました。

やったこと

今回、タイ人とオーストラリア人のクライアントを相手に Webシステムの開発をさせていただきました。海外のクライアントという事もあり、彼らとのやり取りに使われるのは英語でした。

概要: 『タクシーの後部座席に備える広告表示サービスを作成する』

メッシュは4つ、
③管理者ページ: 全ユーザーやお金の管理をする
②広告業者ページ: 広告業者が広告を作成出版する
①乗客用タブレット: 広告業者が投稿した広告が表示される
ドライバー用アプリ: ドライバーが自身の評価を確認する

このうち、私は
乗客用タブレット: 広告業者が投稿した広告を表示する
の WebフロントとAPI作成を一貫して作成しました。使用した技術は以下の通りで、PWAとしてホーム画面にDLする事が可能になっています。

Backend: NodeJS(express), MySQL, TypeORM Frontend: React, NextJS
Backend: NodeJS(express), MySQL, TypeORM Frontend: React, NextJS

デモ動画(タブレット)

カメラにより認識した乗客情報を元に乗客に合わせた広告のみを表示する

・広告上の黒背景文字はその広告の「対象性別」「対象年齢」表しています
・広告上の黄色背景文字は顔認識の結果を表しています
※これら2つはデモのために表示をしています

機能

Grid-CSSを当てた4つのフィールドは以下の通りです。

①左(広告表示部分)
②右上(ドライバー情報部分)
③右中(近くの主要場所リスト表示部分)
④右下(近くの主要場所マップ表示部分)

このうちの2つについて詳細な説明をします。

①左(広告表示部分)

以下の3つの情報をもとに広告が表示されます。
1. 乗客の性別
2. 乗客の年齢
3. タクシーの走っている現在地点

それとは別に以下の制約があります。
A. 広告を途絶えさせてはいけない
B. 広告の種類には 画像, 動画, 別サイト の3種類がある
C. それぞれが次の表示されている時間は以下の通り
- 画像は15秒間
- 動画は最後まで再生されたら
- 別サイトは15秒間触られなかったら
D. SKIP機能を持たせる

1. 乗客の性別

2. 乗客の年齢

face-api.js という顔認識ライブラリを使用しました。とても優れたライブラリで、webカメラを使用して認識した顔の年齢と性別を出してくれるオプションがあったためこれを使いました。(※年齢特定において精度が低いのでモデルの変更を現在検討しています)

3. タクシーの走っている現在地点

他の③④の機能でも現在地点の情報は使うため、global stateとしてデータを管理することにしました。(実際の現在地取得はこのコンポーネントではなく、④地図コンポーネントで行なっています) 初めは Reduxを用いた管理をしようとしていたのですが、後述する理由故に Reduxでの状態管理から context を用いた状態管理に変更しました。

  • 現在地を 指定 interval1 での取得
  • 顔情報を 指定 interval2 での取得
  • 広告を 指定 interval3 での取得
  • 各広告の種類に合わせた時間の管理

と、複数の時間の概念を1つの機能内で扱うことは初めてで如何に 保守性, 可読性に優れたコードをかけるかということに時間をかけました。react-hooks の useStateやuseEffectでのsetや副作用のタイミングをここまで加味したのも初めての経験でタメになりました。

フロント側で要素となる情報をサーバーサイドに送り、サーバーサイドではそれぞれの要素を元に広告を返すだけでした。初めて MySQL の GeoPoint関数を使ったのですが、久しぶりに算数ができてよかったです。

最終的にデモ動画にもある通り、全ての要件を達成し、画像,動画,別サイト広告の表示をシームレスに行うことができるようになりました。

④右下(近くの主要場所マップ表示部分)

今回、事業的事情で GoogleMapではなくOpenStreetMap を使いました。そのため、JavaScriptライブラリである Leafletを用いる必要がありました。しかしながら、このLeafletは SSRに対応していなかったため、苦渋の決断ではありましたが、このMapコンポーネントのみ CSRでの表示に切り替えました。NextJSには NuxtJSのような SSRモードというモノはないので、https://nextjs.org/docs#with-no-ssr にあるように Mapコンポーネントを CSRで取得し表示をしました。

技術的に学んだこと

  • Redux(Flux)を使わないという選択

今回のプロダクトでは、コンポーネントの数が少なく、コンポーネントを跨いだProps の利用やバケツリレーも少ししか起こり得ないという状態でした。ここでReduxを組み入れるのはオーバースペックで必要な部分にはContextで十分に代替ができました。

Reactで長期的なサービスを作る = Fluxを使わないといけないというバイアスが綺麗に消えました。何故Fluxを使う必要があるのか(Ex.「今後どのくらい機能が増えるのか」「その時どれだけの開発スピードが求められるか」) を考えた上で使わないなら使わないでいいという事を実感しました。

  • ReactHooksのuseReducerの使い道

今回初めて ReactHooksの useReducer を使える機会がありました。というのも1つのコンポーネント内で上記で綴ったような複雑な state ロジックがあったり、前の state を基に次の state を決める必要がありました。実務でuseReducerを使う機会を探していたので、良かったです。

  • SSRは諸刃の剣

今回 、正直SSRをしてもしなくても良いという状況でした。SEOやユーザー体験のことも特に考える必要がなかったのですが、NextJSを使ってみたかったという私情によりSSRを行うことにしました。結果的にNextJSを使った事で、考慮しないといけない事が増えてしまいました。(Tokenの管理やSSRでは使えないライブラリの対応など)

当たり前のことなのですが、SSRをする際にはトレードオフをしっかりと考えないといけないなと再認識できました。

感想

技術的な学びは勿論ですが、それ以上に 英語の重要性 を再認識する事ができました。色々なところで言われてるように、これからは国間のボーダーはどんどん低くなっていくと思います。それに加えて日本のマーケットの縮小が危惧されており、海外に出て行かざるを得ない状態になると思っています。

20歳という割と若い段階で外国人クライアントを相手に海外でエンジニアリングをするという経験を積め、英語の重要さを身を以て感じれたことは本当に良かったです。

その機会を与えてくださった #GAOGAO の @tejitak さんと Ken/GAOGAO@バンコクさんには本当に感謝をしています。

もしも若いうちに海外に挑戦をしたいというエンジニアにとっては #GAOGAO は最高の環境だと思います。

Kaaazu

Written by

Kaaazu

Japanese Student. 20 years old. WebFrontendEngineer

More From Medium

Related reads

Related reads

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade