snaqme Engineers Blog

おやつ体験メーカー snaq.me エンジニアによる開発プロダクトブログ

第3回【社内LT会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、3回目の【社内LT会】を開催しました!今回も業務委託メンバーが多く参加してくれて、ワイワイしながら情報発信を行うことができました。

今回もスナックミーらしくおやつを楽しみながら…

今回もまたマレーシアを生活の拠点とされている業務委託の方が、現地で売られていたおやつを紹介してくださいました!

トルコの伝統的なおやつ「ロクム」

「ターキッシュ・ディライト(ロクム)」という名前で、砂糖にデンプンとさまざまな種類のナッツを加えて作る、トルコの伝統的な甘いおやつとのこと。食感は柔らかく弾力があり、日本の「ゆべし(柚餅子)」に似ているようです。食べてみたい!

発表内容

おやつ体験の「飽き」をアサインで克服したい

発表者:兼崎

中身をお見せできないのが残念!

兼崎は2年以上前に、当時インターンとしてジョインしてくれたメンバーで、非エンジニアのメンバーとコミュニケーションを取りながら、弊社のシステムを幅広く開発してくれています。

最近はおやつの定期便の満足度を向上するため、パーソナライズのロジック部分を試行錯誤してくれています。特に「飽き」という部分にフォーカスを当てており、データアナリストのインターン生と協力して、どのようにデータ分析しているかなどを共有してくれました。

とても忙しいのにも関わらず、限られたリソースの中でしっかりスライドを作ってアウトプットする姿が、スタートアップのエンジニアらしくて感動しました。

アウトプットのモチベーションはみんな違ってみんな良い!

発表者: @yamataku3831

技術広報関連の勉強会などに参加すると、どうしても採用&組織のために技術発信してくれないかと働きかける方法…みたいなことが取り上げられている印象を受けます。自分もエンジニアリングマネージャーとして、チームメンバーにはどんどん技術発信をしてもらいたくて、さまざまな施策を行っています。

ただ、いちエンジニアとして過去を振り返った時に、私が技術発信を始めるようになったのは「自分のスキルを向上させるため」だったことを思い出しました。そして技術発信のおかげで言語化能力が鍛えられ、コミュニケーションが円滑になり、徐々に仕事がしやすくなったんです。

そう考えた時に「もっと自分のために技術発信してもいいよな。その結果チームに貢献できればWin-Winだと思えるくらいのスタンスでもいいよな」と思うように。そういったことを伝えたくて、今回の発表に至りました。

おわりに

社内LT会もいよいよ3回目。チームメンバーのアウトプットに対する向き合い方が、徐々に変わりつつあるように思えます。フロントエンドエンジニアのメンバーは約3ヶ月ごとにテックブログを書いてくれますし、どうすれば定期的に記事を書けるか模索している内容を Slack に投稿してくれていたりもします。

チームメンバーが情報発信をしやすい土壌を整えたくて始めた社内LT会なので、メンバーのそういった行動をとっても嬉しく感じます。これからもこの活動は続けていこうと思います!

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

7年目の React プロジェクトを TypeScript に移行した話

こんにちは。スナックミーでフロントエンドエンジニアをやっている前田です。
以前 新規サービスの技術選定についての記事 を書きましたが、今回は定期便のマイページについてのお話をしようと思います。

snaq.me の定期便とは

定期便のお届け内容イメージ

弊社のメインサービスである snaq.me は、8個のおやつを定期的にお届けするサブスクリプションサービスです。100種類以上あるおやつのレパートリーの中から、お客様の好みに合うおやつが自動的に選ばれるのですが、その選定はマイページで登録していただいた情報をもとに行われます。
マイページはお客様の情報を得るための重要なツールであるため、その歴史も古く、リポジトリが作成されたのは2017年1月でした。

(どうやっておやつが選択されているかを詳しく知りたい方は、 ユーザーに最適なおやつを届ける「アサイン」の歴史 などの記事をどうぞ!)

初期の技術選定と時代背景

