Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。
この記事は、「WYSIWYGウェブページビルダーを支える技術的マジックの裏側」の書き起こしです。
@Hal:みなさん、こんにちは。私たちは、Merpay Growth Platform Frontendチームです。今日はFigmaのようなWYSIWYGツールの使いやすさにコンポーネントの合成や条件付きレンダリングのような強力な機能を追加した、私たちが取り組んでいるプロジェクトについて紹介します。
始める前に、このプロジェクトを支えるチームを紹介します。
まず、Tech LeadのArvinです。彼は、チームをリードし、メンバーの生産性を維持すると同時にこのプロジェクトや他のプロジェクトに貢献しています。
次に、Benです。彼は私たちのWYSIWYGツールにおける高度な機能の多くを概念化し、ソースコードに大きく貢献しツールのユーザーであるマーケターをサポートしています。
Jasは比較的新人ですが、基盤技術の大規模なリファクタリング、アーキテクチャの変更など、私たちのソフトウェアの多くの面を担当しています。
私は、チームのマネージャーであるHalです。問題解決に向けて関係者と話し合い、チームの成功に必要なことを調整します。
今日は私たちのウェブページビルダーである「Engagement Platform Pages」というツールについて、皆さんとともに興奮を分かち合いたいと思います。
このプロジェクトに取り組むことは毎日ワクワクしますし、とてもチャレンジングでもあります。フロントエンド技術の基本を深く掘り下げなければならないので、私たちは多くのことを学びました。
その前に@arvinhvからこのプロジェクトの背景とここまでの経緯について説明してもらいます。
@arvinhv:まず、数年前を振り返ると、このスライドにあるキャンペーンページを作成するためには、マーケター、デザイナー、エンジニアの多大な労力が必要でした。マーケターがキャンペーンのテーマや内容を決め、デザイナーがUIをデザインし、CSSやHTMLを使ってゼロからウェブページを作ります。最後にエンジニアがJavaScriptを組み込み、統合されたページに仕上げます。
平均して月に30のキャンペーンページの作成が必要です。ほぼ毎日、1ページを作成します。この3者が関与するので、何度もやり取りをしなければならず、全員に負担がかかっていました。
みんなの仕事をもっと楽にする方法はないのでしょうか?エンジニアとして問いかけ、この状況を改善するために、私たちは第1世代のCMSツールを作りました。
このツールは、JavaScript、HTML CSSをコンポーネントにカプセル化することでデザイナーが必要なコーディングの量を最小限に抑えることができます。
このツールはエンジニアによって始められたもので、このプロジェクトにリソースを投入できるよう、チームのロードマップの一部にしました。
このツールがどのように見えるかをお見せしましょう。これが第1世代ツールのユーザーインターフェースです。右側にプレビューエリア、左側に設定フォームがあります。
あらかじめ組み込まれたコンポーネントのリストから、コンポーネントの追加ができます。それがプレビューエリアに表示されるため、すぐに見た目を確認できます。また、コンポーネントのフォームからコンテンツの色の変更もできます。
つまりページを作成する方法は、これらのコンポーネントの設定であり、ページを構成するコンポーネントはいくつでも追加できます。
ここでわかるように、新しいコンポーネントは前のコンポーネントの後に追加されています。このツールはわかりやすいもので、これまでデザイナーがHTMLやCSSを書いていた問題が解決されました。マーケターが自分でウェブページを作成できるようにもなりました。
第1世代のCMSツールですが、すでに私たちの目的を達成しているように見えます。マーケター、デザイナー、その他ページを作る必要がある誰でも自分でページを作ることができるようになりました。
シンプルで、基本的にページ内にあるものが画面に表示され、各要素は設定可能なビルドを使って表せます。うまく機能していますよね。
他に何が必要だったのでしょうか?最初は、これは究極の解決策だと思ってました。しかし、多くの社内メンバーであるユーザーがツールを使い始めるにつれて、いくつかの問題に気づきました。
システムにコンポーネントを追加し、コンポーネントフォームにフィールドを追加していくと、ページを作成するときに巨大なフォームが表示され、ユーザーが修正したいフィールドを見つけるのが難しくなります。
第2に、新しいコンポーネントやコンポーネントの新しいフィールド追加など、新しい要件をサポートするために、エンジニアリング能力が必要でした。例えばコンポーネントにペインティングフィールドを追加するといった小さな変更の場合でも、リリースが必要であり、全てのパイプラインの通過が必要で、スピードも遅くなります。
さらに、要求がPMからエンジニアに、エンジニアから最終的な実装へと伝えられるプロセスでコミュニケーションギャップが生まれます。
各ステージごとのバイアスによりアウトプットが不正確になり、エンジニア、デザイナー、PMがフィードバックややり取りの調整に多くの時間を費やしていました。エンジニアとしてここは改善したいと思いました。
そこで思いついたのが、ツールをもっとカスタマイズできるようにして、マーケターがエンジニアに依存せず、エンジニアはシステムの改善に集中できるようにしたらどうだろうということでした。
そのやり方で、マーケターはこのシステムを使ってビジネス要件に対処できます。そうすれば頻繁なやり取りは不要になります。
この例を使って、考え方を説明しましょう。つまり、マーケターが既存のコンポーネントに新しい種類のログを追加したい場合、第1世代のシステムでは、チケットを作成し、エンジニアがチケットにスケジュールを設定し、リリースしなければいけません。
このプロセスには小さな変更であっても通常数日はかかりますよね。なぜなら、要件を確認し、検証し、マーケターの承認が必要だからです。
では、マーケターがページから直接何かを選択し、新しいログやアクションをページに追加できるようにしたらどうでしょうか?プロセスの生産性がそれによって大幅に向上します。
このアイディアを練るために1クォーターを費やし、アプリケーションのモックアップを作成しプレゼンテーションを行いました。
今でも覚えているのは、ミーティングを開いたり、ごはんを食べながらのOpendoorを開催したりして、多くのメンバーを集め、この新しいCMSツールの必要性を伝えていきました。なぜなら、これらの技術が大きな影響をもたらすと信じていましたし、非常にエキサイティングでもあったからです。
新しいメンバーが加わり、2、3ヶ月に及ぶ活発な開発を実行し、第2世代のシステムが完成しました。
この第2世代のものは大きく刷新されたものです。システムのコンポーザビリティやエディターの動き方、見た目を改善しました。スライドスクリーンショットをご覧いただければ、その違いはおわかりいただけるかと思います。
@jasにこの新しい変更について詳しく説明してもらいましょう。
@jas:コンポーザビリティについては、粒度を細かくすることで、柔軟性が増し、多様なコンポーネントを作成できるようになります。
以前は、コンポーネントを編集する際に二つの課題に直面しました。まず機能ごとに別々のコンポーネントを作成することは、拡張性も効率性も良くありません。
例えば、機能やスタイルが異なるボタンごとにエンジニアが開発し、エディターで使用する前にさまざまなプロセスを経る必要がありました。時間がかかりました。
二つ目の課題は、単一のカラムLayoutにしか対応ができないことです。
第2世代のエディタでは、四つの基本コンポーネントを提供します。Layout、Text、Image、Markdownです。これらのコンポーネントを組み上げることで、エディターは開発やリリースを待つことなく、複雑な機能を持つコンポーネントを作成できます。スライドの右側は、コンポーネントのスタイルコントロールパネルです。
スタイルコントロールは、Tail window CSSを使用しています。つまりCSSの機能のほとんどをコンポーネントに適用してより複雑なビジュアルスタイルやLayoutを作成できます。
さらに、異なるページの状態やユーザーの環境に応じて、異なるコンテンツを表示できるロジックコントロールコンポーネントも追加し、それによって、よりパーソナライズされた体験を提供できています。それはWHENコンポーネントです。例えばユーザーがログインしていないときにログインボタンを表示をしたり、APIのレスポンスに応じたコンテンツを表示できます。
最後に、アクションコンポーネントも導入しました。アクションコンポーネントは、ダイアログの表示やAPIのリクエストなど、多くのアクションをサポートしています。
では、実際の画面を見てみましょう。エディタを使って簡単なページを作り確認してみましょう。
これがエディタです。まず、ADDボタンをクリックして、メニューからLayoutコンポーネントを選択しましょう。
このLayoutをお客さまがウェブブラウザを使用するときに表示されるコンテンツのをコンテナとして使用します。ですので、これはウェブコンテンツと名付けます。
続いて、QRコードのコンポーネント、Textのコンポーネントを挿入して、お客さまにアプリのダウンロードとインストールを求めるブロックを作成しましょう。
次に、アプリを利用するお客さまのためのコンテンツを保持するために別のLayoutコンポーネントを追加します。
モバイルコンテンツと名付け、その中にボタンを設置しましょう。全てのコンテンツを作成した後、WHENコンポーネントを使用してそれらをラップし、さまざまな環境に基づいてそれらを表示する条件を追加します。
これはアプリのお客さま向けです。そこで、モバイルアプリを使用している条件を適用します。
ウェブブラウザを使っているお客さまのためにもう一つWHENコンポーネントを追加しましょう。ブロックの一つだけを表示して結果を確認してみましょう。
これはアプリのお客さまが見るものです。
こちらがウェブブラウザのお客さまに押されるものです。コンディションレンダリングができました。
ログインしていないお客さまに対してのみ、両方のコンテンツを表示したいとしましょう。これを実現するにはアクションコンポーネントを使用して、AuthサービスにAPIのリクエストを行い、お客さまのログイン状態を確認します。
その後、全てのコンテンツをゲストユーザー条件付きのWHENコンポーネントでラップしてログインしていないお客さまだけにコンテンツを表示できます。最後にお客さまがクリックしたときに、ログイベントを拡張するためにボタンにアクションを追加します。
@Hal:おそらく、これまで持っていたCMSツールよりも直感的になっていると思います。しかし、そんなに簡単に学べそうには思えません。
機能が多くて、マーケターはどうやってツールを使い始めたのでしょうか?
@ben.hsieh:おっしゃる通りです。プロジェクトをローンチしたあと、マーケターの方々からたくさんの問い合わせが来ました。そのため、日々ハンズオンのセッションを行いました。たくさん開催しましたね。
これはみなさんにツールの使い方を学んでいただき、同時にフィードバックをもらうためでもあります。このときに、ユーザビリティが問題なのだと気づきました。
第2世代のシステムを作り始めたときに、私たちは柔軟性を考慮していました。それは、マーケターの方々にパワーを与えたかったからです。
彼らが、エンジニアからの手伝いをもらわなくてもできるようにしたかったからです。しかし、システムの柔軟性を高めると、適切に使うためには技術的な知識が必要になります。なので、その二つのバランスが必要になります。
ページエディターを作る上で、かなり労力を割いています。今日はいくつか例を使いながらその道筋を紹介していきたいと思います。
まず、例としてLayoutシステムをあげます。
ここでは、Tail window CSSを使って柔軟なLayoutシステムを実現しています。ページエディターは、どんなLayoutでも作れるようになっています。CSSを裏側で使っているからです。
ですが、前提条件として、Tail window CSSクラスネームをかけるようにする必要があります。
これがすごく大きな問題です。マーケターの方々は、CSSの書き方がよくわからないからです。初めて紹介したときにマーケターの方々はすごく混乱しました。
そこでお手伝いをするために、CSSクラスネームビューを小さなものに分けたり、色付けをしたりしたらどうかと考えました。
それによって、使い方がわかり、クラス名を適切なフィールドに入力できるようにし、適切なクラスネームを把握できるようにしようとしました。
新しいバージョンをマーケターに見せたときに、また混乱が起こりました。
ドキュメンテーションを見て、クラスネームを少しずつ把握する必要があったからです。
そこで、もう一つ、新しいアイディアを見つけました。これは素晴らしいアイディアだと思いました。例えば IntelliSense のようなものを作ることです。デベロッパーはIntelliSenseが大好きだからです。
クラス名などが入力するごとに自動補完で表示されるようにしたら、マーケターはドキュメンテーションを調べなくてもいいじゃないかと思いました。
このスクリーンショットのように、何かを入力すると、クラス名が表示されるだけではなく、クラスネームの説明も表示されるようになります。そうすることで、マーケターは使いやすくなりますし、Tail window CSSを少しずつ使いながら学べると思いました。
これはすごく有効だと考えたんです。しかし、驚いたことに実際にマーケターの方々に試してもらったところ、また混乱してしまいました。
「CSSを知らなくてはならない」という前提は変わらないからです。クラスネームを作るプロセスが簡単になったとしても、使うための知識は必要です。なので、根本的な問題は完全に払拭できていませんでした。
その結果、Figmaあるいはブラウザウェブツールなどを作っていくことにしました。このソリューションは受け入れられ、上手く機能しました。
マーケターは、このGUIのLayoutエディタでやり取りをすると、裏側ではこの入力をTailwind CSSのクラスネームに変換しているんです。なので、元々のソリューションを諦めているのではなく、エディターの裏側に隠れているのです。
このGUIのLayout Editorはまだまだ制約があって、このクラスネームを使うことで、できることもあるけれども、GUIエディターできないこともあるので、エンジニアの方々は事前に設定をする上で使ったり、緊急の要件を満たすために使うことができます。
つまり、いろいろな技術レベルに応じて、いろいろな使い勝手が生まれます。
もう一つの例がCondition Systemです。先ほど申し上げましたように、私たちの新しいシステムは、条件に応じてコンテンツのレンダリングができます。その裏側ではJavaScriptのExpressionを使って、一部のコンテンツをレンダリングするかを判断しています。
これを作るときにこれらのコンディションはすごくシンプルで、JavaScript Expression1〜2行だろうと思っていました。このスクリーンショットにあるように、store?.user?.profileのようなものだと思っていました。
ですが、実際に幅広く使い始めてみたところ、この条件がかなり複雑で、10行以上になってしまうことがよくありました。
場合によっては、nullの検証やフォーマットのコンバージョンをしなければならなくなり、Expressionがさらに長くなります。
コンポーザビリティを増やすことによって、コンポーネントがネスティングできるようになります。そうすると、コンディションがあまりにも複雑になってしまって、マーケターは自分で設定ができなくなり、エンジニアが関わる必要が出てきます。
私たちのソリューションは、Layerとシステムとほぼ同じですが、複雑な部分をラップする作り方にしています。
よって、マーケターは機能へシンプルにアクセスできるようにしています。例えば、コンディションについてですが、マーケターに自分たちで条件を書くのではなく、GUIツールを作って一般的に使われているコンディションをテンプレートとして提供しています。
マーケターは、いくつかのコンディションから選びます。例えば、iOSアプリを利用するお客さまにだけ示したいときには、iOSアプリを利用するお客さまを選びます。そうするとGUIフィルターで条件を自動入力できます。
また、テンプレートの引数も提供していますので、多くの場合、柔軟に使えるようになっています。例えば、コンテンツとして、お客さまが販売しているものの個数に応じて表示する場合、マーケターがテンプレートを選ぶと別のフィールドが表示されて個数を入力するようになります。マーケターは、数字を入力し、テンプレートの条件を完成させます。
二つ目は、ネステートコンフィギュレーションレンダリングです。ここでもマーケターの方々が、再使用可能なコンポーネントを自分たちで作れるようにしています。
第1世代ではエンジニアがコンポーネントを書く必要がありましたが、エディターでコンポーネントを作って、彼らが再使用して、カスタム変数を使って振る舞いをカスタマイズしたり、見た目をカスタマイズできるようにしています。複雑なページのコンピレーションを将来的には再利用して、一部カスタマイズできるようになります。
二点目ですが、コンセプトは大体同じです。高い柔軟性から始めて受け入れられるレベルまで徐々に調整をしていきます。
これが、例です。高い柔軟性を提供した結果、ユーザビリティの問題がありました。しかし、高い柔軟性は開発の初期段階ではいい選択肢だと思います。オンデマンドで将来的にいろいろなレベルの柔軟性を提供できるからです。
2点目として、柔軟性とユーザビリティの問題に対応するためには、まずは小さなPoCからはじめることをおすすめします。巨大なソリューションから始めるべきではありません。マーケターが気に入ってくれるかどうかわからないからです。
IntelliSenseと同じように労力を割いているけれども、うまく使えなかったケースもあり得るからです。
3点目として、WYSIWGエディターを作るときには課題があることを覚えておいてください。技術的なものだけではなくて、さまざまな課題が発生します。ですが、1回やると、すごく学んですごく成長できると思います。
@Hal:教訓が、いくつかあります。まず問題があったときに、再発しそうな問題の場合は、効率を改善するやり方を考えてください。
例えばテンプレートの作成や自動化したり、この仕事をしなければならない人をエンパワーしたりすることを考えてください。2点目としては、エンジニアは興味のあるプロジェクトに関わった方が効率が上がります。
まとめです。
問題があり、そこに対してのソリューションを作りました。つくってみると拡張性や利用する人の能力における問題が新たに発生し、そこに対応するためにソフトウェアを再開発する必要がありました。良いバージョンのものを半年で作り、ツールの使い方をマーケターにオンボーディングし、新しいツールの確固たるファンデーションを作り、テクノロジーの使用を拡大しようとしています。
ご清聴いただきましてありがとうございました。何か新しいものを学び、勇気を持ってぜひ仕事の仕方の改善に役立てていただければと思います。