ライフラインチャート作成サービスを開発した話

ライフラインチャートを作成、公開できる「LifeLog」というサービスをコラボで開発しました。

個人サービスを開発、運営したいと思っていたのですが、エンジニアだけで開発することに限界を感じていて、たまたま機会があり他の役割の方とコラボという形で開発をすることになりました。
「企画、マーケティング」「ディレクション、デザイン」「エンジニア」(私)という役割分担で三人でサービス開発にあたりました。

【サービスでできること】
①登録→ログイン
②生まれてから今に至るまでの主要な出来事/年齢/幸福度（-100~100）を入力
③全部入力を終えたら「作成する」ボタンを押す
④ライフラインチャート（グラフ）の完成

リリースについては、まずプレリリースをしてユーザーのフィードバックを得て必要な機能を実装して正式リリースを行うという形で進めました。
プレリリース後のフィードバックで、企業採用の選考で使いたいという要望を頂き、「**ユーザー登録をtwitterログインのみではなく、メールアドレス登録からのログインも出来るようにする**」「**デザインの都合上ターニングポイント詳細の最大文字数が100文字だったため、デザインを変更し詳細の最大文字数を1000文字とする**」の二点の変更を行い、正式リリースをしました。

当初は、ライフラインチャートという話で開発を進めていましたが、キャリアでの出来事をポートフォリオ的にまとめる用途でも使われたらなと思っています。
Wantedlyなどに記載した職務経歴書などのURLをプロフィールに設定するとグラフ上部に「詳細を見る」ボタンが表示され、そこから登録したURLに遷移する機能も追加しています。