2017年というと、つい最近のような、ずいぶん昔のような不思議な感覚を覚えますね。皆さんは当時どのような技術スタックを使用されていましたか?当時の私は、素の JavaScriptNext.js (まだ zeit で、v4.0.0!!!) を使ったり、flow-typedVue.js を使ったりしていた形跡が古い PC から見つかりました。
TypeScript は2016年の9月に v2.0 がリリースされ、 strictNullsCheck がサポートされた時期です。世間的にも、フロントエンドを Ruby on Rails (2016年に v5.0 がリリースされて API モードをサポート) などのサーバーサイドフレームワークから分離する設計が広く受け入れられるようになった時期だと記憶しています。

私が入社したのが 2021年なので、選定理由などはあまり把握していませんが、snaq.me のマイページはリポジトリ作成時から React, Redux を使用しています。それらは今でも活発にメンテナンスされているので、とても息の長い技術選定をされたと考えています。

昨今のフロントエンドの風潮と、マイページの課題

そうして走り出したマイページのプロジェクトですが、今でも日々多くの試行錯誤を行っています。我々のようなスタートアップにとって「少ない人的リソースの中でもとにかく早くお客様に価値を届け、フィードバックを得る」 ということは何より重要であり、エンジニアに限らずすべての社員が持っているマインドです。
しかしそのような試行錯誤の連続の中では、一度立ち止まって技術選定や設計の正しさを問うことは非常に難しいものです。徐々に問題が蓄積されていきました。

私が入社した時点ではリポジトリ作成から4年以上が経過しており、主に以下のような課題があったと記憶しています。

  1. 素の JavaScript で書かれており、静的型解析を利用できない
  2. 自動テストが少なく、変更の安全性が低い
  3. JSDoc などのドキュメントが少なく、コンポーネントや関数の使い方を調べるために多くのコードを読む必要がある
  4. ライブラリが古くアップデートしたいが、静的型解析や自動テストの恩恵をあまり受けられないことが原因で一歩を踏み出せない

昨今のフロントエンドでは TypeScript による型安全な開発が好まれるケースが多く、弊社でも 1 を解決することで 3, 4 の大部分も解決することができると考え、 TypeScript の検討を開始しました。
なお、2 の自動テストについては本記事では言及しませんが、静的型解析の有無にかかわらず書いていかなければなりません。(自戒も込めて…)

意思決定

さて、 TypeScript 導入を決意しましたが、事業としての優先度を決めるために社内での合意を得る必要があります。
スタートアップで大きな技術スタックの変更を行う場合、最初の壁となりがちなのが社内での合意形成ですが、当時から API のフルリプレイスを進めていた背景もあり、スムーズに合意を得ることができました。

特別なことは何もしていません。ですが、毎週のスプリント振り返りで型がないことの問題点を説明し、Slack の times チャンネルで TypeScript の素晴らしさを説き、本番環境を障害で止める(変更したファイルに依存したページが他にあることに気づかず...)など、毎日少しずつジャブを打ったのは重要だったように思います。

(余談ですが、現在ではスナックミーのバリューに「やってみよ!」という項目があり、このようなチャレンジが広く受け入れられる土壌が整っています)

移行期間と考察

結論から書くと、弊社では 2021年8月に移行を開始し、すべての .js(x) を .ts(x) に変換完了したのが 2023/6/15 でした。
推移は以下のグラフをご覧ください。

移行戦略

単に拡張子を変えるだけであれば、 tsconfig.json で型の厳格性を弱めてしまえばすぐにでも可能でしたが、安心して TS ファイルを扱いたかったため strict: true で移行を開始することにしました。
また、 strict: true で TypeScript へ移行する場合には移行作業に時間がかかりますが、機能実装を一定期間止める(もしくは優先度を下げる)ことを許容できなかったので、対象を定めてファイル単位で少しずつ移行しています。

移行のフェーズ

機能実装を続けていたため、ファイル数は全体を通して緩やかに増加していますが、 .js(x)ファイルの減少にはいくつかの段階がありました。

機能実装のついでに期

