Nuxt × Go × AWS で比較コミュニケーション的な掲示板サービス作ってみた

比較コミュニケーションサイト Versus
~~https://versus-web.net~~(停止中)

![FireShot Capture 075 - 比較コミュニケーションサイト『Versus（バーサス）』 - versus-web.net.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379449/1ee33604-7c8c-fd80-e979-1ab4b7a8c396.png)

![FireShot Capture 076 - 比較コミュニケーションサイト『Versus（バーサス）』 - versus-web.net.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379449/b9035a66-65f6-46c0-4c70-b6b9bfce023b.png)

~~Twitter で技術マウント合戦している人たちが面白かったので~~
AWS と Go の勉強がてら、テーマを持ち寄ってコミュニケーションできる簡単な掲示板サイトを作ってみたので作業工程など記録してみる。

## 構成
### インフラ
+ ECS
+ Lambda
+ DynamoDB
+ API Gateway
+ Route 53

### バックエンド
+ Go

### フロントエンド
+ Nuxt (SSR)

Go と Fargate 辺りを使ってみたかったのでこんな構成になりました。

## 作業工程
### タスク管理
タスク管理ツールとして Trello を使用した。
<img width="1434" alt="スクリーンショット 2020-02-23 17.21.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379449/6cb895ae-77fc-0a1b-72b4-1431fb6a954f.png">
こんな感じに5カラムで管理してみた。
Doc としてドキュメント管理にも使用してみたが、シンプルでサクサク動くし、個人開発規模ならすごく使いやすいと思った。

### デザイン
Figma を使用。
![FireShot Capture 066 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379449/d6b3d670-bc0d-ac35-5519-a4e5fddd7ff4.png)
こんな感じに遷移図作ったり
![FireShot Capture 065 - Untitled – Figma - www.figma.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379449/7b048c82-27c1-0bc9-00cb-bd900828d5fa.png)
色管理もしつつ、わりとしっかりめに使ってみたつもり（デザイナーの方からするとまだまだだろう）
このくらいやっておくと開発時だいぶ楽。

### 開発
#### Go
Lambda で採用。ディレクトリ構成は以下の通り。

```sh
.
├── posts-function
│   └── posts
│       ├── bin
│       ├── cmd
│       └── internal
│           ├── actions
│           ├── handler
│           ├── models
│           └── repositories
└── threads-function
    └── threads
        ├── bin
        ├── cmd
        └── internal
            ├── actions
            ├── handler
            ├── models
            └── repositories
                └── mock
```

AWS SAM を使用することで、コマンドで Go の Lambda 関数を作成することができる。
ディレクトリ構成は [golang-standards](https://github.com/golang-standards/project-layout) を参考にした。
どの粒度で Lambda 関数を作成するか迷ったが、リソース単位で分割することにし、以下のようにハンドリングしてみた。

```go:handler.go
package handler

import (
	"context"

	"posts/internal/actions"

	"github.com/aws/aws-lambda-go/events"
)

var routes = map[string]actions.ActionFactory{
	"GET":  actions.NewPostsGetter,
	"POST": actions.NewPostsPoster,
}

// CORS compatible
var headers = map[string]string{
	"Content-Type":                "application/json",
	"Access-Control-Allow-Origin": "*",
}

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	factory := routes[request.HTTPMethod]
	action := factory()
	jsonData, err := action.Run(request)
	if err != nil {
		return events.APIGatewayProxyResponse{}, err
	}

	return events.APIGatewayProxyResponse{
		Body:       string(jsonData),
		StatusCode: 200,
		Headers:    headers,
	}, nil
}

```
HTTP メソッドで振り分けるだけなのでルーティングは楽。関数を分ければ当然デプロイも分けられるので、この辺の粒度は規模を見つつといった感じになりそう。（ちなみに他プロジェクトではマイクロサービス粒度で分けていた）

#### Nuxt
フロントエンドで採用。
基本的に初期表示速度的な意味で SSR をすべきと思っているので今回も SSR を採用。
難しいことをしていないのであまり特筆する点がないのだが
バリデーションに [vuelidate](https://vuelidate.js.org/) を使用してみてとても使いやすかったのでおすすめしたい。
人気の [VeeValidate](https://logaretm.github.io/vee-validate/) と比較すると、vuelidate はテンプレートとアプリケーションロジックが分離しているので、バリデーション時の処理を細く設定したい要件があるときに使いやすい。

## 所感
AWS と Go がほぼ初見だったためだいぶ苦労した。
Node なら Lambda 上のコードを AWS コンソールから見れるため、とっつきやすさもあるが、Go の場合それができず、デプロイ周りを整えるまで一苦労だった。
新しく何かを作るときは未知の技術は１種類にすべき、みたいな話をどっかで聞いたけどその通りだと思った。
しかし今回の技術スタックはだいぶ耳にすることも多くなってきたので、試してみるのは一興だと思う。