未経験からモダンな技術を学んで「バーチャル旅行を楽しめるサービス」を立ち上げるまで【React / Rails / Firebase Authentication / Google Map / YouTube API】

# はじめに

こんにちは！**いとう([@Ito_GeekHatch](https://x.com/Ito_GeekHatch))** と申します。
未経験からWebエンジニアを目指し転職活動中です！

転職活動用のポートフォリオとして
**「地図と動画でバーチャル旅行を楽しめるWebアプリ」** を個人開発しました！
開発したWebアプリに加えて、自己紹介とこれまでの学習歴、これから挑戦したいことについて紹介させていただきます！
未経験からWebアプリをポートフォリオとして開発する予定の方の参考になれば幸いです🙇‍♂️

:::note warn
**ご注意**
なかなかの長文になっております。
「制作したアプリのことだけ知りたい！」という方は
**[2. ポートフォリオの紹介](#2-ポートフォリオの紹介)** をご覧ください🙏
:::

# 目次
[1. 自己紹介](#1-自己紹介)
[2. ポートフォリオの紹介](#2-ポートフォリオの紹介)
[3. 技術選定の理由](#3-技術選定の理由)
[4. 学習過程](#4-学習過程)
[5. 今後の展望や挑戦したいこと](#5-今後の展望や挑戦したいこと)
[6. 終わりに](#6-終わりに)


# 1. 自己紹介
大学を卒業後、10年間営業職をしていました。
営業職といってもゴリゴリの新規開拓営業ではなく、納期や価格の調整がメインのBtoB営業をしていました。
営業職を続けていく中で、自分のスキルと言えるようなものが身についていない感覚にずっと違和感を感じており、「会社が変わったら何もできない自分」にコンプレックスを感じていました。
一方で、技術者たちが専門知識を武器にバリバリと現場で動き回る姿を見て、エンジニアという働き方に魅力を感じていました。中でも身近に存在するWebに関わるサービスを開発し、場所を選ばず価値を提供できるWebエンジニアに強い魅力を感じたため、退職を機に転職を志し、学習を始めました。

### プログラミング学習歴
| 学習方法 | 学習内容 | 学習期間 |
| :-- | :-- | :-- |
| 1. 独学 | HTML/CSS/JavaScript/React など | 3ヶ月 |
| 2. プログラミングスクール | Ruby/Ruby on Rails/Docker など | 3ヶ月 |
| 3. ポートフォリオ開発 | React/Firebase Authentication など | 3.5ヶ月 |


# 2. ポートフォリオの紹介
### バーチャル旅行アプリ「BackHacker.」
![BackHacker_thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/48f0537c-3397-628a-4fb2-1818d9cff04d.png)

### サービス概要
BackHackerは、**「自宅にいながらPC一台でバックパッカー」** をコンセプトとした、旅行好きのためのエンタメアプリです。 地図上から世界中の都市を直感的に選んで、街並み動画を見ることでバーチャル旅行を楽しむことができます。 

#### ▼サービスURL

https://backhacker-frontend.vercel.app

ログインなしでも基本的な操作は可能です！ぜひ触ってみてください！
レスポンシブ対応済みです。


#### ▼GitHubリポジトリ

https://github.com/ITOmaSabai/BackHacker

#### ▼紹介ポスト(X)

https://x.com/Ito_GeekHatch/status/1790676910722498794

### サービス作成の背景
私は旅行が趣味ですが、旅行に行けないときはGoogle Mapを眺めて**バーチャル旅行**をしています。
加えて、YouTubeでの街歩き動画を眺める趣味もあります。
地図で気になった際には、YouTubeでその土地の街歩き動画を見て楽しんだりしていました。しかし、「地図を見る→気になった場所を見つける→YouTubeを開く→動画を検索する」というプロセスに**煩わしさを感じていました**。
 
その煩わしさを解消するため、地図上の気になる場所を見つけたら、**その場で動画を視聴できるアプリがあれば便利だ**と考えました。
また、地図と動画の2つを組み合わせれば、より解像度高く知らない土地の情報を見ることができ、**バーチャル旅行がもっと楽しくなる！** とも考えました。

上記の2つの理由から、本サービスを開発することとしました。

余談ですがサービス名の「BackHacker.」は、バックパッカーとハッカーをかけたのですが、あんまり「ハッキングしてる感」は演出できなかったので、もう少しバーチャル旅行を押し出した分かりやすい名前にすればよかったなぁと後悔しています。



### メイン機能の使い方

| スポットを見る | スポットを投稿する |
| :--- | :--- |
| ![view_spots.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/8cac17af-5303-af71-3d98-8b15c4787473.gif) | ![post_spots.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/72f9b464-2956-6698-da92-bd348692095a.gif) |
| 地図上のピンをクリックします。モーダルが動画を見る場合は、開いたモーダルの動画サムネイルをクリックします。 | 地図上をクリック後、スポットを投稿ボタンを押下します。次に、スポット名と説明（任意）を入力してから投稿するボタンを押下します。 |

:::note
動画は自動で取得される仕様となっています。
#### 仕組み
クリックした場所の住所(例えば"Japan Tokyo Shibuya"など)をMaps JavaScript APIから取得します。次に取得した住所を検索ワードとして、YouTube Data APIから動画を取得します。最後に取得した動画を保存し表示しています。
:::

| いいねする | コメントする |
| :--- | :--- |
| ![likes.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/203bca79-e631-680a-9765-1179d54ee014.gif) | ![comments.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/dc73cbfc-4672-cdf3-db5f-3397a1bd457c.gif) |
| スポット詳細画面のハートのボタンを押下します。いいねを解除するには、もう一度押下します。ボタンの横の数字はいいね数を表しています。 | スポット詳細画面の吹き出しボタンを押下するとモーダルが開きます。コメントを入力後、投稿ボタンを押下します。コメントを削除するには、コメントの横のゴミ箱アイコンを押下します。 |


### 機能一覧
- ユーザー登録機能
- ユーザー削除(退会)機能
- ユーザー情報機能
- ユーザーの投稿したスポット一覧機能
- ユーザーのいいねしたスポット一覧機能
- ログイン機能
- ログアウト機能
- スポット新規投稿機能
- スポット削除機能
- スポット編集機能
- スポット一覧機能(地図上に表示)
- いいね機能
- いいねしたスポットの一覧機能(地図上に表示)
- コメント投稿機能
- コメント削除機能

### 使用技術
| カテゴリ | 技術 |
| :---| :--- |
| フロントエンド | React 18.2.0 |
| UIコンポーネント | Material UI |
| コード解析 | ESLint |
| バックエンド | Ruby 3.2.2 / Rails 7.1.3 |
| データベース | PostgreSQL |
| 認証 | Firebase Authentication |
| インフラ | Vercel(フロントエンド) / Render(バックエンド) |
| API | Maps JavaScript API(Google Map) / YouTube Data API |
| その他 | Axios / react-google-maps / react-lottie-player / react-spring |


### 工夫した点
アプリやサービスを使用する際、ユーザーが操作性に違和感を感じるとストレスとなり、そのストレスが溜まるとサービスからの離脱につながってしまうのではないかと仮説を立てました。
そこで、ユーザーがストレスを抱えないように以下の工夫をし、ユーザーが楽しいと感じてもらえるものにしたいと思いました。

##### ▼ユーザーが次のアクションに迷わないようにするため、次のアクションを促すモーダルを表示して誘導するようにしました。
| 新規投稿完了後のモーダル |　ログイン誘導モーダル |
| :--- | :--- |
| ![post_spot_modal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/69b2a14c-c5d7-7d8b-95a5-062242ab1d15.gif) | ![login_modal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/20bae450-96f0-1d76-e20a-5540a7410426.gif) |


##### ▼ユーザーが操作に迷わないように、よりユーザーが取りやすいアクションを予想してボタンの配置と配色を選択しました。
| 「投稿する」ボタンを強調 | 「投稿を確認する」ボタンを強調 |
| :---: | :---: |
| ![button_example_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/b1d6407e-0bd9-079f-a321-1df5bf62a534.png) | ![button_example_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/7f6de9bf-2009-29ad-4e6a-437e8364359d.png) |

##### ▼Googleアカウントでのログイン機能を実装しました。
採用した理由は、ユーザー登録の手間を減らすことで、登録ユーザーを増やせると考えたためです。
Firebaseから取得したトークンをバックエンド側に送信してデコードしトークンの正当性を検証する実装をしたのですが、トークンが送信されているのか、どこまでデータが取得できているのかわからずかなり苦労しました。
スクールの先輩に教えていただきながら、一行ずつデバッグをしながら確認を進めました。
実装時間は、全部の機能で一番長くかかりました。


##### ▼バーチャル旅行の没入感を演出するために、画面の全面に地図を表示するようにしました。
| PC画面 |
| :--- |
| ![map_laptop_view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/7f1cfc3b-625f-3379-7c24-aadedb636d4d.png) |


| スマートフォン画面 |
| :--- |
| ![map_smartphone_view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/ed7e9ba9-c489-8001-beb5-4aa2d7e50587.png) |




### ER図
![er-diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/2e817644-750e-8e22-9c5a-4df5cf69a1f8.png)


### 画面遷移図
[画面遷移図(Figma)](https://www.figma.com/design/gM0GshoqZXcmSWJeINOdt2/BackHacker.?node-id=0-1&t=AcCxx29zZgj9309B-0)


# 3. 技術選定の理由

### フロントエンド: React
Reactを使ったアプリの開発経験はほとんどありませんでしたが、以下の2つの理由からReactを採用しました。

1. JavaScriptで描画するGoogle Mapの制御を容易にするため
2. 充実したUIライブラリを活用し、リッチなUIを構築してユーザー体験を向上させるため

特に2の理由を重視していました。理由は、複雑な機能を持ったツール系アプリではなく、エンタメ要素の強いWebアプリあったために、ユーザーに継続して使用してもらうためには見た目や操作性を向上させることが効果的だと考えたからです。
なお、ReactのフレームワークであるNext.jsは、キャッチアップコストと得られるメリットを比較検討した結果、今回は導入を見送りました。

### バックエンド: Ruby on Rails
フロントエンドのキャッチアップに時間を要すると判断したため、最速でバックエンドを構築したいと考え、学習経験のあったRuby on Railsを選定しました。

### 環境構築: ローカル
Dockerの使用も検討しましたが、最短時間で環境構築をし、フロントエンドの構築に時間を割きたかったため、ローカルでの環境構築を選択しました。

### 認証: Firebase Authentication
以下2点の理由から、Firebase Authenticationを使ったGoogleログインを選定しました。
1. 機密情報の漏洩を避けるため
2. ログインにおけるユーザーの工数を削減するため

1については、ユーザーのメールアドレスやパスワードなどの機密情報を、自分のデータベースに保存せず外部サービスに保存することで、情報漏洩のリスクを低下させる狙いです。

2については、Googleアカウントにログイン状態であればパスワードを入力する必要がなく、ユーザーの手間を削減でき、結果としてユーザー数を増やせると考えました。また普及率の高いGoogleアカウントであれば、ユーザーがログイン状態である可能性も高いと考えました。

### インフラ: Vercel / Render
以下の2点の理由から、VercelとRenderを選択しました。
1. ドキュメントが豊富に存在していて、設定が容易である点(フロントエンドの構築に時間を割くために、環境構築の時間を最小にしたかった)
2. 基本利用が無料である点(個人開発アプリを長く維持するためには、運用コストは最小限に抑える必要があると判断したため)


### ブラッシュアップの方針
今後は以下を追加して、サービスをブラッシュアップしていきたいと思います。

#### 1.通知機能の追加
アプリ内で、自分の投稿したスポットに対していいねやコメントがついた場合に、ユーザーにお知らせする機能を実装予定です。
目的は、ユーザーとサービスの接点を増やすためです。私は通知が来ているか確認するため、Xなどのアプリをついつい開いてしまうことが多いので、ユーザーがアプリを開きたくなる仕組みとして導入したいと思います。
| 実装イメージ |
| :---: |
| ![notification_feat_demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/22b8de6a-ec10-4a14-2901-a4ec8c4b6a2d.gif) |


#### 2.最新の投稿をトップに表示する機能の追加
目的は、ユーザー同士の交流を促しサービスを活性化させることです。
トップページに最新の投稿が一覧表示されることで、いいねやコメントなど、ユーザーからのリアクションが集まりやすくなると考えました。リアクションが得られると投稿者に通知(前述の機能)が表示されるようにして、アクティブユーザーが増えサービスが活性化すると考えています。


#### 3.セキュリティの向上
ユーザーを情報漏洩や不正アクセスから守るためにセキュリティを強化したいです。
URLパスにidを使っているので、別のuidを使用したり、またRails側にserializerを導入したりして、セキュリティを基礎から学び、堅牢なアプリにしたいです。

#### 4.ローディング画面の導入
ユーザー体験を向上させるために導入したいと思います。
API側からデータを取得する際に画面がチラついたり、画面のレイアウトが崩れることでユーザーに違和感を感じさせてしまい、ユーザーにストレスを与えてしまっていると思います。
自分が試した際には通信環境が良好で、ロード時間が一瞬だったのでローティング画面がなくても気にならなかったのですが、通信環境が悪い状況ではユーザーの感じ方が全く違う（というか悪い）と思います。そのため、自分の環境のみでなく、あらゆるユーザー環境を想定して開発をしていく必要があると学びました。

#### 5.テストコード
開発スピードの向上のため、テストコードを書いていきたいです。
バグの早期発見ができ、安心してリファクタリングができるようになるので、開発がよりスムーズになると思います。

#### 6.エラーハンドリング
サービスが停止してしまうことのないように、正常に動く前提でなくエラーが発生する可能性を考慮してコードを書いていきたいと思います。


# 4. 学習過程
ポートフォリオを作成するまでの私の学習過程を時系列順に振り返ります。
未経験からWebエンジニア転職を目指す方のご参考になれば幸いです。

### 独学(3ヶ月)
学習内容：　HTML・CSS・Sass・JavaScript・React
使用教材：　Progate、書籍、YouTube、Udemy講座
学習時間：　およそ200時間
詳細：　
まずはProgateを使ってHTML、CSS、JavaScriptを学習しました。その後、書籍やYouTube動画を見ながら、静的Webサイトの模写をして学習しました。
その後、より複雑な画面を持ったWebアプリケーションを開発してみたいと思うようになり、Udemy講座を中心にReactの学習をしました。
Reactを選んだ理由は、Webサイト制作の学習から入ったために、「ユーザーの目に見える部分にもっとこだわりたい」と考えたためです。
まずは講座を見ながらコーディングをし、簡単なTODOアプリの作成をしました。


### プログラミングスクールでの学習(3ヶ月)

学習内容：　HTML・CSS・Ruby・Ruby on Rails・JavaScript・SQL・Git・GitHub・SCSS
使用教材：　スクール独自カリキュラム
学習時間：　およそ600時間

プログラミングスクール「RUNTEQ」に入学しました。
入学の決め手は、高レベルなポートフォリオを作成する力が身につくと感じたことと、受講生同士のコミュニティ活動が活発であり、Webエンジニアとしてのカルチャーを学べる点に魅力を感じたためです。
私は保守的な業界(製造業)での社会人経験が長かったため、「色々な技術に興味を持つ」「失敗してもいいからまずやってみる」「他者にGiveして知識をシェアする」などのWeb業界で重視されるカルチャーに触れる経験がほぼありませんでした。
異業種からWebエンジニアに挑戦する以上、業界のカルチャーに馴染むことは必須だと思い、自分の意識改革のために入学を決断しました。

学習内容は、カリキュラムでネットワークの基礎からRuby on Railsで構築されたサイトの改修、卒業制作としてのWebアプリ開発などを学びました。それ以外にも、受講生主催の勉強会が充実しており、学習方法のLT会や環境構築の勉強会など幅広い知識に触れることができました。


### ポートフォリオ作成(3.5ヶ月)
実施内容：　サービス構想、画面遷移図の作成、テーブル設計、ER図、Issue管理
学習内容：　Reactのキャッチアップ(Udemy講座中心)、技術検証、デモアプリの作成

初めての本格的なWebアプリ開発に着手しました。サービスの構想、画面遷移図、ER図、Issueとスケジューリングまでをスクールの講師の方にレビューしていただきました。個人開発のポートフォリオであると同時に、スクールの卒業制作の位置付けでもあります。

#### 工夫したこと：
##### 1.ディレクトリ構成のベストプラクティスを取り入れてみる
事前に技術検証のためにアプリを作成したのですが、ディレクトリ構成やコンポーネントなど意識しておらず、かなり煩雑なファイル構成となってしまいました。そのため自分でも可読性がかなり悪く、どのファイルが何をしているのか判断に時間がかかっていました。
その点を解消したいと思い、本アプリでは **「Reactベストプラクティスの宝庫」** と言われている[bulletproof-react](https://github.com/alan2207/bulletproof-react)を参考にしてディレクトリやファイルを作成することにしました。
完璧なディレクトリ構成やコンポーネント化には程遠いのですが、コード自体や出来上がる画面以外にも意識を向ける経験ができました。

参考記事：

https://zenn.dev/manalink_dev/articles/bulletproof-react-is-best-architecture

##### 2. ユーザーからのフィードバックを元に改善する
技術検証アプリを受講生中心に多くの方に触っていただき、フィードバックをもらって改善しました。
具体的には説明文やボタンの表示など、わかりにくいところをユーザー目線で洗い出してもらい改善しました。
開発を続けていると感覚が麻痺してきて、「すべてのユーザーが、そのサービスをことを詳しく知っている前提」で画面や機能を作りがちになっていたので、このフィードバックは本当にありがたかったです。

##### 3. 実務を意識してプルリクエストを作成する
プルリクエストは画像や動画を添え、可能な限り情報を厚く書くようにしました。
理由は実務を意識することで、実務とのギャップを少しでも埋めておきたいと考えたためです。

「レビュアーの負担を減らすため、プルリクエストはなるべく情報を厚く書く方がよい」というプログラミングスクール卒業生のアドバイスに従い、実務でレビュアーに説明することを想定して、プルリクエストを作成しました。
(実務未経験なので、実際の現場とは異なっていると思いますがご容赦ください🙇‍♂️)
![pull_request.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/8c651343-2438-d631-bd8f-3c50d9a3a056.png)


# 5. 今後の展望や挑戦したいこと

#### フロントエンドの強化
ReactのフレームワークであるNext.jsの学習をしてみたいです。
表示速度の向上やファイルベースのルーティングの恩恵を味わってみたいので、挑戦してみたいと思います！
また、エラーを早期発見して開発スピードを向上させるため、TypeScriptも学習したいと考えています。

#### 複雑なビジネスロジックやテーブルを扱うサービスを開発する
今回のアプリは、APIの機能(Google MapやYouTube)が前面に出ているので、複雑なビジネスロジックやテーブルの設計を経験できていません。
次回は、自分で組み立てたロジックでユーザーに価値を提供できるようなサービスを開発してみたいです。
スクールの他の受講生のポートフォリオを見ていると、テーブルが20個近くになるサービスもあります。**憧れます！**

#### マネタイズ
自分で開発したサービスで、1円でもマネタイズする経験をしたいと思います。
自分のサービスをビジネス目線で開発することで、ユーザーが課金をしたくなる仕組みの構築など、一段上の開発経験を積めると考えているからです。


# 6. 終わりに
最後までお読みいただきありがとうございました🙇‍♂️
開発においては本当に多くの方に助けていただき、本サービスを完成させることができました。
プログラミングスクール受講生同期の皆さん、講師の皆様、サービス開発者様、参考にした記事の投稿者様、本当にありがとうございました。
Webエンジニアとして転職目指して精進いたします！

Xもやっておりますので、よければフォローをお願いします！

https://x.com/Ito_GeekHatch