初期は TypeScript のお試し期間でもあったので、「新規追加するファイルは TypeScript で作成して、そのファイルから参照されるファイルを時間の許す限り移行しようね」という緩めのポリシーで進めていました。グラフ中では 2021年8月から 2022年4月 のあたりです。
想定していたよりサクサクと移行が進み、半年ちょっとで TS 率50% を超過。「これは2022年中の移行完了も可能では...?」と考えていましたが、ここから長い停滞が始まります。

JS ファイル全然減らない期

2022年4月から年末まで、 JS ファイルが一切減らない時期が続きました。大きな新規機能実装が続いたことと、よく編集する JS ファイルの移行が軒並み完了したことが主な原因です。
新規開発で TS ファイルがモリモリ増えたので相対的には TS 移行率が向上しましたが、2022年の後半は実質的にまったく進捗がありませんでした。

Issue 上げてみる期

設定画面などのあまり変更されない画面がボトルネックになっていたため、 UI 改善などの名目で issue を作成し、スプリントに組み込むように。これはおよそ2022年12月から2023年3月の時期ですが、グラフからもわかるようにあまり良い方針ではありませんでした。
当時全体のデザインリニューアルが進んでおり、設定画面だけ古いレイアウトのままだったこともこの手法を選んだ要因でしたが…

  • ユーザー体験としては全体の見た目を統一することが目的であるため、事業的に優先度が低い
  • UI 改善にはデザイナーを巻き込む必要があるため、エンジニアのみの工数で完結しない
  • 「新しい UI の適用」と「型のついていないファイルを読み込んで仕様を理解し、場合によって作り直す」を同時に行う必要があったため対応の工数が高い(よってさらに優先度が下がる)

などの理由から、一旦諦めて別の手法を取ることとしました。

いらないファイル一掃期

この時点でおよそ 250 ファイルぐらい JS ファイルが残っていましたが、まずは使われていないファイルを削除して以降対象を見極めることとしました。

  1. JS ファイルのファイル名から import 文で使用されそうなワードの一覧を生成
  2. ワード毎に git grep して1件もヒットしなかった JS ファイルを絞り込み
  3. 絞り込んだファイルを 1件ずつ目視で確認し、問題無ければ削除
  4. 削除した後もう一度 1 から実行(非 import が消えたことによって参照が消えた可能性がある)

という単純作業で、1日あたり 100ファイルほどの JS ファイルを検出し、削除することができました。

諦めてエラー踏み潰す期

ここまでで残った JS ファイルですが、

  1. あまり変更されない
  2. 難易度が高い

の二種に分類されていたため、まずは1を一掃することに。 ただし、あまり時間をかけられないため 「30分以上かかりそうなら 2 に分類して後回し」「@ts-expect-error と any を使ってもいい」という条件を付けて 1 ファイルずつ移行し、1日で 80ファイルほど移行することができました。

クロージング

この時点で残り70ファイルです!90% 以上が TypeScript なので、以前消せなかったファイルも安心して消すことができるようになり、ファイル削除だけでさらに 30ファイルほど消すことができました。

残りは前項で高難易度と判断したファイルだけだったので、スプリントに組み込んで工数を確保し、地道に型を付けて完了させることができました。機能実装の優先度を一時的に下げることになったので少し心苦しかったですが、作業対象が小さくなったため見積しやすく、他課題との優先度調整も行いやすかったです。

移行作業の反省点

ほぼ2年近くかかってしまいましたが、機能実装の優先度を大きく下げることなくやりきれたのはとてもよかったかなと思います。また、 any をほぼ使わずに移行できたので、以前より安心して機能開発できるようになりました。

しかし、実質的に移行にかけた時間は初期に想定したよりも少なく、うまく優先度を調整をすれば半年から1年程度で移行することも可能だったのでは…とも考えています。
移行を短期間で終わらせることができると、機能実装やリファクタリングをスムーズに行えるようになるため、チームやプロジェクトの規模によってはこちらの方がメリットが大きいかもしれません。

いずれにしても、「移行のために数週間から数ヶ月機能開発を止める」もしくはフルリプレイスするという選択ではなく、少し長めの期間をとって機能実装と並行するという手法は弊社にとっていい選択でした。
移行期間中、設計についてじっくりと思考を巡らせることができたため、私自身の考えを整理することができましたし、リファクタリングや設計に関する良質な記事が多く公開されので、それらのエッセンスを取り込むことができました。

