TENTIALのテックブログ

株式会社TENTIALのエンジニアチームが開発や組織のよもやまを謳っていきます

フルスクラッチでECサイトを作る方法とそれを選択するということ

こんにちは。TENTIALというD2CスタートアップでCTOをしています、いっちです。
エンジニア採用困ってるんだよねっていう話をしたら、
弊社のテックリードが「エンジニア採用にはやっぱテックブログっしょ!卍」とか言い出したので、
とりあえずエンジニアチームの共同作業の一つとして意見に乗ることにし、始めました

ひとまず、
弊社はECサイトを自社でフルスクラッチ(Nuxt.js + Express.js + Mongo)で作っていることもあり、
EC事業者かそれを担うエンジニアの役に立てばと、簡単にフルスクラッチでのECサイトの作り方(概念)をまとめてみました。

フルスクラッチでECサイトを作るために準備するもの

  1. いくつかのECサイトでの購入経験
  2. 複数のECサイトのソースコードを眺める
  3. 決済サービスのAPIを眺める
  4. ライブラリを作れるぐらいのプログラミングスキル
  5. ジョブ管理・ログ・定期実行に対する高い意識
  6. 手動テストとめげない根性
  7. 2〜3ヶ月分の工数
  8. 技術に対する全社的理解

以下でそれぞれ説明していきますが、ざっとこんなもんでしょう(適当)
(これも準備した方がいいよ!っていうのがあればご教授くださいませmm)

いくつかのECサイトでの購入経験

当たり前なので一応書いているだけですが、
Amazonでも楽天でもZOZOでも何でも良いので、ネットで買ったことがないとそもそものユーザーフローが分からないかと思います
どのような行動フローで何の値を保持して購入完了まで持っていっているか触りながらイメージしたりしました

複数のECサイトのソースコードを眺める

ここからはエンジニアっぽいことをしていきます
色んなサイト(大規模なところ)でデベロッパーツールを使ってソースコードを見まくりました

とあるサイトで分析しやすいようにカートに入れた時刻を入れてるとか、
コンソールのNetworkから商品っぽいAPIレスポンスを眺めるのも良い勉強になりました
<input type="hidden" でソースコード内検索すると色々と大事そうなところが出てきたりします

f:id:hey_icchiman:20210215232516p:plain
商品毎にカート入れた日が分かるようにカート入れる際のtimestampが埋め込まれている

f:id:hey_icchiman:20210215232900p:plain
商品一覧を取ってきてるAPIっぽいのを探してJSONで見る

JSON整形してレスポンスを見るとこんな感じだったりしました(sale_priceなるほど~、割引系の設計・UIって最初から考慮し辛いですよね)

