こんにちは。WhatACotton といいます。わたこっとんです。
この記事では 1 年かけて開発してきたカリスワークスについて書いていきたいと思います。
# このプロジェクトの経緯
大学に入学してから、何か頑張りたいと思って題材を探していたところ、母親から「そのうちブレスレットを売ってみたいんだよね。」という話を受け、〇〇カリや〇〇マなどで出品するのもいいけど、システムを1から開発してみるのも面白そうだよねという話になり、そこからプロジェクトは始まりました。1から勉強して、全てやってみたいという思いから後述する書き直しまでは友人達に相談することはありましたが、全て一人で実装を行ってきました。
ちなみにこのプロジェクトは通年で個人がやりたいテーマを決め、研究や開発を行うという、筑波大学の情報科学特別演習という科目も兼ねており、定期的に DB 設計などに関しては担当教員からのアドバイスの頂いておりました。
当初は母親のみが販売するという話だったので、そのように開発を行っていたのですが、夏休み辺りに母親から、「〇〇さんも出品してみたいんだって。」という話が舞い込んできて、そこから実装のハードルがとんでもなく上がったのですが、プラットフォーム型 EC サイトの開発へと方針を転換していくこととなります。
24 年 1 月頃、やっと形が見えてきたのですが、コードを友人に見せたところ、これは保守性がとても悪く、管理に手が負えなくなると指摘を受けました。確かに今思えば、よくこんなコードで公開しようとしていたものだと思うのですが、それからまたスクラッチからの開発がスタートしました。書き直すのにあたって設計をその友達に手伝ってもらいました。途中で忙しくなって開発から抜けてしまったのですが、立ち上げ時に協力してもらった彼にはとても感謝しています。ありがとう。
友人達にはずっと 3 月いっぱいに公開すると言い続けていたので、それを目標に死にものぐるいで実装してきました。1 月末から実装し始めてバックエンドは 1 万行近く書きました。
そして、やっと 3/31 の 22 時頃にサービスのテストリリースを達成することができました!!!
ただ、このサイトはまだテストカードでしか決済できず、商品や金銭のやり取りはまだ行えないため、プロジェクトは完了したわけではありませんが、本当にあと一歩というところまで来ました。バックエンドに関してはほとんど開発が終わっているのですが、テストを書きながら実装していたのでフロントエンドに着手するタイミングが遅れてしまったため、まだもう少しかかるという感じです。これから本番公開に向けてフロントエンドのやりきれていない箇所の実装と、テストリリースでは実装していなかったフロントエンドの出品者側の実装を行う予定です。
# 技術的な話
ここからはプロジェクトで使われている技術スタックについて書いていこうと思います。
(ここで説明しているものは主に 1 月から書き直したプロジェクトのものです。)
# フレームワーク
使用したフレームワークは RESTAPI と gRPC です。
基本的な実装はすべて RESTAPI で行っており、管理者関連の実装を gRPC で行いました。
本当は全て RESTAPI でも良かったのですが、今までと同じようにしてエンドポイントを定義して実装するだけだと刺激が足りないと思い、gRPC で実装してみたという感じです。gRPC は proto ファイルを使いまわすことができ、すごく直感的に実装することができたので、そのうち gRPC のみを使用したシステムを実装したいなと思いました。
# 言語
フロントエンドをTypeScript
、バックエンドをGolang
で開発しました。
選定理由ですが、フロントエンドは TypeScript に強い友人が多かったからで、バックエンドは Golang をおすすめされて触ってみたら、とても感触が良く、使いやすかったからです。パフォーマンスなどで選んでいるわけではなく、手にとても合っていたので採用しました。
# 言語でのフレームワーク
フロントエンドはNext.JS
、バックエンドはGin
を採用しました。
Next.JS では App router を採用しています。(旧実装では Page router でした。)
Next.JS で開発した理由はドキュメントが豊富なところと、友人が触っているプロジェクトの多くで採用されていたため、実力がついてきたら貢献できるかもしれないと思ったからです。
実際のところ、現在友人達によるプロジェクトに途中参加し、issue を潰す役目に回っております。立ち位置としてはページの具体実装よりかは、エラーハンドリングや挙動の修正をメインで行っております。
バックエンドで Gin を採用した理由としては Golang のメジャーなフレームワークであることもあるのですが、やはり本当に未経験だったときにはじめて動かすことができたフレームワークということもあり、書き直しをする際にも楽だからという点で採用しました。書き直しを行う際、ほかのフレームワークでは chi を検討していました。
# テスト
再実装を行う際に力を入れたのはテストです。先輩方からテストの重要性を教わり、書き直しを行うタイミングでちゃんとテストをかけるようになりたいと思い、先輩が書いたコードを読みながら見様見真似で実装していきました。
参考にしたリポジトリ:
テストを書いていく中で、small、medium、large テストと、規模を大きくしながらテストを書くことを意識していきました。
最近は github Actions で依存関係をもたせて CI を回すことに気持ちを向けていて、少しずつではありますが、CI/CD にも関心が出てきました。
# 開発手法
書き直しをするにあたって OB の先輩から Dependency Injection という依存性注入と呼ばれる開発手法を教えていただきました。これをすることでテストをより書きやすく、保守性の高いコードをかけるということを知り、その開発手法を勉強しながら書き直しを進めていきました。
Dependency Injection は最初はなんのためにやっているのかあまり理解できなかったのですが、とりあえずやってみるということでやっていくと、すぐにその威力に思い知らされました。うまく関心の分離ができていたので、旧実装よりも重厚な実装を実現することに成功しました。更にモックを作ることもできていたので、今実装するべきはどこなのかを明確にしながら開発することができ、とても開発体験が良かったです。
# データベース
データベースは mariaDB を使用しています。
データ構造はコロコロ変わっていましたが現在はこの構造で安定しています。
上下で起動しているサーバーを分けていて、これから transaction の方の DB は定期的にダンプを取って保管しようと考えています。
# イメージなどのリソース保管場所
cloudflare R2 を使用しております。ドメインを cloudflare で管理しているため使いやすく、無料枠があるので採用しました。CDN でのキャッシュも魅力的な点でした。ちなみにこのブログも cloudflare pages で公開しております。
# メールサーバー
cloudflare Email routing を使用して、gmail 経由で送信しております。ただこの体制はメールをたくさん送信するようなサービスになってしまうと gmail の制限がかかるため、少し不安要素ではあります。
# 外部ライブラリ
# ユーザー認証
firebaseSDK を使用しております。ユーザー認証は手前実装だとリスクしかないと考えたからです。
旧実装では firebase から一度だけ jwt を取得してそのあとの通信は独自に発行した token を cookie に保存してやり取りするというものだったのですが、firebase の機能を全然活かせないことや、一度取得したセッションが何らかの影響で期限切れになった場合にそれを検知することができないこと、複数端末での同時ログインが実現できないことから廃止しました。
現在の実装では auth を始めに取得し、その auth を使いまわし、バックエンドへの毎リクエストごとに jwt を載せる実装をしています。
# 決済
Stripe SDK を使用しております。決済は Stripe に一任しております。そのうち paypay も使用可能にしたいと考えています。現在の実装では複数サービスに対応できる形なので、余力があればやりたいと考えています。 連結アカウントなどの機能によって出品者が登録した口座に自動送金できるため、Stripe を採用しております。
# CSS ライブラリ
chakra UI を使用しています(一部 material UI)。ただこれは暫定なので変更することがあるかもしれません。旧実装では material UI を使っていました。
# 技術構成
フロントエンド・バックエンド構成で、nginx でリバースプロキシされており、認証・決済を上記の通り外部ライブラリにまかせているという形を取っています。
# 終わりに
テストリリースまで約一年間かかりましたが、ここまでこれたのはずっと気持ちを持ち続けることができたことにもあると思いますが、それ以上に先輩方や友人達に恵まれていたからだと思います。charis works の charis とは感謝という意味があります。最初は母親が全てに感謝するという意味合いでつけたこのプロジェクト名ですが、これまでお世話になってきた方々に感謝しています。本当にありがとうございます。
まだ本番リリースではないこのプロジェクトですが、なんとか本番を目指して開発を続けていきたいと思います!!!