今後どうするか

「 TypeScript に移行した話」とタイトルを付けましたが、TypeScript を使ったことがある方ならお気づきの通り、まだまだ「TypeScript への移行が完了した!」と言える状態とは程遠いのが現状です。
喫緊では、下記を対応しなければならないと考えています。

  • @ts-expect-error, @ts-ignore, unknown, any がプロジェクト内部に多数記載されている
  • noUncheckedIndexedAccess が false になっているので、配列やインデックス型へのアクセスが安全ではない
  • API の型定義 (主に null, undefined ) に若干不整合がある

また、ソフトウェアの安全性を静的型解析だけで担保することは難しいため、自動テストの追加やアーキテクチャ変更、ライブラリの変更などやるべきことはまだまだ山積しています。

弊社では「永遠のβ版」として常にサービスをアップデートしているため、このような問題も永遠になくなりません。しかし、多くのお客様に使われているサービスの機能開発をしながら、技術的な課題の解決に取り組める環境はとても得がたいものだと考えています。

「多くのユーザーに使われているサービスの開発をしたい!」
「技術的な課題に立ち向かいたい!」
という欲張りな方は、一緒に snaq.me のマイページ開発にチャレンジしてみませんか?

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

第2回【社内LT会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、前回に引き続き【社内LT会】を開催しました!今回は業務委託メンバーも多く参加してくれて、前回以上にワイワイしながら情報発信を行うことができました。

スナックミーらしくおやつを楽しみながら…

前回の社内LT会も盛り上がりはしたのですが、ごく一般的なLT会になってしまい、もう少しスナックミーらしさを出すことはできないかな…と思っていました。

スナックミーはおやつを取り扱っているスタートアップであるということと、そもそもアウトプットのハードルを下げるために始めた社内LT会であるということを考慮して、おやつをもぐもぐしながらリラックスした雰囲気でやってみることに!

食べながら参加というのがよかったのかはわかりませんが、前回よりも相互のコミュニケーション量が多く、終始和やかな雰囲気で会を進めることができました!この会をきっかけに、アウトプットのハードルがどんどん下がっていけば本望だなと思います。

ちなみに業務委託で手伝ってくださっている方のひとりに、マレーシアを生活の拠点とされている方がいらっしゃるのですが、マレーシアの伝統的なおやつを紹介してくださいました!

鮮やかで綺麗なニョニャクエ

「ニョニャクエ」という名前の甘いおやつで、米やタピオカ、ココナッツなどが使われているようです。カラフルな色が特徴的なのですが、花や植物などの天然色素を使って色づけしているので、体にもやさしいとのことでした。食べてみたい!

発表内容

僕の考えた管理画面とLambda の開発環境

発表者:岩田(スナックミーをしっかり支えてくれているパートナー)

岩田は約2年前から業務委託として一緒に働いているパートナーで、今日に至るまでずっとシステム開発を助けてくれています。

正社員とパートナーには、セキュリティ観点により、主に権限やデータ周りでお渡しできるものが異なります。それが理由で、パートナーにとってどうしても動作確認や開発を行いづらい部分が存在してしまいます。

そんな中、開発しやすい環境を自発的に構築していた彼が、他のパートナーも開発しやすいようにとわざわざ言語化して全体に共有してくれました。本当に感謝しています!

キーボード沼のすゝめ 〜自作キーボードの一歩手前まで〜

発表者:前田(スナックミーの頼れるフロントエンドエンジニア)

前田は自作キーボードを使って開発しているメンバーで、キーボードへの熱い想いを抱いています。先日自作したキーボードを見せてもらったのですが、とっても格好良くて、私も自作してみようかなと心が揺さぶられました(笑)

前田が作成した自作キーボード

エンジニアは1日8時間以上キーボードに触れ続けることも珍しくない職種です。体を労わることを目的としていたり、オシャレなキーボードでモチベーションを高めたり…キーボードにこだわる理由はいろいろありそうでした!

