account自分の名前や好きな文字を使って自由にカスタマイズして、オリジナルのLINEスタンプを作ることができる「カスタムスタンプ」。購入後は何度でも課金なしでテキストを変更することができます。今回はこのカスタムスタンプのリリースまでの開発舞台裏について、プロジェクトメンバーたちに語り合ってもらいました。本日は「カスタムスタンプ」の開発に関わった皆さんにお集まりいただき、色々とお話を伺っていきたいと思います。皆さんのご担当と、いつからこのプロジェクトに関わったのかを教えていただけますか?Taku:私は「カスタムスタンプ」のプロジェクトにPMとして携わりました。去年の6月に「カスタムスタンプ」の提供が正式に決まり、企画者としてアサインされました。Parth:私は去年の6月からジョインして、CMSのサーバー側を担当しています。イメージ生成の部分も実装しました。張:私は去年6月末まで育休を取っていて、その後このプロジェクトに加わったのは7月です。サーバー側のコンポーネントの設計及び開発を担当しました。ふ:私は「カスタムスタンプ」のiOSクライアントをメインで担当していました。Studio」というサービスの開発チームから、去年の10月に現在のチームに異動したタイミングでジョインしました。「カスタムスタンプ」の開発で取り組んだことを教えてください。Taku:今回のプロダクトでは、クライアント側での対応以外に「カスタムスタンプ」の可変テキスト部分のスタイルを設計するCMSツールの新規開発が必要でした。通常のスタンプだと、入稿する部分の素材はイメージ画像だけなんです。今回は私たちがベースイメージと呼んでいる絵柄とセリフなどが含まれている画像の上に、ユーザーがカスタムできるテキスト部分を載せるレイヤーがもう一枚あって、その二つをマッピングする構造となっています。その可変部分を画像のどこに置くのか、文字のフォント・カラー・サイズなどのスタイルをデザインするために、入稿する前段階で使ってもらうスタンプ製作者のためのツールです。CMSのイメージParth:Inkscapeなどの既存ツールには、私たちのニーズに合っているものがなかったからです。SVGのテキストパス機能を使っているのですが、その部分だけを作るツールがなかったんです。私たちにもバリエーションなどのニーズやルール上の制限などがあったので、自分たちで作ることになりました。最初のプロトタイプは、福岡のエンジニアと2人で1~2週間で作りました。パスを設定すると、イメージ生成ができるものです。実装できてからは、いろいろとビジネス側と企画側で議論できたと思います。Taku:最初にプロトタイプを見たときは、本当に感動しました。テキストパスが動く部分とフォントなどが変えられる可変部分、機能の基礎部分を確認するための技術検証ができて、初めて実現の可能性を感じました。Parth:自分で操作できるものとして、世の中にはオープンソースもあるんですけど、商品として使えるか、制作会社や個人のクリエイターやデザイナーたちが扱えるかなどを考えると、現実的には厳しいので自分たちで作るしかないと判断しました。CMSツールの実装で苦労したことはありますか?Parth:一番難しかったポイントはSVGからPNGに変換するときに、タイ語のフォントでいろいろ問題が発生したことですね。Taku:今回はカスタム部分をユーザーに入力してもらうので、可変するテキストのフォントをスタンプごとに指定していますが、他の言語よりタイフォントのみの問題が多くて苦労しました。Parth:普段意識してない文字コードとグリフの関係を調べるのが大変でした。タイ語で2つや3つの文字コードが重ね合わせてレンダリングするときにその座標が組み合わせによって違うが、開発側で全然気づいてなくて、座標が間違って変な結果になっていたとか。文字コードが一つでフォントによって複数のグリフを返すとか、条件判断のコードがそれで無限ループになってしまったとか。CMSサーバーとイメージ生成部分などを担当したParthさんTaku:それに気づいたのがQAの時でした。私たちはタイ語がわからないので、今回は最初のCMSを設計する時点で、ビジネス側やローカルのメンバーと取り組んでいました。ところが、最後のQAの段階で現地の人にβ版を触ってもらった時に、文字の点の位置がずれていたり、こちらではとても気づきにくいバグがたくさん判明してきたんです。Parth:利用しているライブラリの中身もいろいろ修正しましたね。張:今年の1~2月に広範囲にQA始めてからですよね。バグが次々と見つかって、QAのスケジュールやリリースを後ろ倒すことも視野に入れざるを得ない状況でした。Parthさんともう一人のエンジニアが、ライブラリのオープンソースの中身にいろいろ踏み込んで、なんとか解決してくれました。Taku:CMSは自分たちが使いやすかったという感覚くらいしかありませんでした。言語によるフォントリストの並び替え変更など、いろいろと意見が出てきました。開発からフィードバックはもらっていたんですが、こだわらなくてはいけない部分がたくさんあって、最初のリリースでどこまで対応するのか議論を繰り返しました。Parth:タイフォントで現地の要望が実現できるのか、かなり議論しましたね。Taku:日本のビジネス側とは直接やりとりしていたこともあり、あまりトラブルはありませんでしたね。Parthさんに追加対応の工数とビジネス側のニーズの優先度を聞いて調整しながら、リリーススケジュールを決めていました。Parth:SVGを設定するときに、いろいろバグりましたけど(笑)。Taku:はい、この可変部分をどう移動させるのか、スタートやエンドの色を区別して、文字を選んだときにちゃんと全体が移動できるようにするとか。最初は回転もさせたいと言われたんですけど、回転は難しいので最初のリリースのタイミングではやらないことにしました。Parth:欲しい機能はまだたくさんありますよね。ユーザーが設定できるテキスト領域の仕様は、どのように決めたんですか?Taku:最初に販売されたパッケージは日本語だと4文字なんですが、実は4文字と決まっているわけではないんです。スタンプによってデザインが違いますし、文字数も違います。最初は4文字にしたんですけど、スタンプごとに設定ができます。台湾も4文字だったので、自分の名前が5文字以上の担当者に全然使えないと言われました(笑)。Parth:それは英語でアルファベット使いたいときですね。漢字なら大丈夫なんですけど。タイ語・インドネシア語があります。最初のカスタムスタンプのデザインは韓国でやっていたのですが、そもそもCMSが読みにくいところもあり、ビジネス側が現地に行って説明して回ったのですが、結構時間的にギリギリでした。Parth:今回、スタンプのデザインは韓国側のデザイナーが作ったので、ローカライズされたセリフが長いとか、可変する部分は言語によって文字数が同じでも幅が異なるなど、自分だけじゃ予想しにくい言語によるデザインイシューが出てきたんです。Taku:汎用的なセリフがないとユーザーが買ってくれないだろうと思ったので、セリフの選定の部分に関してはビジネス側が頑張っていたと思います。普通のスタンプは一回買ったら終わりなんですけど、今回はカスタムテキストを変更した後、もう一度ダウンロードする必要があります。そこは今までにない仕様なので、エラー対応が多く大変でした。クライアント側での開発内容を教えてください。ふ:クライアント側のタスクとしては、ベースの画像とテキスト部分をサーバーから別々にとってきて合成する処理をしたり、それを保存して表示させたり、テキストをセットする画面を作ったりしています。大変だったのは、可変テキスト部分の暗号化ですね。ユーザーの会話情報の一部という認識なので、暗号化の必要がありました。文字を変えるたびに新しいハッシュを生成して、スタンプの送受信にはそれだけを利用します。受信したクライアント側ではそのハッシュをもとに画像を取得して、はじめて文字が分かる様になっています。実装する上では、文字数カウントも工夫しました。iOSのカウント方式とサーバー側のカウント方式、Androidのカウント方式は全部違います。タイ語が大変でした(笑)。あと特殊なUnicodeや絵文字など、目に見えるものが実際のカウントと違ったりすることもたくさんありました。4文字と表示されるのに、サーバー側に送信すると文字数のバリデーションに引っかかってエラーで返されるんです。仕様を合わせるためにサーバー側と調整してコードを書き直しました。Parth:今はサーバー側のコードに統一してますね。タイのフォントは、組み合わせて最後に構成された文字を初めて一つの文字として認識するんですが、見た目だけでは4文字より長くてもカウントしたら4文字になっちゃうことがあるんです。今回のプロジェクトでは最初から最後までタイ語についての知識不足に振り回された状態で大変でした。Taku:リリース時は、日本、タイ、台湾、インドネシア(グローバル)向けの4パッケージを発売しました。タイ語のスタンプに関しては、メンバーのタイ文字に対する知識が不足していたために、タイ文字の処理の大変さが事前に想像できていませんでした。最初のプロトタイプのタイミングでも、基本的には可変部分の実現性をメインに検討していたので、フォントの部分がそんなに大変なことになるとは思いませんでしたね。セキュリティを担保するために意識したことはありますか?張:私は主にサーバー側のAPIの提供、カスタムテキストの暗号化などバックエンドの部分を担当していました。APIを通じてクライアントとやりとりして、テキストのプレビューや保存、商品を購入する通常の流れなど、既存のものを修正しながら新しいAPIを作っています。今回のプロジェクトの特徴の一つとして、プライバシーの保護と機能要件を両立させる必要があります。通常、ユーザーの全ての会話内容は暗号化されていますが、今回のカスタムテキストはデータの定義上、会話内容ではなく、描画のためのデータです。カスタムスタンプは、一度買ってしまえば後で何回でもテキストを変えられるという点では普通のトークと変わりません。コミュニケーションの一貫と考えられるので、商品の商品性を損なわない上で、セキュリティを保つ必要がありました。このトレードオフの中で社内の色んな部門とコンセンサスを取りながら進めていました。カスタムスタンプのテキスト部分を暗号化する時と復元する時は、どちらも同じ暗号キーが必要になります。社内のアプリケーションセキュリティチームと、技術的な観点でその暗号キーを変えなくていいのか、という議論をかなり密に行いました。結論としてはキーを変えなければならないということになりました。一回漏れてしまったら、特定の状況で二つのユーザーのスタンプのやりとり(テキスト)が分かってしまうんですね。それを防ぐために、キーをリフレッシュする仕組みを新たに作り、暗号化と復元のための中間の処理なども高速化するためにキャッシングを使って、正確性と高速性の両方を保つ設計をしました。サーバー側で工夫したことはありますか?張:これまでの商品はキャッシュをフルに活用することで高速化を図ったんですけど、今回はユーザーがテキストをいつでも何にでも変えられるじゃないですか。そのためキャッシングはほぼ効かないんですね。常にリアルタイムでレンダリングすることになるので、サーバーのスケーリングの議論はかなりやりました。ロードテストではまだそんなにリクエストを出してないのに、サーバーがいきなり死んでしまうこともありました。Parth:ありましたね。張:そのときParthさんは、このくらいのサーバーならこのくらいのリクエストをさばけるといったことを調査していました。この商品が大ヒットしたとして、どのくらいのリクエストが来るか想定した上で、サーバーの量を3倍にしましょう、と提案してくれました。Parth:そうそう、リリースの4日前に追加することを決めました。張:リリースした直後が一番危ないんですね。通常ならこれくらいで大丈夫だろうと思っていても、リリースする直前にMAXと考えていた量をさらに倍にする。コストにはなるんですけど、リリースして一週間くらいして落ち着いたらサーバーを撤去すればいい。いう考えがサーバー側には常にあります。実際に、過去にそれをやらなかったせいで、リリース時に障害が起きたこともあります。お話を聞いてきましたが、他にも今回の開発でこだわったことはありますか?張:特定のユーザーから大量のリクエストを送られてしまうなどのabusingにも、ユーザー単位でメモリ上にリミットを設けてますね。Limiting機能があります。ダミーのクライアントを使って悪さしているんじゃないかというリクエストを制限してます。ふ:クライアントも、ほぼありえないと思うんですけど、そのエラーをサーバーから受け取ったらエラー画面に遷移します。張:Parthさんは今回初めてサーバーを一から作って、しかも、LINEのパートナーの認証など今までShopチームではやったことがない前人未到の開発をいろいろ経験してきたんですよね。Parth:CMSやイメージ生成など、全部ゼロから始まった開発だったので、オペレーション上のやりとりも大変でした(笑)。ふ:あと、クライアントを作る際に、エンジニアぽいこだわりみたいなものがいくつかあって。バリデーションの時に文字入力を受け取りながら裏側で文字数をカウントしたり、サーバーに対してバリデーション投げたりするんですけど、それを常に送りながらバリデーションに対して完了ボタンが押せないバックグラウンド処理などを行っています。iOSには「キーボードの設定を名前モードにしておくとデフォルトでiPhoneに設定した名前が出てくる機能」というのがあるんですが、それを入力時に適用したり、名前入力画面に移動するとキーボードが自動的に表示されたり、といったUXが良くなるようなマニアックなこだわりを入れました。iOSクライアントを担当したはるふさんParth:あと、今回の開発ではSVGをPNGに変換させる機能を作ったことが、とてもいい勉強になりました。ふ:クライアントでいえば、スタンプショップの画面は7年前からほとんど変わってこなかったんですね。今回新しい名前入力BOXなどが追加されたんですけど、かなり古いコードで動いている状態でした。そこに機能を足すのが大変で、結構コードを書き変えました。問題が起こらなかったのは奇跡ですね。張:スタンプと絵文字の画像は専用のサーバーに提供されています。今回のカスタムスタンプもそのサーバーに変更を入れる必要がありました。そのサーバーは長い間コードの追加ばかりでリファクタリングが全く足りていなくて、カオス状態に近いくらいコードが汚かったんです。その状態のコードに更に新しいロジックを入れることになるので、実際に修正を入れようとしたParthさんともう一人の担当の方は結構困った顔をしていましたね。きっかけなので、崩れ落ちるくらいだったのを、今回の開発で一気にサーバー自体を書き直しました。一時的な対応ではなく、ちゃんと望ましい状態にすることができ、おかげで後続の開発も効率化ができました。どんな人でも最初に開発する時に、最終的に一番良い形の実装は何なのかまでは想像できないはずです。今後新しい開発がある場合、その時の要件に基づいて常に最適な状態に修正することが期待されると思います。きっかけがある度に、なるべく頑張ってリファクタリングすることは必須なコストであり、スケジューリングの際も考慮すべきだということは、今の開発チームの共通認識であると考えています。Parth:既存のスタンプショップ自体もいろいろ最適化されました。スタンプはZIPに圧縮してダウンロードされるんですけど、今回はカスタムスタンプのベース画像だけをZIPにまとめてダウンロードする仕様になっています。それを解凍して、それぞれの画像に対してテキストを合成します。既存部分が最適化されているところが大変でした。私もクライアントチームに入ったばっかりだったので、そもそも圧縮されてることに驚きました。ベース画像に対しても処理を入れたんですけど、結構大きくリファクタリングしましたね。Stickerにリファクタリングしました。すごく時間はかかるんですけど、みんな楽しんでやっていました。リファクタリング大好きです(笑)。最後に、今後「カスタムスタンプ」で改善していきたいことや取り組みたいことはありますか?Taku:今はセリフの一部が可変で且つ40種類ぐらいのスタンプが同じテキストで適応していますね。今後はスタンプに入っているすべてのセリフを一言づつ変えられるように、スタンプそれぞれに違うテキストが設定できるようにサポートするとか、いろんな可能性があります(笑)。多くのバリエーションあるカスタムスタンプをリリースできるようにして行きたいです。張:40枚のスタンプごとにカスタマイズできる文字の長さなどあるので、複雑度は上がるけど、サーバー側としてAPIやクライアントの設計の段階で考慮しなければいけないですね。ある程度の拡張性も持った上で、今回の初期のリリースのために作りやすくしました。拡張については、設計の中に思想として膨らんでいます。Taku:個別のテキスト設定については、最初の段階でも話していましたね。プロトタイプの段階では、難しいと判断して絞ってました。Parth:改善したい部分はありますね。Twitterで少し流行っていたんですけど、テキスト部分を何回も変えて使う、大喜利みたいなスタンプの楽しみ方が生まれていて。いう使い方も参考にして、もっと面白いスタンプを作れると思っています。今のスタンプはフォントが一つしか選択できなくて、そのフォント以外サポートされていない文字がある。言語によってフォントが違うので、フォントを増やして選べる機能を作りたいですね。ふ:今回実装したのは「複数の画像を組み合わせて、1つのスタンプとして扱う」という機能なので、かなり拡張性のあるものです。同じ仕組みを名前以外にもカスタマイズできたら面白いと思っています。張:今まではスタティックなイメージからアニメーションやサウンドなど、商品のバリエーションの相乗効果を図ることが多いですけど、今回もそういった拡張がありそうですね。Taku:カスタムスタンプを、現在展開している音声、アニメーション、ポップアップスタンプにまで拡張する可能性が十分考えられますね。どれも大変そうですけど(笑)。Developers。