〜サイトカスタマイズ機能の開発物語〜フロントエンドこんにちは、Webエンジニアの野川(@chan_naru_way)です。AIを触ってなんでも知った気持ちになることです。(最近はGensparkも面白い!)とはいっても、回答を鵜呑みにせずに自分の頭で考え続けたい、まだまだAIに使われたくない所存です。徐々にパソコンのファンの風が心地よく感じる季節になってきました。季節の変わり目なので、みなさん体調に気をつけてくださいね〜。今回は、Communeで提供している機能のひとつ「カスタムブロック」が、どんな課題を解決するために、どんな判断や開発を経て作られたのかを紹介します。ひとつの事例ですが、私たちの開発の雰囲気が伝われば幸いです。〜SaaS依存のカスタムブロック機能〜Communeはコミュニティづくりを立ち上げから活性化までトータルサポートするコミュニティサクセスプラットフォームです。コミュニティサイトの管理者たちは、Communeを使ってサービスやコミュニティの世界観・魅力をユーザーに正しく伝えたいと思って日々試行錯誤しています。コミュニティを彩るためサイト上に「もっと自由にコンテンツを掲載したい!」と意見をいただくこともありましたが、当時のCommuneが持ち合わせていた機能(ホームバナーやカードリンク、投稿など)だけではコミュニティ管理者の素敵なアイデアを十分に表現できないことがありました。そこで、2023年の3月ごろにコミュニティサイトをカスタマイズできる機能「カスタムブロック」の提供を開始しました。カスタムブロック機能とは、サイト上にあらかじめ指定した複数の箇所に任意のHTMLコンテンツ(HTML/CSS/JavaScript)を埋め込むことができる機能のことです。当時はPoC版という立ち位置でWeb版のサイト(ブラウザのスマートフォン表示は含み、スマートフォンアプリは含まない)だけに機能を提供しており、実現手段に他社様のSaaSを使っていました。当時のシステムや運用の流れはざっくりこんな感じです。パターン2コミュニティサイトの数や管理者の人数が増えてきたこともあり、カスタムブロックへの要望も多くいただくことになりました(とても嬉しいです!)。お客様側でコンテンツを制作しても、弊社側で設定する必要があり、設定を依頼すること、そしてコンテンツを修正するたびに再度設定を依頼するという、弊社だけでなくお客様側にも手間がかかってしまう状況でした...。Communeのスマートフォンアプリのサイトも、もっともっと自由に彩りたいという要望がどんどん高まっていました。した背景から、カスタムブロック機能のあり方を見直す必要があると判断しました。そこで、この記事で紹介する取り組みが始まったのです。内製化を決断!理由と判断基準ソフトウェア開発では、新しく機能を開発する際に「外部サービスの活用」と「内製化」の選択肢があります。一般的に、以下のような考え方がベースにあると思います。段階では、外部SaaSを活用し、迅速に価値検証を行う。機能の価値が証明された後は、内製化を検討し、自由度の向上やコスト・UXの最適化を図る。要はサクッと試して「いける!」となったら自分たちで作っちゃおう、ということです。カスタムブロック機能の開発においても、これらを意識して検討を進めました。PoC版のカスタムブロック機能は、いくつか課題を抱えていました。ネイティブアプリのコミュニティサイトのカスタマイズ性が低い(カスタムブロックがネイティブアプリ版のCommuneに対応していない)。カスタムブロックにコンテンツを掲載するために、一定のコミュニケーションコストがかかる。このコストはカスタムブロックの利用者が増えるとともに右肩上がりで増える可能性がある。同じコミュニティサイトでもスマホアプリユーザーが取り残されることになったり、スマホアプリこそ適したコミュニティを彩ることができなかったり。お客様が増えれば増えるほど、我々の作業も増える。嬉しいような、大変なような。いずれも、PoC版で価値を一定示しつつも自由度が足枷になっている、と思えます。内製化も検討できそうなタイミングと捉えました。課題を乗り越える方法をいくつか比較検討しました。重要なのは、課題を解決した上でコストを抑えられるかです。他社様のサービスを使うことはベストな解決策になることも多いですが、システムの一部が社外に依存する(社内で管理できない要素が増える)という考え方もあり、慎重に検討する必要があると私は思います。短期的な修正コストだけでなく長期目線で検討した結果、内製化に決めました。この決断は、すでにPoC版で提供している価値を保ちながら技術的な自由度を高め、また長期的なコスト削減も見込めるものとなりました。設計と技術選定カスタムブロック機能には、主に3つの機能が必要になると考えました。サイト上のあらかじめ指定した箇所に対して、任意のコンテンツ(HTML/CSS/JavaScript、画像や動画など)を挿入できる機能コンテンツを表す各種情報(HTML/CSS/JavaScriptのスクリプト、画像や動画ファイルなど)をコンテンツ掲載箇所毎に保持する機能サイトの管理画面上でコンテンツを作成できる機能(エディタ機能やプレビュー機能)コンテンツの表現に自由度を与えつつ、実装もシンプルになって開発工数も見通しが立ちやすい考え、iframeを選びました。iframeは独立したオリジンで提供されるため親サイト(メインのコミュニティサイト)とのセキュリティ分離がしやすく、リスクも想定しやすいので比較的スムーズに開発できるだろうと見込みました。Cloud)を活用しました。Cloud)上で動いてるCommuneのバックエンドAPIと接続(接続方法を後述する)しました。コミュニティサイトの管理画面上にHTML形式のスクリプトの入力画面を用意し、そこでコンテンツを受け付けるようにしました。※最初のリリースではHTML形式のスクリプト、要は文字列だけを受け付ける形にしました。画像や動画は入力画面から直接アップロードはできません。画像や動画を載せたい場合は、別途ファイルアップロードサービスで配信し、HTMLのimg要素やvideo要素などでURL指定してもらうようにしています。Communeでも他の機能の一部でファイルアップロード機能を提供しており、お客様にはこれを使ってもらっている現状です。今後は文字列だけでなくファイルアップロード/ディストリビューションサービスとしても拡張しようと考えています。Storageの接続方法は、バケットをストレージボリュームとしてマウントする方式にしました。cloud.google.comこれは開発時点でPreview版の機能だったのですが、下記の理由で採用しました。新しい技術を採用することで、将来的な機能拡張や最適化の際に知見を活かせる可能性があり、また開発者の技術力向上とモチベーション向上につながると考えた。ローカル開発環境とクラウド環境で同じファイルシステムインターフェースを使用できるので、開発時の認知負荷を下げれると考えた。堅苦しく書きましたが、要するに「負荷もそこまで高くなさそう」そして「おもしろそう!」ということです。新しい技術はリスクも伴います。代替案や運用体制を考えてから採用に進みました。APIを使用する方法」で、これは社内ですでに実績のあるものです。APIの直接利用も含めた設計を行う予定です。FUSEには以下のような制限事項があります。今回開発するカスタムブロック機能ではパッと懸念が思い浮かばず「代替案もあるしこれ以上深く考えなくても大丈夫だろう」とスピード感を優先しました。同時書き込みの制御やファイルロックがサポートされていないメタデータの同期が完全ではない小さなファイルの頻繁な読み書きでパフォーマンスが低下する可能性があるこれからも新しい技術と実用性のバランスを取りながら、知的好奇心を刺激しつつ、より良いプロダクトを開発して参ります。初回のリリースでは、エディタ機能は提供したもののプレビュー機能は提供していません。「コンテンツを表示する前に一度目視で確認したい!」というニーズには、コンテンツの出しわけ機能(表示先の制限機能)で対応します。確認用のユーザーへのみコンテンツを表示させることでプレビュー機能を代替しました。これは大きな例でしたが、このように提供できる価値を損ねずに開発工数を節約する工夫は継続していきたいです。そこに焦点を当てて実装内容を紹介します。コンテンツをデータベースへ保存する/取得するバックエンドAPIの部分は省略します。コミュニティサイト側(一般ユーザー画面)の実装コミュニティサイト側へiframe要素を追加します。CommuneのフロントエンドはNext.js/Reactで作っており、このようなReactコンポーネントを用意しました。APIを使用する際は、必ずoriginをチェックしましょう。信頼できるソースからのメッセージだけを処理して潜在的な攻撃を防ぐためです。)}このReactコンポーネントの仕事は、データベース上に保存されたカスタムブロックコンテンツをiframeに読み込むようにsrc属性の値を設定し、コンテンツの高さを送信するイベントをリッスンしてiframe要素の高さを調整することです。HTMLは自由に作れるのですが、少し制限を設けました。バナー画像のような静的コンテンツを埋め込む場合、コンテンツ読み込み時やリサイズ時に1度だけ、iframe要素の高さ情報を親サイト(コミュニティサイト)側へ伝える必要があります。下記のようなスクリプトを埋め込みます。</script></body>...省略また、何らかのイベント(クリックやアニメーション等)でコンテンツの高さが変わるような動的コンテンツを埋め込む場合、イベントを実行するたび高さ情報を親サイト(コミュニティサイト)側へ伝える必要があります。アコーディオンメニューを考えると、コンテンツ読み込み時やリサイズ時に加え、アコーディオンの状態が変更されるたびに高さを更新する必要があるかもしれません。その場合、このようなスクリプトを埋め込みます。</script></body>...省略コミュニティサイト側(管理画面)でコンテンツを入力コンテンツのHTMLは、コミュニティサイトの管理画面側で設定します。管理画面上に簡易的なエディタ機能を実装することで対応しました。詳細は割愛させていただきます。脇道にそれますが、当時どんな方々がカスタムブロック機能を開発したか紹介します。Communeの開発チームはアジャイル手法を採用していて、小さくリリースを重ねることで社内外問わず素早くフィードバックを集めることを通して効果的な開発を目指しています。私のチームは、下の組織構成図で言うとWebチーム1です。当時はフルタイムメンバーが4人(チームリーダーの私、テックリード、開発メンバー2人)、パートタイマーが2人(業務委託のシニアメンバーと学生インターン)の計6人でした。開発の中の実装作業は、主に、私と開発メンバー2人、シニアメンバーの4人で進めました。※テックリードはチーム横断で複雑な課題に向き合っており、学生インターンは単一の機能に捉われずさまざまな機能改修を担当しているため、彼らへカスタムブロック機能の開発を渡すのは控えました。当時の開発チームは度重なる組織変更の影響を強めに受けたチームだったので、プロジェクトの初動がとっても不安でした。実装が始まる前にできるだけ早くDB設計やAPI設計を論理的に進めて懸念点を洗い出し、それをシニアメンバーの知見を借りて潰しておくことで停滞せずに済んだと思っています。2024年の4月から5月の2ヶ月で、初回のリリースを終えました。カスタムブロック機能を内製化することで、お客様や運用担当者の手間を減らしたりCommuneのネイティブアプリ版でもコンテンツを表示できるようになりました。(これを活かして新規のお客様を獲得できると嬉しい...営業のみなさんよろしくお願いします!)さらなるプロダクトの成長に向けてカスタムブロックを開発しながら、私たちは新たな課題や可能性に気づきました。今後もプロダクトを進化させるために、熱い気持ちを胸に取り組んでいきます。次のステップとして、もっともっと簡単にコミュニティサイトを彩るコンテンツを作り出せるようにし、コミュニティ運営者たちのアイデア具現化を支えたいです。具体的にこんな機能があったらいいなあ、と。Communeのコミュニティサイトと調和するUI/UXを提供することで、ユーザーがより直感的にコンテンツを作成できる環境を整える。これによって一貫したデザインになりやすくなるので、ユーザーは本質的な部分(コミュニティのコンセプトに合うコンテンツは何か?どんな形式か?などでしょうか)にさらに頭を使えるようになると見込む。デザインシステムを学習したAIを活用し、コンテンツ生成をサポートする機能を導入する。これにより、ユーザーは素早く質の高いコンテンツを掲載できるようになると見込む。今回カスタムブロックのために開発した(HTML/CSS/JSといった)静的コンテンツの保存・配信システムはさまざまな用途に活用できると思っています。思って一部汎用的な作りにしています(という観点をシニアメンバーにいただきました!笑)。今後の機能開発でも再利用しつつ、いろんなところで使っても実用に耐えうるパフォーマンスを維持していきたいです。Roadmapの中で、カスタムブロック機能は今後も重要な位置を占めていくはずです。具体的な内容はここでは控えますが、ユーザーニーズに応じて機能拡張・改善を続けていく予定です。プロジェクトからの学びこのプロジェクトを進める中で、技術面だけでなく、プロジェクト管理や情報連携など学ぶことがたくさんありました。情報を一元管理することの大切さ:DesignDocの作成と定例会議の設置は、特にチーム外メンバーやパートタイムメンバーとの連携を効率化するものでした。うまく連携方法が確立できてない状況であればなおさら、まずはこの資料見ればOK、このミーディング参加すればOK、という決め事で動き出しをスムーズにできました。「今日○○さんがいないから動けない」がなかったのが良かったです。シニアメンバーの知恵を有効活用すること:ただ答えをもらいにいくのではなく、自分の考えや意見を伝えながら相談することで、課題の捉え方や長期的な視点・システム全体を俯瞰した視点で設計を考えることの大切さを認識しました。カスタムブロックには表示対象のユーザーを絞れる機能を付けたのですが、これは既存のユーザーグルーピングの仕組みを利用しました。その際、既存機能の仕様や目的をもう一度おさらいしつつ、カスタムブロックで使い回して副作用が起きないかどうかを考えました。自分自身や社内メンバーからのフィードバックがモチベーションに響くこと:社内ユーザーの声を直接聞くことで、開発者の当事者意識と製品改善へのモチベーションが向上しました。実際に自分たちで触ってあれこれ言ったり、社内のチャットツールにアンテナを広げて生の声を覗くことで「まずい、このままじゃ使いづらい!」と自分ごととして捉えることができました。それによってやる気がアップしたり、時間の許す範囲でエンジニア自ら改善提案してリリースすることにつながりました。組織の枠を超えて融け合いが生まれたこと:(予想外だったのですが)お客様からお礼の言葉をいただいたり、社内のエンジニアメンバーとビジネスサイドメンバーの交流が生まれることもありました。これはすごく嬉しかったです。おかげで、技術だけでなくビジネス面の理解も深まるきっかけになり、また今後何かビジネス面で困ったときに相談する心のハードルが下がりました(逆も然りなはず!笑)。手を動かして学習することの大切さ:(これは個人的な反省なのですが...)クラウドインフラを活用するプロジェクトだったにも関わらず知識が身についた実感がありません。自ら手を動かす機会、頭に汗をかく機会をもう少し作れれば良かった...。専門家に頼ることで効率よくプロジェクトを進められた反面、自分たちの技術的な成長の機会を逃してしまったと感じます。カスタムブロック機能の開発は私たちにとって大きな学びにつながりました。APIだけなのですが、価値を届ける開発ができたこと、そしてさまざまな学びがあったことは貴重な経験でした。技術を探索したくなるのですが、まずは誰かの困りごとを解決しないと、と自分に言い聞かせるきっかけになりました。おわりに今回は、私たちがどうやって機能開発をしているか、どんな課題を解決しようとしているかの一例を紹介しました。今後も、お客様や社内の皆のフィードバックを積極的に取り入れながら、より使いやすく、より便利な機能を作り続けます。Communeを通じて、魅力的で個性豊かなコミュニティサイトがたくさん生まれることを心から楽しみにしています!Communeでは、私たちと一緒に働く仲間を募集しています!少しでもコミューンの開発組織や職場環境に興味をお持ちの方、ぜひカジュアル面談でお話ししましょう。docs.google.comまた、具体的な応募意思がない場合でも、将来的にCommuneでのキャリアを検討している方や、選択肢の一つとしてお考えいただける方は、「キャリア登録」にご登録ください。こんにちは、コミューンの中でSuccessHubというプロダ...2023-11-08コミューンエンジニア的最強CLI環境を作ってみたコミューンに今年の8月にエンジニアとして入社した角田です。コミューンでQAをしています金丸です。(1)引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。