— なぜ私たちは WebView という選択に至ったのか(ShenDesk の実装経験より)
モバイルアプリにオンラインカスタマーサポートを導入する過程で、私は長期間にわたる技術選定の試行錯誤を経験しました。
当初は、いわゆる「技術的に理想的」とされる選択肢にも強く惹かれていました。
たとえば、
- UI はすべてクライアント側で自作し、私は API だけを提供することで最大限の自由度を確保する方法
- あるいはネイティブ体験を重視し、公式 SDK を組み込む方法
しかし、プロジェクトが進むにつれて、技術的に美しいだけの設計では、実際のビジネス要件を満たせないという現実に直面します。
特に、業界の異なる多くの顧客から実際のフィードバックを得る中で、「何を選ぶべきか」という判断基準そのものを見直す必要があると感じました。
私は EC、教育、SaaS、金融、公共・行政など、10 以上の業界の顧客と直接対話を重ねました。
その実装経験と現場の声を通じて、次のような重要な判断軸が明確になってきました。
技術選定における 5 つの現実的な制約
1. リリースまでのスピードが最大のボトルネック
多くの企業は、1〜2 週間以内にサポート機能を本番投入したいと考えています。
既存のアプリ業務フローを壊さず、
「短期間で・痛みなく導入できるか」が最優先事項でした。
2. UI の一貫性はユーザー体験の核心
ユーザーは、カスタマーサポート画面が
- アプリの外に飛ばされないこと
- デザインや操作感がアプリ全体と統一されていること
を強く期待しています。
明らかに異質な第三者 UI は、信頼感を大きく損ないます。
3. 求められる機能レベルは想像以上に高い
単なるテキストチャットでは不十分です。
- 画像・ファイル送信
- AI ボット連携
- 待ち行列・担当者振り分け
- 会話評価(CSAT)
これらは「あると良い」ではなく、最初から求められる前提機能です。
4. 運用・保守に割けるリソースは限られている
多くのチームは少人数です。
通信、状態同期、再接続などを含むフルスクラッチのサポート機能を長期的に維持するのは、現実的に高負荷です。
5. マルチプラットフォーム対応は見えないコスト
Android / iOS / H5 それぞれで UI を自作すると、
- 開発期間は単純に倍増
- 将来の保守コストはさらに膨張
「自由度の高さ」が、そのまま技術的負債になります。
私たちが辿り着いた結論
これらを踏まえ、私の中で技術戦略は明確になりました。
高度に制御可能で、迅速に統合でき、機能が成熟しており、かつクロスプラットフォームで再利用できる方式こそが、ほとんどの企業にとって最適解である。
十分な柔軟性(スタイルカスタマイズ、テーマ設定、コンテキスト透過)を持ちつつ、
キュー制御、担当者割り当て、履歴管理、通知、評価といった安定したサーバー側基盤が不可欠です。
ShenDesk では、まさにこの思想を前提に設計を行っています。
本記事の後半では、
アプリにカスタマーサポートを組み込む主要な技術パターンを比較し、
なぜ最終的に WebView 埋め込み方式を選択したのかを、
実装上の落とし穴やコード例とともに詳しく解説していきます。
1. SDK 統合 or API + 自前 UI?
SDK 統合や API + 自作 UI は、特定の高度カスタマイズ要件では意味を持つ場合もあります。
しかし、実際の導入現場では多くの隠れたコストとリスクを伴います。
❌ SDK 統合方式でよくある問題
「ネイティブ SDK は最高の体験を提供する」と語られることは多いですが、
実際のエンジニアリングでは、複雑性と長期的な保守負担を招くケースが少なくありません。
以下では、開発・性能・互換性の 3 つの観点から見ていきます。
1. 接続が複雑で、プラットフォーム依存が強い
SDK は通常、Android / iOS それぞれで個別に組み込みが必要で、
依存関係、権限設定、ライフサイクルフックなど、多くの前提条件を伴います。
Android でよくある例:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET"/>
<application>
...
<activity android:name="com.sdk.chat.ChatActivity"
android:theme="@style/SDKTheme"
android:exported="true"/>
</application>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ChatSDK.initialize(
apiKey = "your_key",
userId = user.id,
context = this
)
}
問題点:
- SDK アップデートのたびに初期化仕様が変わる
- 内部 Service / Broadcast がアプリ挙動に影響
- ProGuard 設定漏れによるリリースクラッシュ
2. サイズ・パフォーマンス負荷
多くの SDK は以下を内包しています。
- WebSocket クライアント
- 画像キャッシュ
- ローカル DB
- UI リソース一式
結果として:
- APK サイズが 3〜5MB 増加
- 起動時間が延びる
- 依存ライブラリ競合・Dex 制限
3. UI のカスタマイズ性が低い
SDK の多くは閉じた UI モジュールです。
val intent = Intent(this, ChatSDK.getChatActivityClass())
startActivity(intent)
Fragment のように埋め込めず、
DOM レベルでの制御もできません。
- アプリとデザインが乖離
- 多言語対応が困難
- UX が制限される
4. デバッグが困難でブラックボックス
E/ChatSDK: WebSocket failed to connect.
E/ChatSDK: Internal message parser error.
- ソースコードに入れない
- 状態遷移が見えない
- 難読化されている場合も多い
5. 業務ロジックとの連携が困難
たとえば、
「閲覧中の商品情報に応じて適切な担当者へ振り分けたい」
という要件は、SDK ではほぼ実現不可能です。
ChatSDK.sendMessage("{ \"type\": \"product\", \"id\": \"123456\" }")
構造化メッセージはサポートされないケースが大半です。
👋 最後に
現在も ShenDesk は進化を続けています。
もしあなたがライブチャットシステムを開発・導入した経験があるなら、
リアルタイム更新、負荷分散、柔軟なデプロイをどのように実現したか、ぜひ教えてください。
一緒に語りましょう。
🚀 ぜひお試しください
🌐 公式サイト:https://shendesk.com
📘 ドキュメント:https://docs.shendesk.com
オンラインでも、自分のサーバーでも、無料で体験できます。
セルフホストやリアルタイム通信、カスタマーエクスペリエンス改善に関心のある開発者からのフィードバックをお待ちしています。


