React(Next)/Go/GraphQL/Fargateで個人開発したサービス「読み方アンケート」をリリースするまで

**※[追記]読み方アンケートは閉鎖しましたm(__)m多くの反応を頂いているので記事は残しておきます。ありがとうございました。**

個人開発である程度しっかりしたものを作ってリリースまでするってなかなか大変だと思います。

そこには技術的な壁がある人もいれば、なかなか本業が忙しくて時間がとれない人、途中まで開発して**「こんなん誰が使うねん...」**モードになってしまい頓挫する人。

そんないくつかの壁をなんとか乗り越え、
この度晴れて個人開発サービスである[読み方アンケート](https://yomikata-enquete.com/)をリリースできたのでまとめたいと思います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">個人開発サービスリリース🎉<br><br>恥ずかしい読み間違いをこの世から無くすための投票型読み方情報集約サイトです!<br><br>React(Next)/Go/AWS(Fargate)/GraphQLで作成<br><br>「◯◯ 読み方」で検索上位に出るサイトになります💪<br><br>SNS等アカウントの宣伝できるので是非🚀<a href="https://twitter.com/hashtag/%E8%AA%AD%E3%81%BF%E6%96%B9%E3%82%A2%E3%83%B3%E3%82%B1%E3%83%BC%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#読み方アンケート</a> <a href="https://t.co/NFgemOFMM6">https://t.co/NFgemOFMM6</a></p>&mdash; じゃけぇ.tsx@読み方アンケート開発 (@bb_ja_k) <a href="https://twitter.com/bb_ja_k/status/1284291706662252544?ref_src=twsrc%5Etfw">July 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<br />

**〜こんな人に読んで欲しい〜**
・ 個人開発のモチベーションをあげたい人
・ 個人でWebサービスをリリースするまでにするべきことを知りたい人
・ 以下の技術等に興味のある人
　・ React(Next.js)
　・ Go
　・ GraphQL
　・ AWS Fargate
　・ AWS CodePipeline
　・ GitHub Actions
　・ TypeScript
　・ Atomic Design
　・ Recoil
　・ Vercel

# 書くこと(index)
- [サービス概要](#サービス概要)
- [サービス構成](#サービス構成)
- [なぜリリースまで辿り着けたか](#なぜリリースまで辿り着けたか)
- [Webサービスをリリースするまでにすること](#webサービスをリリースするまでにすること)
- [フロントエンド](#フロントエンド)
- [バックエンド](#バックエンド)
- [インフラ-環境周り](#インフラ-環境周り)
- [さいごに](#さいごに)

# サービス概要
サービス名： **読み方アンケート**
URL: [https://yomikata-enquete.com/](https://yomikata-enquete.com/)
![yomikata-ogp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/c9178f4b-578c-ad2a-2ff5-0dc6b27d7d4d.png)

以下のように投票形式で読み方のデータを蓄積することで、世間一般的な読み方を知ることができる読み方情報蓄積サイトです。
<img width="1391" alt="スクリーンショット 2020-07-25 8.43.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/e0f4208e-a447-371b-ec4c-18c0a92d2f92.png">



ITは特にそうですが、専門用語の読み方って人によって違ったり、「え、そんな読み方すんの！？」みたいなのもあってややこしすぎますよね...

**Djangoを「でぃーじゃんご」って読んでて陰で笑われてたあの頃...**

そんな恥ずかしい読み間違いとサヨナラしてもらうために作りました

積極的に使ってくれるユーザーには恩恵があるようにしたいという思いがあったので、１つのミソとしては上で貼った画像のように読み方を聞いた人のプロフィールは単語ページの上部に大きく表示されます。

読み方を調べようとページに訪れた人の目に止まるので、**検索流入によるアカウントの宣伝権利を半永久的に獲得できる**というわけです。

また、以下のように投票した数や、その人のおかげで集まった投票数もカウントしているのでこの数字が大きい人のアカウントも目立つようにするつもりです(リリース予定)
<img width="1033" alt="スクリーンショット 2020-07-22 18.01.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/f8e9de4a-8a4a-1e1b-5cfa-061dbf361285.png">

「シェアして集めた投票数」はログインした状態で各単語ページのシェアボタンからシェアすると、そのリンク経由でページを訪れた人が投票するとカウントアップされていく仕組みです
<img width="1386" alt="スクリーンショット 2020-07-22 18.01.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/87e64fcd-55d8-afb5-42ad-c0ac7adb780d.png">

目指すところとしては
■ このサイトで調べればある程度世間一般的な読み方がすぐ分かる
■ 「◯◯ 読み方」で検索したときに検索結果上位にでるサイトにすること

という感じです。

是非使ってみてくださいm(..)m

# サービス構成
技術的にどのような構成で作られているかを紹介します。

### サービス構成概要
- 開発環境
  - Docker
- フロントエンド 
  - React(Next)、TypeScript
- バックエンド
  - Go
- データベース
  - RDS(PostgreSQL)
- CI
  - GitHub Actions
- CD
  - CodePipeline
- 画像保存
  - S3
- バックエンドデプロイ先
  - ECS(Fargate)
- フロントエンドデプロイ先
  - Vercel

### フロントエンド
Reactで作成しています。

また、今回はSEOが重要だったためSSR(サーバーサイドレンダリング)が可能なフレームワークである[Next.js](https://nextjs.org/)を使用しています。

Nextは目を見張るスピードで進化していて、かなり使いやすいので使ったことない人は是非使ってみてください。

ルーティングの設定が不要ですし、最近(2020年5月)のリリース(ver9.4)で実装されたFast Refleshはかなり開発効率あがります。
コードを変更したときのホットリロードがかなり速く、しかもstateを保持したままリロードされます。

例えばこれまでフォームのテキストボックスとかに値を入力した状態でコード変更すると頑張って入力したのが全部消えていたのが、**それらの情報は保持されたまま修正箇所のみ変更**されます。はい、最高です。

他にも便利な機能目白押しですb
<br />

コンポーネントの設計は**Atomic Design**をベースに行っています。

適切な粒度でコンポーネントを分割することで、開発効率や保守性が高くなります。詳しくは後述します。
<br />
また、APIのやりとりは**GraphQL**で行っています。

TypeScriptとGraphQLの組み合わせはハッキリ言って**フロント開発の世界が変わります**。RESTには戻れなくなります←

これもコードレベルの話は後述します。

### バックエンド

バックエンドにはGoを使用しています。

普段は仕事でフロントエンドの開発をメインにしており、ずっとGoを使って自分で０からバックエンドの構築をしてみたいと思っていたので色々試せて面白かったです。

GraphQLを使用するので型付きの言語が相性が良く、マイクロサービスでサクッとAPIサーバーを立てるのにGoは適しているので今回はうまくハマりました。

DBとのやりとりの部分はGoのORM(オーアールマッパー)ライブラリである[gorm](https://github.com/go-gorm/gorm)を使用しました。

### インフラ

マイクロサービス構築のノウハウが得たいというのもあり、フロントとバックは別々のサーバーにデプロイしようということは決めていました。

AWSをちゃんと自分で触ったことがなかったため、バックエンドはAWSを使って勉強を兼ねることにし、フロントは[Vercel](https://vercel.com/)(旧Zeit Now)にデプロイしています。

Vercelは**フロントのデプロイ先としてめちゃくちゃオススメ**です。詳しくは後述します。

AWSでは主に以下のサービスを利用しています。
・Fargate(ECS)
・RDS(PostgreSQL)
・S3
・ECR
・ALB
・CodePipeline

AWS周りは事前の知識が皆無だったこともありかなり苦労しましたが、今回の開発を通してだいぶレベルアップできたかなと思います。個人開発の醍醐味ですね。

あとは、GitHubにpushした際にテストを実行したりするのにGitHub Actionsを使用しました。途中まではCircleCIを使ってましたが、やはりGitHub内で完結するのは魅力的です。

# なぜリリースまで辿り着けたか
ちょっと技術的な話から離れて、個人開発をリリースまで持っていくためのTips的なものを紹介します。

### モチベーションを明確にする
これは個人開発だけでなく趣味でチーム開発をする時とかでも大事なんですが、

**この開発におけるwhyを明確にする**

ということが大切です。

「開発におけるwhy = モチベーション」と思ってますが、大体は以下のどっちがかなと思います。

**１.アイディアを形にしたい**
　・過程より結果重視
　・使ってもらうことが最優先
　・作る時ワクワク、これ使われないなーと思うと一気にやる気↓↓

**２.開発を通して技術を学びたい**
　・結果より過程重視
　・学習ありきの開発
　・最悪使われなくても良いや

チーム開発の場合、上記のようなメンバーのwhyが揃ってないパターンは大体頓挫します。

どちらが良い悪いではなく、**自分は何故個人開発をやっているのか**を理解して常々選択の軸にすることでブレずにリリースまで持っていける可能性が上がります。

因みに自分は今回の場合、２が70%くらいの比重を占めています。

感覚としてこれ以上2の比重が高くなってしまうとモチベーションを保って開発を続け、リリース日を迎えることがむずかしいです。

### タスクを見える化する

仕事だけでなく個人開発でも**見える化**はめっちゃ大事です。

見える化してないと夜パソコンの前に座ってもどうしてもやる気出てこなかったり、「どこ実装しようかな〜」って考えながら現状でできてるアプリを動かして目についたとこ実装していくみたいな**無駄の多い開発**になります。

そして「あ、こんな機能ありやな〜」て移動中とか思いついたアイディアが忘れ去られたりします...
<br />
具体的には[Trello](https://trello.com/ja)に代表されるようなタスク管理ツールを使います。

自分の場合は[ClickUp](https://clickup.com/onboarding?fp_ref=48cb1&gclid=EAIaIQobChMInOrw6erg6gIVv8EWBR39LQrVEAAYASAAEgKQn_D_BwE)を使用しています。

ClickUpは無料で、プライベートな空間で使用できますし、タスクレーンのカスタムもできたり、Slack通知も簡単に設定できるので仕事でも重宝しています。

以下のようにレーンを分けたりラベルを付けて優先順位やタスクタイプを見える化します。(テンション上がる)(一部都合上隠しています)
<img width="1386" alt="スクリーンショット 2020-07-22 21.18.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/243c7adc-6beb-e883-4a59-f14bd1891c3b.png">


### 「その先」を妄想する

たぶん個人開発者あるあるだと思います←

サービスをリリースした未来を妄想します。

- **サービスが人気になって「◯◯作った人ですよね！」って認識される未来**
- **そこで学んだ技術を生かして仕事で活躍できる未来**
- **そのサービスがきっかけでバイネームで仕事を依頼される未来**
- **大当たりして個人開発で食べていける未来**

冗談のように聞こえますが、個人開発をずっと続けれている人達はこの妄想力が段違いなんじゃないかと思ってます←

必須スキルかもしれません。


# Webサービスをリリースするまでにすること

では個人でWebサービスを開発、リリースするまでどんなことをしなければいけないのか紹介します。

これから開発する方は参考にして頂ければと思います。

（抜け漏れある気がするのでコメントで補足してもらえると助かりますm(..)m）

*※ * がついている項目は必須*

### システム構成を考える*
まずは当たり前ですが構成を考えます。

- フロント、バックに何を使うか
- DBは使うのか、使う場合はRDBにするのかNoSQLにするのか等
- デプロイ先はどこにするのか

### ワイヤーフレームを作成する

これは必須ではありませんが、サイトの設計書とも呼ばれるワイヤーフレームを考えた方が開発はスムーズに進みます。

手書きでざっくりでも良いですし、得意な人はXDやFigmaを使って作成しても良いでしょう。

因みに自分は今回は何にも作らなかったです←

なんか個人開発くらい場当たり的に画面作ってみたかったのです...

### DB設計をする*

データベースを使用する場合はDB設計は必須です。

**これは場当たり的にはやってはいけません**

DB設計はどうしても数をこなさないと上手くできないと思いますが、考えることを諦めてはいけません。

実装したい機能からどんなテーブルが必要なのか、将来機能追加したときに破綻しないか等々考慮してテーブルや項目を洗い出していきましょう。

### 開発する*

ここまでで開発は進めれる状態になったのでつらつらと開発しましょう。

頑張りましょう。

頑張りましょう。。。

### デプロイ先を考える*

世に公開するためにはどこかのサーバーに作成したアプリをデプロイしなければいけません。

使用している技術やCI/CDとの相性、ランニングコスト等比較して早い段階で決めておきましょう。

### CI/CD環境の整備をする

継続して安定的なサービスを提供し続けるためには今やCI/CD環境は必須と言えます。

GitHub Actions、CircleCI、CodePipeline等々選択し、実装していきましょう。

### 404や500ページのことも考える

意外と盲点なのが存在しないページが開かれた場合の404ページと、サーバーエラーが発生した場合の500ページです。

一般的なサービスは大体このあたりも綺麗に作成されています。

因みにNextの場合、`/pages/`以下に`404.tsx`、`_error.tsx`のようにファイルを作成しておくだけでカスタムできるので最高です。

参考までに読み方アンケートは以下のようにしています。
(500ページにTwitterのタイムラインを載せるTipsはnoteから学びました。サーバートラブルがあってもユーザーに状況を伝えることができます)
<img width="1386" alt="スクリーンショット 2020-07-22 22.32.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/bc3b19d6-3054-ec35-8d11-cf0bd200264f.png">
<img width="1386" alt="スクリーンショット 2020-07-22 22.34.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/6fed79ca-0cea-e142-580f-67bc6e0ef66e.png">


### meta,titleタグを整備する*

Webサービスの場合、meta,titleタグの設定は必須です。

検索エンジンやブラウザに伝える情報を記述します。

これらはHTMLのheadタグの中に記述するもので、titleタグはページのタイトル情報でブラウザのタブに表示されるものがそうです。

metaタグは色々な種類があり、SNSにURLをシェアした際の画像や文章を設定するOGPの設定や、ページの説明文などを記述していきます。

### faviconやtouch-iconを作成する*

faviconは以下のようなブラウザのタブ等に表示される画像です。間違ってもデフォルトのままリリースしないようにしましょう。
<img width="353" alt="スクリーンショット 2020-07-24 14.01.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/820b093a-04a6-d48d-e289-a03b6d553707.png">

apple-touch-iconはスマホやiPadでホーム画面に追加された時の画像を設定します。

faviconに比べ優先度は低いですが、設定しておくにこしたことはありません。(PWA化する場合は必ず設定しておきましょう)

以下のように180×180サイズを設定しておけば大丈夫(のはず)です。

```
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
```

### 各ブラウザ、端末での動作を確認する*

一通りシステムが形になってきたら各ブラウザや、スマホ等でレイアウト崩れが起きていないか、機能が正常に動くかを確認しましょう。

PCでスマホのレイアウトを確認する場合、各ブラウザのDeveloper Tool等を使うと思いますが、実機で見たらレイアウトが異なることがあるのでちゃんと実機で見てみることが大事です。

IEは、、、個人開発であれば無視しましょう←

### 外形監視を導入する

これは最初からやる必要はないと思いますが、個人開発でやってみておくと良い経験になるし仕事に生かせると思います。

[Sentry](https://sentry.io/welcome/)に代表される外形監視ツールは、ユーザーが操作している際フロントエンドで何かエラーが起きたときにSlack等に通知をしてくれるものです。

フロントエンドのエラーはユーザーの使い勝手に直結するので、知らない間にエラーが起きていてユーザーが離れていくということを避けられます。

余裕があれば導入してみましょう。(個人開発レベルであれば無料で使えます)

### ドメインを取得する*

`https://yomikata-enquete.com/`の`yomikata-enquete.com`の部分です。

ドメインの取得は必須です。年間で数百円とかなので惜しまずに買いましょう。

色んなサービス経由で買えますが、私は[お名前ドットコム](https://www.onamae.com/)で買っています。

どこでも対して差はないので大丈夫です。

### Google Analyticsへの登録

[Google Analytics](https://marketingplatform.google.com/intl/ja/about/analytics/)は必須ではないですが、絶対設定しておいたほうが良いです。

ユーザーが今何人サイトのどのページを見ているかリアルタイムで見れたり、日や月単位で何人に訪問されたのか、直帰率はどのくらいか等々分析することができます。

リリース情報を公開したあとなんかはずっとリアルタイムの数字見てワクワクできます。そりゃあもうビール３杯くらいそれでいけます。

### Google Search Consoleへの登録

Google Analyticsがユーザーの分析なら、[Search Console](https://search.google.com/search-console/about?hl=ja)は検索エンジンの分析です。

どんな検索ワードでサイトが訪問されたのか、googleにindex(検索結果にでるように認識されていること)されているか、されていない場合はリクエストしたり等々

検索流入に対する対策をたてるのに使用できます。GAと並んでとても重要です。どちらも無料で使用できるので導入しておきましょう。

<br />
単に開発するだけでなく、上記のことを乗り越えて初めてリリースを迎えることができます。

頑張りましょう！b

# フロントエンド

ではここからは実装レベルでの細かいTips等を紹介します。

ざっくりとの紹介になるので、気になる部分がある人は質問等で聞いてもらえたらと思いますm(..)m

フロントエンドでは以下のライブラリを使用しています(一部)

### ■ React、Next.js、TypeScript
- https://github.com/facebook/react
- https://github.com/vercel/next.js
- https://github.com/microsoft/TypeScript

このセットはかなりDX(Developer Experience)が向上します。

VueとReactを比較した記事も書いていてけっこう読んで頂いているので参考にしてみてください。

[あらためてReactとVueを比較してみる〔2020年最新版〕](https://freelance-jak.com/technology/react/2472/)

### ■ eslint、prettier
- https://github.com/eslint/eslint
- https://github.com/prettier/prettier

コード自動整形や静的解析のために使用。

ESLintとPrettierを連携してVSCodeで保存時に自動で整形されるための設定は以下で紹介しています。(GitHubのリポジトリもあります)

[良い感じのReact開発をすぐに始めれるテンプレートプロジェクトを作ったので共有します](https://freelance-jak.com/technology/react/2508/)

### ■ GraphQL
- https://graphql.org/
GraphQLはFacebookが開発したRESTに代わる新しいAPIの規格です。
schema(スキーマ)と呼ばれるAPIの設定ファイルを基盤にAPIを作成していくことから**スキーマ駆動開発**と呼ばれる開発フローが可能になります。

- https://www.apollographql.com/
ApolloはGraphQLを使うための様々な便利な機能を提供しているライブラリで、クライアントもサーバーもサポートしています。キャッシュができたり、reactの場合、hooksライクにAPI実行できたりするので非常に便利です。以下の`graphql-codegen`と組み合わせることでschema作成→API呼び出しが超簡単になります。

- https://github.com/dotansimha/graphql-code-generator
schema情報から、API実行するための口や型情報を自動生成してくれるためのライブラリです。
以下に簡単なサンプルを紹介します。

**1.schemaを定義**
以下はIDから１つの単語を取得するクエリ定義の例です。

```graphql 
# queryはデータ取得。その他mutationやsubscription
schema {
  query: Query
}

# データ取得はQueryに定義する、引数や返却型を定義
type Query {
  word(wordID: Int!): Word!
}

# 型情報
type Word {
  wordId: Int!
  title: String!
}

```

<br />
**2.クエリを定義する**

schemaを基に取得するためのクエリを定義します。
RESTのようにデータを全て受け取るのではなく、ここでフロントが必要なデータのみ指定できるのもGraphQLの強みです。

```graphql:word.graphql 
query word($wordID: Int!) {
  word(wordID: $wordID) {
    wordId
    title
  }
}
```

<br />
**3.自動生成する**
以下のコマンドを実行するとschema情報を基にファイルが自動生成されます。(別途設定ファイルの記載は必要。package.jsonのscriptに定義すると楽)

```shell
graphql-codegen --config codegen.yml
```

<br />
**4.生成されたファイル**

以下のようなファイルが自動生成されます。

`type Word`の型情報や、`useWordQuery`などのAPI実行用の口ができていることが確認できます。

```tsx:graphqlClientApi.tsx 
import gql from 'graphql-tag';
import * as ApolloReactCommon from '@apollo/react-common';
import * as ApolloReactHooks from '@apollo/react-hooks';
export type Maybe<T> = T | null;
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

/** データ取得はQueryに定義する、引数や返却型を定義 */
export type Query = {
  __typename?: 'Query';
  word: Word;
};

/** データ取得はQueryに定義する、引数や返却型を定義 */
export type QueryWordArgs = {
  wordID: Scalars['Int'];
};

/** 型情報 */
export type Word = {
  __typename?: 'Word';
  wordId: Scalars['Int'];
  title: Scalars['String'];
};

export type WordQueryVariables = {
  wordID: Scalars['Int'];
};

export type WordQuery = { __typename?: 'Query' } & { word: { __typename?: 'Word' } & Pick<Word, 'wordId' | 'title'> };

export const WordDocument = gql`
  query word($wordID: Int!) {
    word(wordID: $wordID) {
      wordId
      title
    }
  }
`;

/**
 * __useWordQuery__
 *
 * To run a query within a React component, call `useWordQuery` and pass it any options that fit your needs.
 * When your component renders, `useWordQuery` returns an object from Apollo Client that contains loading, error, and data properties
 * you can use to render your UI.
 *
 * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
 *
 * @example
 * const { data, loading, error } = useWordQuery({
 *   variables: {
 *      wordID: // value for 'wordID'
 *   },
 * });
 */
export function useWordQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<WordQuery, WordQueryVariables>) {
  return ApolloReactHooks.useQuery<WordQuery, WordQueryVariables>(WordDocument, baseOptions);
}
export function useWordLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<WordQuery, WordQueryVariables>) {
  return ApolloReactHooks.useLazyQuery<WordQuery, WordQueryVariables>(WordDocument, baseOptions);
}
export type WordQueryHookResult = ReturnType<typeof useWordQuery>;
export type WordLazyQueryHookResult = ReturnType<typeof useWordLazyQuery>;
export type WordQueryResult = ApolloReactCommon.QueryResult<WordQuery, WordQueryVariables>;
```

<br />
**5.APIを実行する**

上記で作成したAPIから取得したデータを表示したい場合、以下のようにするだけです！
**型情報を別途定義する必要もなければ、error情報やloadingの情報も含まれて**います。
これがめっっっっっちゃ楽です。
![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/279c214c-ef9f-4482-672b-3682c06ec916.gif)


### ■ Atomic Design
Atomic DesignはアメリカのWebデザイナーBrad Frost氏が考案・提唱したデザインシステムです。

細かい説明は色々なサイトで紹介されているので省きますが、自分がフロント構築する場合はAtomic Designベースでやります。

「ベースで」というのが大事で、自分の中でコンポーネント分割はあくまで概念であって、厳密なルールを強制するものではないと思っています。

なので、ベースはありつつもプロジェクト毎にメンバーで話し合って適宜カスタムしていって良いと思います。

<br />
コンポーネント分割というと「再利用」というメリットがフォーカスされがちですが、TypeScriptと組み合わせることで**実装に制約を注入できる**というのも大きいです。

例えば以下のようにloadingというpropsを必須のpropsとして定義しておくことでボタンを配置するときに押下時のloadingを設定しないとエラーになるので実装者にルールを意識してもらえます。

```tsx:MainButton.tsx
import React, { ReactNode } from 'react';
import { Button } from 'semantic-ui-react';

type Props = {
  children: ReactNode;
  loading: boolean;
  onClick: () => void;
};

export const MainButton = (props: Props) => {
  const { children, loading, onClick } = props;
  return (
    <Button loading={loading} disabled={loading} onClick={onClick}>
      {children}
    </Button>
  );
};
```


loadingを設定しないとエラーになる。
<img width="818" alt="スクリーンショット 2020-07-24 16.12.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/bfd54b76-db8c-a3ba-5544-c705bca061f2.png">

### ■ Semantic UI React
- https://github.com/Semantic-Org/Semantic-UI-React

CSSライブラリとしてSemantic UI Reactを使用しています。

BootstrapやMaterial UIだと人と被るしな〜と思っている人にSemantic UI Reactはオススメです。

サンプルの例が丁寧ですし、色の選択も豊富です。もちろんレスポンジブやGrid系の仕組みも提供されていますし、読み方アンケートのTOPページで実装しているようなアニメーションも簡単に実装できます。

### ■ styled-components
- https://github.com/styled-components/styled-components

ReactではCSSのあてかたに様々なパターンがあり、宗教戦争がおきがちです←

自分はstyled-components(以下SC)を好んで使います。

CSS-in-JSの中でもSCを使用している理由はscssライクに使えるのでもし方針の変更があってもscss→SC、SC→scssといった変換が容易というのと、hoverなどの擬似要素やメディアクエリも同様に使えるところが大きいです。

以下は読み方アンケートで使用している、リンクテキスト用のコンポーネントの例です。

```tsx:LinkText.tsx
import React, { ReactNode } from 'react';
import styled from 'styled-components';

import { COLOR } from 'util/const';

type Props = {
  children: ReactNode;
  onClick: () => void;
};

export const LinkText = (props: Props) => {
  const { onClick } = props;
  return <SLink onClick={onClick}>{props.children}</SLink>;
};

const SLink = styled.p`
  color: ${COLOR.LINK};
  cursor: pointer;
  margin: 0;
  &:hover {
    text-decoration: underline;
    color: ${COLOR.LINK_HOVER};
  }
`;
```

scssの書き方がそのまま使用できるのでhover時のスタイル変更もjs内で簡単に適用できます。

問題としてあげられるのが、SCを使うと外部ライブラリから読み込んで使用しているコンポーネントか、SCのコンポーネントかパっと見で分かりづらいので、自分は`S`プレフィックスを付けるルールをよく使います。

### ■ react-spinners
- https://github.com/davidhu2000/react-spinners
ローディングのインジケーターに使用しています。

ローディングをちょっと工夫したい人は是非。
読み方アンケートだと以下のローディングがそうです。
![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/fda1f8cc-24e0-6a05-1d3f-0002a3119db4.gif)

### ■ Recoil
- https://github.com/facebookexperimental/Recoil  
状態管理としてRecoilを使ってみました。少し前に公開されて話題になったやつです。

上記のローディングを表示する箇所に使ってみています。

以下のような状態用atomを定義して

```ts:loadingState.ts
import { atom } from 'recoil';

export const loadingState = atom({
  key: 'loadingState',
  default: false,
});
```

trueの場合、黒い背景(Dimmer)上にローディングアイコンが表示されるようにコンポーネントをセットしておきます。

あとは下記のように任意の場所でstateを設定することでグローバルな状態管理が可能になります。

```tsx 
import React from 'react';
import { Button } from 'semantic-ui-react';
import { useSetRecoilState } from 'recoil';

import { loadingState } from 'store/recoil/loadingState';

export const UserPublish = () => {
  const setRecoilLoading = useSetRecoilState(loadingState);

  const onClickButton = () => {
    setRecoilLoading(true);
  };

  return <Button onClick={onClickButton}>ボタン</Button>;
};
```

まだ複雑な状態管理は試してないですが、かなり可能性を感じます。


### ■ react-alert
- https://github.com/schiehll/react-alert  
メッセージ表示のライブラリとして使用しています。

hooksライクに使えるので重宝しています。

なんでこんなにstarが少ないんだろう..


# バックエンド
### ■ Go
- https://github.com/golang/go  
今更説明は不要かと思います。

今回の規模のサービスでは特に困ることはありませんでした。ビルドが早いのは良いですね。

### ■ gorm
- https://github.com/go-gorm/gorm  
ORMライブラリとしてgormを使用しています。goのORMでは１番シェアが大きいのではないかと思います。

DBとのやりとりがシンプルになりますし、素のSQLも簡単に実行できるので助かりました。


### ■ GraphQL
- https://github.com/99designs/gqlgen  
GoでGraphQLを扱うためのライブラリとしてgqlgenを使用しています。
フロントエンドと同様、shemaファイルを基に型情報やresolverの情報を自動生成できるので重宝します。

また、[GraphQL Playground](https://github.com/prisma-labs/graphql-playground)が含まれているので、バックエンドだけ実装した後GUI上で簡単にAPIを実行した結果を確認できるのでわざわざAPI実行のために別のツールを導入する必要がなくなります。

### ■ jwt-go
- https://github.com/dgrijalva/jwt-go  
認証にJWTを使用しているので使用しています。

一般的なJWT系のライブラリと同じ感じで使えます。

### ■ go-chi
- https://github.com/go-chi/chi  
ルーティングに使用。

### ■ CORS
- https://github.com/rs/cors  
CORSの設定に使用。何もしないと別ドメインからのリクエストはエラーになるのでマイクロサービスの場合は設定必須。


# インフラ-環境周り

読み方アンケートで設定しているインフラや環境周りを紹介します。

### ■ Docker
開発環境はDockerで構築しています。

nginxを含めてリバースプロキシすることで`http://localhost:3000/`ではなく、`http://localhost/`でアクセスできるようにしています。(色んなプロジェクトで3000使うので不便なんですよね...)

以下は読み方アンケートのdocker-composeファイルです。

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres:11-alpine
    volumes:
      - db:/var/lib/postgresql/data
      - ./docker/init:/docker-entrypoint-initdb.d
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - "5434:5432"
    container_name: yomikata-postgres

  nginx:
    image: nginx:stable
    container_name: nginx
    ports:
      - '80:80'
    volumes:
      - ./conf.d:/etc/nginx/conf.d
    links:
      - front

  front:
    build:
      context: .
      dockerfile: ./docker/front/Dockerfile
    container_name: yomikata-front
    hostname: front
    volumes:
      - .:/yomikata-enquete:cached
      - node_modules:/yomikata-enquete/node_modules:cached
    ports:
      - '3001:3000'

  api:
    build:
      context: .
      dockerfile: ./docker/api/Dockerfile
    environment:
      DB_INFO: host=db port=5432 user=postgres dbname=postgres password=postgres sslmode=disable
    ports:
      - "8081:8081"
    container_name: yomikata-api
    tty: true
    volumes:
      - .:/usr/src/app
    command: go run ./server/cmd/server.go
    depends_on:
      - db

volumes:
  db:
    driver: local
  node_modules:
    driver: local
```


### ■ AWS Fargate

バックエンドはFargateで構築しました。

初めてだったのでまぁまぁ大変でした...

手順もまとめているのですが、ここに書くと長くなるので別途記事にしようと思います。

### ■ AWS CodePipeline
CDのためにCodePipelineを使用しています。

GitHubの`production`ブランチへのpushに反応して動き、ビルドやデプロイを自動でしてくれます。

また、Slackへの通知も簡単に設定できます。

読み方アンケートでは以下のように開始と終了の通知をSlackに送るようにしています。
<img width="652" alt="スクリーンショット 2020-07-24 18.25.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/943d2b52-29cb-5854-e386-8250686fb6ce.png">


### GitHub Actions
各ブランチをGitHubにプッシュした際にテストを実行するためにGitHub Actionsを使用しています。

`/.github/workflows/`にymlで設定ファイルを記述します。

読み方アンケートでフロントのテストを実行する場合は以下のようなファイルを定義しています。

```yml:front_test.yml
name: front_test

on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup NodeJs
        uses: actions/setup-node@v1
        with:
          node-version: '10.x'
      - name: Cache dependencies
        uses: actions/cache@v1
        with:
          path: ~/node_modules
          key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-node-
      - name: Install Dependencies
        run: yarn install --frozen-lockfile
      - name: Run test
        run: yarn test
```

プルリクエストには以下のように表示されます。
<img width="920" alt="スクリーンショット 2020-07-24 18.42.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/a4d3cba8-1aea-8361-aaa2-4cb9de06e97b.png">


ちなみにGitHub Actionsの勉強で買った以下の本は読みやすくて良かったです。
[GitHub Actions 実践入門](https://www.amazon.co.jp/GitHub-Actions-%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E6%8A%80%E8%A1%93%E3%81%AE%E6%B3%89%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88NextPublishing%EF%BC%89-%E5%AE%AE%E7%94%B0-ebook/dp/B08B1873L5/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=github+actions+%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80&qid=1595583569&sr=8-1)
![9784844378716.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/3e614079-13a4-79dc-9fcb-4015de9324dd.jpeg)


### Vercel

フロントのデプロイ先には[Vercel](https://vercel.com/)(旧Zeit Now)を使用しています。

GUI上でGitHubのリポジトリとの連携設定を簡単にできて、ブランチをpushする度に各ブランチに対応したPreview用のURLを生成してくれるのでチーム開発では力を発揮します。
(わざわざブランチをpullしてきてローカルで実行して確認しなくて良い)

- 以下のように自動でVercelがコメントしてくれる
<img width="928" alt="スクリーンショット 2020-07-24 23.56.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351043/5e731eb8-12d9-196e-e1d5-0f827d48f3e1.png">

Next.jsを開発している会社と同じなのでNextのデプロイもめちゃくちゃ簡単ですし、ReactやVueのデプロイもほぼ0configで可能です。

SSL化もデフォルトでされており、別途証明書を発行する手間もありませんし、お名前ドットコムなど外部で取得したドメインを設定するのも簡単にできます。

気になるお値段ですが、

<br />

なんと個人利用の場合**無制限で無料**です

<br />

いや、太っ腹かよ(　ﾟдﾟ)

ぜひ使ってみてください。

# さいごに

個人開発、大変ではありますがやはり**実際のプロダクトを作ることで得られる経験というのは本を読んだりUdemyで勉強するのとは段違い**だと思います。

仕事と違って誰にも合わせる必要なく自分の思うがままに進めれるのも良いですしね←

ちなみに次は React × AWS Amplify で何か作ってみるつもりです。

<br />

読み方アンケートや使用している技術に関して質問があればこの記事にコメントしていただくか、[私のTwitter](https://twitter.com/bb_ja_k)にDMでもかまわないのでお待ちしています。

個人開発がんばりたい人、個人開発の先駆者の方、フォローお待ちしております。お互い頑張りましょうb