[LIFE LOGの開発の経緯についてはこちら](https://note.mu/soutaros/n/n4eca63d031d0)

# 作ったサービス
[LIFE LOG - スマホで簡単に人生曲線が作れるツール](https://www.lifelog.site/)

### トップ画面
<img width="400" alt="スクリーンショット 2019-06-16 1.02.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/54bb2a18-b28d-553b-ebee-6c7b62377b75.png">

### 人生曲線入力画面
<img width="400" alt="スクリーンショット 2019-06-16 19.40.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/8ca89691-d8a1-f1f2-d7b0-a9e9e2bb36c2.png">

### 人生曲線のグラフ
＊クリックすると詳細が表示されるようになっています
<img width="400" alt="graph" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/be73c013-eddd-83f8-9780-26611718dfbb.gif">

# 使用した技術
- **Ruby on Rails**...サーバーサイド
- **Vue.js**... フロントエンド(入力フォーム)
  - React.jsも検討しましたが、フォーム周りは動きはシンプルなので、テンプレート構文で記述ができ実装コストが低いVue.jsを使いました。
- **React.js**...フロントエンド(グラフ描画)  
  - ライブラリを選定したところ、React.jsベースで記述できる[Rechart](http://recharts.org/en-US/)というライブラリを使って実装することなったため、React.jsを利用しました。
- **jQuery**...フロントエンド
  - ローディングなどのフロントエンドの軽い動作で利用しています。
- **html2canvas、carrierwave**
  - グラフ画像をSNS(twitter、facebook)シェアする部分で画像を[html2canvas](https://html2canvas.hertzen.com/)でスクリーンショットを取得し、base64形式でAPIに送信し、サーバー側で受け取ってファイルをアップロードしています。
- **PostgreSQL**
  - HerokuのPostgreSQLの無料プランが10,000レコードまで使えること（MySQLだと5Mまでしか使えない）から利用しました。
- **Heroku**...サーバー
- **Google Cloud Storage**...グラフイメージ配信
- **SendGrid**...メール配信

# **サーバーサイド**
サーバサイドはRuby on Railsを利用しています。
レンダリングは基本的にはサーバサイドで行っていますが、入力フォーム処理やグラフ描画処理はフロントエンドでレンダリングしています。
フロントエンドでレンダリングしている処理のAPIも提供しています。

# **DB**
PostgreSQLを利用しています。

Herokuで利用する場合は、MySQLと比較検討し、無料で利用する場合はMySQLだと5MBまでに対してPostgreSQLだと10,000レコードまで（全テーブルのレコード合計）利用可能です。

テーブル構成については、初めは複数テーブルで考えていましたが、PostgreSQLの無料枠がレコード数で制限がかかることやサービス要件的にRDB的な機能が不要なことから、１テーブル（Usersテーブルのみ）の構成としました。
人生曲線のターニングポイントは1Userに対して複数レコードを持ちますが、Userレコードのlife_logカラムに複数レコード分のデータをJSON形式で持つようにし1テーブルのみの構成としました。

# フロントエンド
ターニングポイント入力フォーム部分はVue.js、人生曲線グラフ描画部分はReact.jsを利用しています。
フォーム周りは動きがシンプルなので、テンプレート構文で記述ができ実装コストが低いVue.jsを利用することになりました。

グラフ描画部分は、React.jsベースで記述できる[Rechart](http://recharts.org/en-US/)というライブラリを使って実装することなったため、React.jsを利用しました。
振り返ってみると、React.jsで統一するべきかと思いますが、諸々の事情があり、入力部分を先に着手することとなりwebpackerを使ってプロジェクトのフロントエンドをVue.jsベースで作っていました。

Vue.jsベースで作られたプロジェクトにReact.jsを入れたかったのですが混在させることができず、グラフ部分を別のnodeプロジェクトとして作成し、そのプロジェクトをビルドしたものを既存のRailsプロジェクトに配置する構成としました。

### ターニングポイント入力部分(Vue.js)
Vue.jsを使ってフロントエンドで入力フォームをレンダリングし、サーバサイドの処理はAPIを通して行っています。

フォーム部分のコンポーネント構成はLifeLogEditコンポーネントの配下に色選択部分（ColorSelect）、現在の年齢・幸福度入力部分（CurrentLileLog）、ターニングポイント入力部分（TurningPointLileLog）の各々のコンポーネントを配置する構成になっています。

親コンポーネントのLifeLogEditコンポーネントでAPIと通信し、propsを通じて各々の子コンポーネントに初期状態を渡しています。フォームの状態については各々の子コンポーネントで持つようになっています。submitボタンが押されたときに親コンポーネントのLifeLogEditコンポーネント内のメソッドが発火し、メソッドの処理で[$refs](https://jp.vuejs.org/v2/api/index.html#vm-refs)を使って子コンポーネントの状態（フォームの状態）を取得し、APIと通信するようになっています。

**コンポーネント構成**
<img width="400" alt="スクリーンショット 2019-06-16 18.51.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/3bca74c3-c2b8-1f7c-484c-a427c966344a.png">

**LifeLogEditコンポーネントのコード**
<img width="498" alt="スクリーンショット 2019-06-16 20.18.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/d901235d-3438-69d0-5355-1a3da91ccd87.png">



### ライフラインチャートグラフ描画部分(React.js)
グラフ部分は[Recharts](http://recharts.org/en-US/)というReactのライブラリを使っています。RechartsはReactのコンポーネントベースで記述することができ、カスタマイズがしやすいライブラリです。

標準コンポーネントに渡すpropsを調整することでカスタマイズすることができます。propsには数値を渡して位置やサイズなどを調整したり、独自にコンポーネントを定義することでライブラリで描画するグラフの一部分を独自に記述して表現することができます。

LifeLogだと、ターニングポイントをクリックしたときに詳細画面が開く部分はTooltipというコンポーネントを使っているのですが、このコンポーネントのpropsのcontentに独自のコンポーネントを渡すことで詳細画面(クリックしたときに開かれる部分)を独自に記述しています。
他には、グラフのドット部分（ターニングポイント部分）やラベル部分を独自のコンポーネントを使って記述しています。

**グラフ部分のコード**
<img width="710" alt="スクリーンショット 2019-06-17 21.03.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30728/1753c94e-bdb0-7923-41c4-80145e39ef27.png">

# ライフラインチャートをSNSシェア
フロントエンドでグラフ画像をSNS(twitter、facebook)シェアする部分はグラフ部分のスクリーンショットを[html2canvas](https://html2canvas.hertzen.com/)で取得し、base64形式でAPIに送信しています。サーバーサイドでフロントエンドから送られたデータを受け取り、[carrierwave](https://github.com/carrierwaveuploader/carrierwave)を使ってGoogle Cloud Storageのバケット上に画像ファイルをアップロードしています。

# 最後に
サーバーサイド言語はずっとJavaを使っていて、フリーランスになったこともありRuby on Railsに転向したいという動機からこのサービス開発を始めました。幸いにも、サービス開発を開始してすぐにRuby on Railsの案件に参画することができました。

実務に参画して思うのは、当たり前のことなのですが個人開発を進めるよりも実務に参画する方がスキルアップの度合いが圧倒的に大きいということです。個人だとレビューを受ける機会もなく、テストコードやコードレベルが甘くなりがちです。また、割ける時間も少ないです。
サービス開発になると単調な作業もたくさんやらないといけないので、スキルアップという意味では非効率かと思います。

今後、新たな技術を習得する場合は、開発するものをプロトタイプレベルにとどめて実務でスキルアップをしていきたいと思います。
実務ではサーバサイド、フロントエンドの開発がメインなので、今後はインフラまわりのスキルを習得したいと思っています。また、Ruby on Railsは、とあるOSSに参加することになったので、そちらの方でスキルアップに繋がったり技術的に興味が持てるISSUEをやりながら、スキルアップを図りたいと思っています。

「LifeLog」について、今後は新規機能の追加などの予定はありませんが、より多くに人に使われるサービスにしていきたいと思います。
また、個人サービスにありがちなリリースしても少したつとクローズすることがないように継続的に運営をしていきたいと思っております。