{
    "status": 200,
    "success": true,
    "data": {
        "list": [
            {
                "sku": "~~~",
                "item_code": "~~~",
                "core_item_code": "~~~",
                "product_name": "デニムスリムテーパード パンツ",
                "brand_name": "~~~~~~",
                "color_code": "~~~",
                "color_name": "~~~",
                "size_code": "~~~",
                "size_name": "S",
                "list_price": 4950,
                "sale_price": 3950,  // 割引額表示のUIを考慮する値
                "image_large": "/images/~~~.jpg",
                "page_url": "~~~"
            },
            ...
    }
}

 

決済サービスのAPIを眺める

利用するAPIだけでなく、
他の決済APIの仕様、パラメータを眺めるとDB設計が深まりました
ついでにStripeのAPI仕様は凄く参考になりましたので引用しておきます(弊社は実際にはGMO Paymentを利用している)

f:id:hey_icchiman:20210215214841p:plain
↑StripeのProduct APIを見て商品情報の持ち方を参考

f:id:hey_icchiman:20210215214901p:plain
↑StripeのSKU APIを見てSKU情報の持ち方を参考

f:id:hey_icchiman:20210215231321p:plain
↑StripeのOrder API(注文作成)を見て購入時の処理情報を参考

これを試行錯誤することで命名規則やテーブル設計はだいたいできるかなといった所存でした

ライブラリを作れるぐらいのプログラミングスキル

関数はなるべく汎用的で万能な仕組みを意識しました(オプションをつけてあらゆる処理を通すことができるライブラリのような)
特にカート内の計算はどこでも使うのでカートの配列を送るだけでカートの情報が整うようなAPIはめちゃくちゃ活躍しています(ページ遷移させないUIUXとか細かい表現が手軽にできる)
合わせて、管理画面やあらゆる内部処理でカートの計算は特に使うため、
いつでも使えるようにexport 関数化(JSの話ですが)しておいた方がいいです。

下記は実際のカート処理で手軽にカート情報を整形できるように、ローカル→サーバーへのやり取りはこのような形にしました

# ローカルで持っているカート情報(未ログインユーザーなどあらゆる条件も保持できるようにローカルで別持ち)
[
    {
        "product_id": "~~~~",
        "sku_id": "~~~~",
        "droped_unixdate": 1613400345525 # 他社参考にカート落ちの時刻も入れるようにした
    },
    ... # ローカル保持しているカートは使いやすい・見やすいようにシンプルな配列で持つ
]

下記は、上記の単純なカート配列をAPIに送るだけで商品詳細+SKU詳細+カート内の総計額を出してくれる大好きなAPIになってくれました(都度カート情報も更新してくれるの嬉しい)
このAPIを通せばカートの詳細情報をいつでも簡単に取れるため、
カート情報を扱ったUIUX改修が圧倒的にしやすくなりました

{
    "status": 200,
    "message": "SUCCESS",
    "data": {
        "items": [
            {
                "product": {
                    "name": "商品名商品名",
                    ...
                },
                "sku": {
                    "color": "レッド&ブラック",
                    "name": "SKU名SKU名",
                    "price": 6171,
                    "product_id": "~~~",
                    "size": "M",
                    "main_image": "~~~.jpg"
                }
            }
        ],
        "total_price_in_tax": 6171,  // 合計金額
        ...
    }
}

ジョブ管理・ログ・定期実行に対する高い意識

どんなにリアルタイムで処理できていても、
少しのサーバー障害(自社サーバーのみならず各種利用APIサービスの障害)による処理の途中停止で決済漏れや配送漏れなどが必ず起こります
そのため、いつ何が起きてもいいように、定期的にエラーで止まっている処理を各所でやり直せる仕組みが必要でした。

いつどこまで処理が通っているかのログ埋め込み・監視体制と、
仮売上→実売上(決済の細かい話ですが)や配送情報を更新する定期処理、メルマガ情報の更新など、
バッチ処理を10個近く作りました(この辺りはリリース後に付け足していきましたがまだまだ足りないかも)

一定ジョブ管理で賄う安心感ができることで、今では不具合時の対処も効率化出来てきました

手動テストとめげない根性

理論上システムができるとひたすらデバッグテストで漏れを対応していきました。
どんなにあらゆるデバッグケースを想定しながら実装していても、エンジニアは魔法使いでも何でもなく、ただの人間なので漏れは必ず起きます (ましては何万行のコードを0から1文字ずつ書いてるのにバグが起こらないわけがない)
各ページや全リンクの遷移テストや全購入パターンでの購入テストなど社員全員の時間を頂き全社員(当時18名ほど)でオフィスの広場に集まってみんなでデバッグしました

それでバグ以外にも「ここ押しづらいよね」とか「ここ分かりにくいかな」とかとか改善点も出てきたためスプレにまとめて(確か全部で100項目近くあった)
ひたすら改修していきました(むしろ経験上リリース前は100近くの項目が出てくるため、100近く出るまではリリースしないぐらいの感覚でしつこく洗い出しました)

2〜3ヶ月分の工数

開発する上で工数の洗い出し・会社全体の理解が必要不可欠です。
自分たちは以前EC forceというECプラットフォームを利用していてからの移動でした。
もちろんEC forceの改修もあったり別事業(弊社はメディア事業もしており)の稼働にも時間を取っており、
一昨年の年末から一人でコード書き出して途中からインターンが2人入り業務委託1人含め4人体制(しかも平均年齢当時23歳ぐらい)で作りましたが、
翌年の3月半ばぐらいまでかかったのでEC事業に専念したとしても早くても2〜3ヶ月はかかる理解をこれからフルスクラッチでECサイトを作ろうとするビジネスサイドの人たちは持っておいた方がいいと思います

技術に対する全社的理解

もちろんフルスクラッチでするデメリットはありますがメリットも大きくあると思っています
むしろシリーズA以降でテックに重きを置きたい企業はフルスクラッチで書くべきかなぁとも思っています。

最近、ECプラットフォームが便利になってきているためECプラットフォームで初速も考慮し進めては良いのですが、一定のフェーズで作り変えが生じるパターンも出てきます。(細かいUIUXの再現や付け足し機能、独自の新機能などはエンジニア的にはかなりやり辛くなったりと、実際に作り変えはしなくても議論自体は大抵起きる)

その上、ECプラットフォームからのユーザーの完全移行などはほぼ出来ず(ユーザーに1フロー介さないといけない)、溜めたユーザーをチャラにしてしまうこともあるため
最初からフルスクラッチで書けるに越したことはないかなぁと思っています(ちなみに弊社はスプレなどに過去のユーザー情報は移動しましたがDB上ではチャラになりました)

「shopifyでいいじゃん」って一度でも言われたことがあるECエンジニアは多いかと思いますが、
ECのフルスクラッチなんて贅沢なもので、予算と時間をかけてわざわざ作ることになるため、その意見は合ってはいます。

ただ、一見、見た目が同じでも中身が違うことに本質があるかなと思っています。

ECプラットフォームで書いた時に何か不具合が起きたらプラットフォームのせいにするか、
自分たちで書いたコードで自分たちのせいにして(何か別サービスのアップデート時でも)自分たちで直すか、
のどっちを選びたいか

どういうエンジニア組織・文化を作りたいか
そのエンジニア組織が将来、社内ましてや社外にどんな影響を持つようにしたいか
どのような価値を創造できる集団にしていきたいか

エンジニア組織や文化はお金があれば作れるものではなく、
経験と社内の歴史とその雰囲気が作るものだと思っています

まぁECプラットフォームかフルスクラッチかはどちらを選んでも隣の芝生は青いと言った形で、
ないものねだりでしかなかったりするので、
自分が一番良いと思った選択をやり切る、
それをみんながする環境にこれからもしていこう

と書いてて思いましたのさ。

最後にエンジニア募集してます!!