ちなみに私は前職で首から肩にかけての筋を痛めたことがあり、それがきっかけで肩が開く分離型のキーボードを使用するようになったので、キーボードへこだわる理由にかなり共感できました。

おわりに

チームメンバーが情報発信をしやすい土壌を整えていくためにも、アウトプットの練習を行う場として、これからも社内LT会を続けていきます!

今回はおやつをもぐもぐしながら開催したからか、相互のコミュニケーションも増えて、とても和やかな雰囲気で行うことができました。とはいえ、毎回何かしらアップデートできるといいなと思っているので、次回も今とは違う何かを始めたいですね。

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) /体験チーム / 株式会社スナックミー

ソフトウェアエンジニア Backend (lead) /オペレーションチーム / 株式会社スナックミー

プロダクトマネージャー / 株式会社スナックミー

第1回【社内 LT 会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、スナックミー社では初の【社内 LT 会】を開催しました!LT とは、Lightning Talks(ライトニングトーク)という短時間で行うプレゼンテーションのこと。正社員メンバーだけでなく、業務委託の方々も参加してくれて、一緒にワイワイしながら情報発信を行うことができました。

メンバーがアウトプットしやすい土壌を作りたい!

先日 AWS Summit に参加した際は、スナックミーを知っている色んな方がブースへ立ち寄ってくださいました。スナックミーが多くの方に知られているという嬉しさがあった一方で、おやつ会社であるスナックミーがなぜ AWS Summit に出展しているのか?と聞かれることも多かったんです。

スナックミーからエンドユーザーのもとへ届くものはあくまで「おやつ」だけなので、ユーザーごとにパーソナライズされたおやつが無事届くまでの過程に使用されているテクノロジーの存在が、どうしても伝わりづらいという性質を持っています。

そういった背景もあって、スナックミーとしてエンジニアチームの存在をしっかりと発信することで、世のエンジニアにもっと興味を持ってもらいたいと思うように。とはいえ、メンバーに突然「技術発信しましょう」と言ったところで、もちろんそのハードルはかなり高く感じることでしょう。

自分も前職で上司やチームメンバーに協力してもらい、勇気づけられ、多くのハードルを乗り越えたことで、ようやくアウトプットすることができました。ですから、次は私がチームメンバーに協力して、勇気づけて、ハードルを乗り越えられるようにフォローする番。その想いで社内 LT 会を開催するに至りました。

発表内容

PC が変わっても使い慣れた Neovim で すぐに開発を始める仕組み

発表者: @yamataku3831

私は Neovim を使用して開発をしています。その運用方法を先日 Zenn で投稿したのですが、意外と多く読まれたこともあり、有益な情報になるかもと思って発表しました。

zenn.dev

ほとんどのメンバーは VSCode を使用していて、Dev Container を通じて Docker を使っていることを知りました。私の運用方法でも Docker を利用しているので、お互い共通の「重くなってしまう」という課題感があるとわかって学びになりました。

スナックミーのおやつアサインの歴史とこれから

発表者: @miyoshihayato

社外秘の情報が含まれるため、スライドを共有することができないのですが、おやつの定期便において根幹を担うシステムである「アサイン」の歴史とこれからの展望について CTO に発表していただきました。

おやつの定期便は、現在はユーザーの好みに合わせた8種類のおやつを機械学習を利用してアサイン(割り当て)しています。この方法に至るまでにどういった経緯があったのか、そして今後ユーザーの満足度を更に上げていくためにどういった展望を考えているかなどについて、チームで認識を揃える良い時間となりました。

ざっくりとした概要にはなりますが、アサインの歴史を知りたい方はぜひこちらの記事をご覧ください。

labs.snaq.me

おわりに

チームメンバーが情報発信をしやすい土壌を整えていくためにも、アウトプットの練習を行う場として、これからも社内 LT 会を続けていこうと思います!

また今回は私自身初めての企画ということもあり、バタバタしてしまって、ごく普通の LT 会になってしまいました。せっかくなので今後はスナックミーらしく、おやつをもぐもぐしながら LT 会を行ったりと、徐々にアップデートしていきたいです。

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

