はじめに
概要
インフラエンジニアだった私が、開発の勉強をするためにクイズアプリを開発してみました。文法や実装の仕方の記事はいろいろとあるので、どのように学習したかを重点的に書いています。私の勉強の備忘録の記事になってしまいましたが、勉強方法が分からず困っている人の参考になれば幸いです。
対象読者
- 開発の勉強をし始めている人
- Go言語初心者
- Next.js, TypeScriptちょっとわかる人
書いたきっかけ
- Go言語の製品やサンプルAppを多く見かけるようになったのでGo言語の勉強をしたくなった
- 部署内で技術用語を確認し合えるサービスがあったらいいなと思った
- Advent Calendarという目標と期限を決めて勉強したかった
完成品
いろいろやりたいことはありましたが、とりあえず一問一答までとなりました。
題材はとりあえず私に身近なクラウドネイティブにしてみました。
バックエンドの開発
Go言語の勉強
新しい言語を学ぶとき、私は簡単なサンプルAPを実装しながら学習します。私のおすすめはToDoアプリです。大体の言語でToDoアプリの記事があり、かつToDoアプリはいろいろな要素を学習できる良い教材だと思います。
Go言語を触るのが初めてだったので、いつもと同じように学習しようとしましたが、パッケージ管理で早速つまずきました。パッケージ管理方法がバージョンごとで異なるとか色々出てきましたが、最終的にはきちんとプロジェクトを作っていなかったことが原因でした。言われてみれば当たり前のことでした。。
具体的には、下記コマンドを実行していませんでした。
$ go mod init ${PROJECT_NAME}
当たり前であるが故に省略されていることがあるので、皆様は同じ失敗をしないよう気をつけてください。ちなみに私がこのことに気づいたのは、GoのホームページのGet Startedをやって気づきました。改めてGet Startedをやることの重要性に気付かされました。
プロジェクト作成やパッケージ管理は、この記事にも書いている通り、他言語から来た人がはまるポイントのようです。
最終的に下記2つのサイトを実践して学習しました。
Docker環境
OSに依存しないようにDocker環境で開発しました。
"docker go"で検索した時に出てきた記事を参考に作りました。今回Dockerの操作について詳細に説明しませんが、作成したファイルのみを参考として記載します。
services:
api:
container_name: api
build:
context: .
dockerfile: ./docker/go/Dockerfile
ports:
- 8080:8080
links:
- db
tty: true
volumes:
- ./api:/go/src/api
db:
container_name: db
build: ./docker/mysql
hostname: db
ports:
- '3306:3306'
environment:
- MYSQL_ROOT_PASSWORD: password
- MYSQL_DATABASE: quiz
- MYSQL_USER: user
- MYSQL_PASSWORD: password
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --skip-character-set-client-handshake
volumes:
- './db/data:/var/lib/mysql'
- './db/config:/etc/mysql/conf.d'
- './db/initdb:/docker-entrypoint-initdb.d'
FROM golang:1.17.3-alpine3.14
RUN mkdir /go/src/api
WORKDIR /go/src/api
COPY ./api /go/src/api
VOLUME /go/src/api
RUN go mod download
EXPOSE 8080
CMD "go" "run" "main.go"
APIの作成
この2つの記事を参考にして作りました。
1つ目の記事はステップバイステップでやってくれているので、初学者の私にはちょうど良かったです。データモデル部分を置き換えるだけで簡単に実装できました。
2つ目の記事は1つ目の記事をベースに作っているので、CORS設定やMySQL部分などを参考にさせていただきました。
フロントエンドの開発
Next.js,TypeScriptの勉強
フロントエンドは以前学習したことのあるNext.js,TypeScriptを使いました。知り合いに教えてもらいながら勉強したのでGo言語ほどちゃんと案内ができませんが、わかりやすく解説しているYoutubeの教材がたくさんあるので、教材には困らないと思います。
環境準備
バックエンド同様にDocker環境にしました。
sevices:
frontend:
container_name: frontend
build: ./docker/frontend/
environment:
- NODE_ENV=development
command: sh -c "npm run dev"
# command: sh -c "cd frontend && yarn dev"
volumes:
- ./frontend:/usr/src/app
# - .:/usr/src/app
ports:
- '3000:3000'
tty: true
下記コマンドでプロジェクトを作成しました。プロジェクト作成後に毎回cdするのが大変だったので、上のファイルのコメントアウト部分の通り修正しています。
$ docker-compose run --rm <container_name> sh -c 'npx create-next-app --example with-typescript-eslint-jest <project_name>'
Atomic Design
コンポーネントの分割の仕方はAtomic Designを採用しました。Atomic Designについては、ちょうど16日目の記事で解説しているのでそちらをご参照ください。この記事にも書いてある通り、Atoms/Molecules/Organismsの分け方に正解はなく、試行錯誤しながらベストなものを見つけていくしかないところが難しいなあと実感しました。
ちなみに私は下記教材で学習しました。有料ですが、初学者にはいい教材だと思います。
TailwindCSS
デザイン周りはCSSフレームワークの1つであり、利用者が増えているTailwindCSSを導入しました。良い面や悪い面を書いている記事があるのは知っていますが、まずは使ってみないと何も言えないので使ってみました。
導入については、検索すればすぐ出てくる下記2つのサイトを参考に導入しました。
作成までに時間がなかったので、コンポーネントはありものを参考にしました。具体的には、tailwind UI, TAILBLOCKS, tailwindcomponents あたりを参照しました。ツール集をまとめているサイトもあります。
APIとの繋ぎ込み
今回は、質問と解答という動的に変更しない項目を呼び出すだけなので、getStaticProps内で呼び出すことにしました。最終的に下記のような形で実装しています。
getStaticProps内でfetchではなくuseSWRを使おうと思いましたが、フックの基本ルールに引っかかることを忘れていました。。
ちなみに以前開発した時はCORSエラーにハマりましたが、今回はバックエンド部分であらかじめ設定したので問題ありませんでした。
まとめ
以上で本記事は終了となります。
今回は一問一答という最低限の実装のみになってしまいましたが、短時間でフロントエンドとバックエンドの触りを理解できたのかと思っています。
用語に関するクイズに決まった正解はないと思っているので、他人の解答を見て投票したり、質問文をこう変えたらいいのでは?と提案できるなどもっと回答者とインタラクティブな機能を今後は実装していきたいです。
自分が興味のあった内容を取り入れただけなのでベストプラクティスとは限りません。あくまでも一例としてご参照ください。また、私個人がプライベートで勉強した内容なので、会社とは関係なく個人の意見であることをご了承ください。
参考
ディレクトリ構成
frontendの下にsrcディレクトリを挟めば良かったなと後から思いました。
├── docker-compose.yml
├── api #バックエンド(Go言語)
│ ├── controller
│ ├── db
│ ├── entity
│ ├── server
│ ├── service
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── db #DB(MySQL)
│ ├── config
│ ├── data
│ └── initdb
├── docker #Dockerfile
└── frontend #フロントエンド(Next.js)
├── api
├── components
│ ├── atoms
│ │ ├── Button
│ │ ├── CloseButton
│ │ └── Modal
│ ├── molecules
│ │ ├── Answer
│ │ ├── Question
│ │ └── UserNameForm
│ └── organisms
│ ├── AboutService
│ ├── QuestionCard
│ └── QuestionModal
├── constants
├── node_modules
├── pages
│ ├── _app.tsx
│ └── index.tsx
├── public/img
├── types
├── package-lock.json
├── package.json
├── tailwind.config.js
└── postcss.config.js