スナックミーのエンジニアチームで直近動きたいこと (2023年7月)

こんにちは スナックミー CTO の三好 (@miyoshihayato) です
四半期ごとにチームに共有している近期の取り組みたい内容を一部変更し、こちらのエンジニアブログに載せたいと思います。

ナレッジシェア

スナックミーのエンジニアでは「サービス・フルサイクルエンジニアリング」という考えがあります。詳しくは以下をご覧ください。

labs.snaq.me

一見、範囲が広く、複雑そうに感じるかもしれません。しかし、全てを100%理解する必要はなく、意識して取り組むことが重要だと考えています。実際、エンジニアは様々なチームと連携し課題解決を行っており、各チームが解決した課題や取り組んだ事柄を隔週でシェアする会を実施しています。

このシェア会はエンジニア以外も参加しているため、深い技術的な知識を共有することよりも、各チーム間の相互理解(何に取り組んでいるのか等)を重視しています。

今回はこれに加え、技術面の共有をより強化することを目指しています。これまで社内LTやハッカソンのような活動はほとんど行ってきませんでしたが、チームや会社のスケールアップに伴い、ナレッジの共有は互いのスキルアップに繋がると考えています。

一人では学べる範囲が限られていますが、多くのメンバーがいることで知識を増やすことが可能であり、これに取り組みたいと思っています。また、この取り組みは個人の成長を促すだけでなく、他のメンバーを支援できる範囲を広げ、これまで取り組めていなかった課題も解決できると考えています。

そのため、今回のテーマとしてナレッジシェアを掲げました。

仲間集め

「仲間集め」は前回のブログでも触れましたが、非常に重要なことなので今回も取り上げます。これは今後も続けて共有したいと考えています。

興味がある方は、ぜひカジュアルでお気軽にお話しいただければと思います。

倍速

「倍速」は会社全体の四半期のテーマでもあり、重要なポイントであるため、エンジニアチームの直近の取り組みたいこととしても掲げました。

倍速とは、名前の通り、通常の2倍のスピードで物事を行うことです。例えば、MTGの時間を1時間から30分に短縮したり、PRを出す時間を半分にしたり、施策のアイデアを通常の2倍出したりなど、さまざまな形での取り組みが考えられます。重要なのは、意識的に取り組む ことです。意識的に取り組むことで、クオリティを下げずに短時間でアウトプットすることが可能になります。この感覚を得るだけでも、仕事への取り組み方が1段階、または2段階向上すると思います。時間を有意義に使うことで、自己投資やリアーキテクトへの時間、他のメンバーが困っていることへのフォローなど、さまざまな事柄に取り組むことができます。

まとめ

以上が、エンジニアチームが直近で取り組みたい3つのテーマです。 常にエンジニアの仲間を探しています。エンジニアはあらゆる面でチーム力の底上げに貢献したいと考えています(PM、バックエンド、フロントエンド、データエンジニアなど)。

興味がある方は、ぜひカジュアル面談でお話ししましょう。

おやつと、世界を面白く。」 一緒に面白くしたい仲間をお待ちしてます!!

youtrust.jp

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

プロダクトマネージャー / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

新サービスのフロントエンド技術選定

はじめに

はじめまして、スナックミーでフロントエンドエンジニアをやっている前田です。
入社3年目にして初のブログ投稿なので、緊張しています。

さて、今回は新規サービス立ち上げに際し0⇒1で技術選定に取り組む機会があったため、その経緯をブログとして記録に残したいと思います。
弊社では定期便の会員様向けに、お届け内容を設定できるマイページを提供しています。またオンラインストアでは、定期便でお届けしているおやつの大袋や、期間限定の特別なおやつ、ドリンクなど、おいしい商品を幅広く販売中です。
その中でも特に根強い人気を誇る商品『CLR BAR』と『good JerQy』を定期便としてお届けするサービスを、今回新しく開発することになりました。

UI ライブラリ・フレームワークについて

昨今では ReactVue.jsSvelteSolidJSAstro など、数多くの UI ライブラリやフレームワークが台頭してきていますが、その中でも snaq.me のマイページでは React を使用しています。ほかのライブラリに依存した要件がなく、特に不満もないので React を選びました。

また、ほぼパーソナライズ情報しか表示しない会員向けページが主コンテンツであり SSR や SSG のメリットをあまり受けられないと判断し、SPA で構築しています。
今となっては Next.js (SSG) は利用しても良かったかもしれないと考えていますが、本プロジェクトの着手時には App Router がまだ stable になっておらず、 Static export も未実装だったため React + React Router を使用しました。

アーキテクチャについて

bulletproof-react を参考にしました。弊社ではライブラリ周りに違いがある(CRA を使っていないなど)ためやや改造していますが、概ね同じ構成となっています。
features によるドメインの分類を行わず、src 直下の各ディレクトリに追加していくほうがシンプルな設計ではあるので、リリース初期は作業ペースが安定するのでは?という先入観を持っていましたが、サービスのドメインを分析して整理していくやりかたは、むしろ最初からやっておくべき工夫だと考えています。

スタイルについて

snaq.me のマイページでは styled-components を使用していますが、 使用するタグに頓着しづらい傾向がある点などに以前から課題を感じていたため、別のライブラリも使用することに。
styled-components を使用する上での課題は、命名規則や Tagged Templates の使用禁止などによって回避可能ではありますが、vanilla-extract など className でスタイルを適用するライブラリを使えば自然と解決できそうです。

しかし、今回はこのような制約があります。

  • リリースまでの期間がややタイトである
  • リリース初期は CSS を書く時間がどうしても増えがちだが、 Object Style だと'" の分、ややタイピング量が増えてしまう
  • CSS の細かな調整が必要な UI があまりない

結果として「スピード優先!細かなスタイルにはこだわらないでいい」ということで、UI コンポーネントライブラリである Chakra UI を使用することになりました。どの UI コンポーネントライブラリを使用するかという議論については、チームメンバーの経験から「キャッチアップの工数が低いもの」という観点で選んでいます。

また、Chakra UI を使用した場合は以下のような課題もあるため、今後の成長に合わせて設計変更や移行を検討したいと考えています。

  • やや型が弱い
    • mb="15" など存在しない値を指定しても静的なエラーが出ない
    • テーマのカスタマイズが補完されない(colors にブランドカラーを追加したときなど)
  • バンドルサイズが大きい
  • JSX がスタイルの指定で膨らむ
    • 適宜コンポーネントを分けていれば私は気にならないのですが、気になる方もいるようなのでメンバー構成の変動に合わせて検討

状態管理

snaq.me のマイページでは Redux を使用しています。大規模なサービスでは多くのグローバルステートが必要となり、それらを管理する目的としてなら Redux はいい選択肢です。
しかし、 新サービスは機能要件的にあまり多くのグローバルステートを必要としないため、より小さい構成で始められる Recoil と Jotai のどちらを使うかという検討を行いました。

ファーストリリース時の機能要件的にはどちらでも(もしくはどちらも使わず Context AP でも)満たすことが可能ですが、結論としては、下記の理由により Jotai を選択しました。

機能要件的にどちらも満たせるとはいえ、 Recoil にも多くの integration が存在し、人気のあるライブラリです。
今後、サービスが成長していくにつれ移行が必要になる可能性は十分にあると考えています。そのため、Jotai を各コンポーネントなどで直接参照せず、カスタム Hook などを経由して値の取得・設定をするようにしています。

テスト

主に VitestReact Testing Library を使用しています。
API 疎通が必要な箇所については、MSWAPI レスポンスをモックしています。

また、E2E テストとして Playwright を導入し、いくつかの画面で動かせる状態にはしていますが、CI などの運用フローに含めるところまで成熟させられていないのが現状です。
E2E テストを安定させるためには API のモッキングが必要となりますが、通常の UI 実装のための vite のサーバープロセスと、 MSW で API がモックされたサーバプロセスの二つを用意する必要があり、開発端末のスペック的に両方を起動し続けることが難しかったことが要因です。

Playwright でも Component Test が試験的に導入されつつありますが、その用途であれば React Testing Library によるユニットテストのほうが高速に動作するため、今は Vitest と React Testing Library に主軸を置いています。

その他細かなライブラリ

  • Vite
    • snaq.me のマイページでは webpack を使用していますが、コードベースが巨大になった影響でファイル保存時の CPU やメモリ負荷が高いため、ノーバンドルツールを選択しました。
  • axios
    • interceptors でリクエストに認証情報を付与するほか、500レスポンスを検知して通知するために使用しています。axios 自体があまり型が強くない点と、axios をラップした関数を作成しているため、fetch に戻すことも検討中です。
  • neverthrow
    • 主にAPI エラーをハンドリングするために使用しています。
  • React Router v6
  • dtsgenerator
    • API が OpenAPI を出力してくれるので、それを型定義に変換するために使用しています。
    • OpenAPI を axios や fetch のラッパーなどに変換してくれるツールも存在しますが、弊社では OpenAPI から型情報だけを得たかったので dtsgenerator を選択しました。

おわりに

というわけで、新しくリリースされたサービスはこちらです。
私の推しは『good JerQy』の黒糖醤油味ですが、他フレーバーも『CLR BAR』もおいしいので、ぜひお試しください!
またスナックミーはエンジニアも積極的に募集していますので、興味のある方はぜひ応募していただけると嬉しいです!

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

CLR BAR

clrbar.com

https://portal.snaq.me/checkout/flavor-select?brand=clrbar

good JerQy

goodjq.com

https://portal.snaq.me/checkout/flavor-select?brand=jq

【Vimmer の Webエンジニアが TypeScript で Neovim プラグインを作った話】をイベントで発表してきました!

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

このたび6月21日に、クラスメソッド株式会社のオフィスで開催されたイベントにて、LT登壇の機会をいただきました。

connpass.com

250人のエンジニアが参加する中、今回お話しさせていただいたテーマは【Vimmer の Webエンジニアが TypeScript で Neovim プラグインを作った話】。この記事では、発表時に使用したスライドもご共有しつつ、私が TypeScript で Neovim プラグインを作るに至った背景をご紹介します。

スナックミーの世界観あふれるマイページは TypeScript で作られている

スナックミーでは「おやつの定期便」だけでなく、ECストアでも楽しいおやつ時間を体験することができます。特にサービスとユーザーの大切な接点であるマイページは、ナチュラル/ポップテイストのソーシャルゲームを彷彿とさせるような、ワクワク感にあふれたデザインになっているのが特徴的です。

マイページの画面

アニメーションやマイクロインタラクションが豊富に使われているのですが、実は TypeScript がベースになった React で開発されています。私は前職でも React や React Native を使っていたので、TypeScript は親しみ深い言語のひとつと言えます。

Web アプリケーションを Neovim で開発していた自分に訪れた転機

前職の上司の影響もあって、私はエンジニアとしてのキャリアをスタートした頃から Neovim を使っていました。Vim Script や Lua は設定ファイルを書く程度しか使ったことがなく、プラグイン開発は考えたこともありませんでした。

ところが、2021年7月に Denops という Vim/Neovim のエコシステムが vim-jp から正式リリースされ、JavaScript や TypeScript を用いてプラグインを開発できるようになりました。Denops の存在を知ったことをきっかけに Vim/Neovim プラグインを作ってみたくなった気持ちが再燃し、使い慣れた TypeScript でプラグインを開発してみることに…

これが Neovim プラグインを開発するに至った背景です。Denops とは何か?どういうメリットがあるのか?どのように作るのか?などは発表資料にまとめていますので、気になる方はぜひご覧になってください。

おわりに

楽しいおやつ時間を想起させるような、スナックミーならではのワクワクに満ちたマイページ。そういった世界観をフロントエンドエンジニアが具現化できている要因のひとつに、FastAPI に mypy を利用して型を指定したり、自動テストを実装したりして、必要なデータを安定的に提供する基盤を構築しているということが挙げられます。

弊社ならではの世界観を実装面からしっかり支えていただけるバックエンドエンジニアの方も、積極的に募集しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー