「我這個功能該用 REST 還是 GraphQL?該用 WebSocket 還是 SSE?要不要開 webhook?」
這個問題很多人問,但網路上找到的答案通常分散在 5-6 篇文章裡——每篇講一種協定,沒有放在一起比較的「全景」。讀完還是不知道自己的場景該選哪個。
這篇就是來解這個問題的。6 種協定放同一頁、同一張比較表、同一個決策樹。讀完你會知道:你的 use case 該選哪個、為什麼。
一張表先講結論
| 協定 | 方向 | 連線型態 | 格式 | 瀏覽器原生支援 | Streaming | 適合場景 |
|---|---|---|---|---|---|---|
| REST | Client → Server | 短連接,每次重連 | JSON | ✅ | ❌ | CRUD / 對外 API / 公開 API |
| GraphQL | Client → Server | 短連接 | JSON | ✅ | ⚠️ subscription 需 WS | 前端要彈性查詢 / 多端 client / over-fetching 嚴重 |
| gRPC | 雙向 | 長連接 HTTP/2 | Protobuf | ❌(要 grpc-web 轉) | ✅ 雙向 streaming | 微服務之間 / 高效能內部通訊 |
| WebSocket | 雙向 | 長連接 TCP | 自訂 / JSON | ✅ | ✅ 雙向 | 聊天 / 協作編輯 / 即時遊戲 / 競標 |
| SSE | Server → Client | 長連接 HTTP | text/event-stream | ✅ | ✅ 單向 | 通知推送 / 進度條 / Dashboard / AI chat streaming |
| Webhook | Server → 你的 server | 對方主動打你 | JSON | N/A(不是瀏覽器用的) | ❌ | 第三方事件通知 / 異步整合 |
每一行接下來會展開講「什麼時候用 / 不該用」。
REST:絕大多數場景的預設選擇
特性:HTTP 動詞(GET / POST / PUT / DELETE)+ 資源 URL + JSON。
該用的場景:
- 對外公開 API(給第三方接的)
- CRUD 為主的後台 API
- 工程師團隊規模 < 50 人
- 你還沒有特殊需求
不該用的場景:
- 前端需要查很彈性的資料形狀——應該選 GraphQL(避免 N+1 個 endpoint)
- 微服務之間高頻呼叫——應該選 gRPC(JSON 太肥、HTTP/1 太慢)
- 需要 server 主動推資料——應該選 SSE 或 WebSocket
REST 是「你不知道該用什麼的時候,先用 REST」。它的成熟度、debug 難度、工具鏈支援都是其他協定難匹敵的。
GraphQL:前端要彈性查詢
特性:單一 endpoint、用 query language 描述要拿什麼欄位。
該用的場景:
- 多端 client(web / iOS / Android)但每端要的欄位不同
- 後端 over-fetching / under-fetching 嚴重(例如要 user 資料還要回他全部 order list)
- 前端工程師多過後端、希望前端能主導查詢結構
不該用的場景:
- 公開 API(GraphQL 的 schema introspection 是攻擊面,且 query complexity 不好限制)
- 服務間通訊(過於 chatty + 多了一層 schema 維護成本)
- 團隊小、後端不熟 GraphQL(比 REST 多很多運維坑)
特別注意:GraphQL 的 N+1 問題沒解 dataloader 會炸。Subscription 需要 WebSocket 支撐。
gRPC:服務間通訊的高效率選擇
特性:Protobuf 二進位編碼 + HTTP/2 + 雙向 streaming。
該用的場景:
- 微服務之間高頻呼叫(壓測上 Protobuf 比 JSON 小約 50%、快約 30%)
- 需要強型別 schema 約束
- 跨語言服務間調用(Go ↔ Python ↔ Java 統一介面)
不該用的場景:
- 瀏覽器直接打——gRPC 不能在 browser 原生跑,要走 grpc-web 轉一層(增加複雜度)
- 服務數少(< 5 個)——gRPC 的學習成本大過效能 leverage
- debug / 抓封包頻繁——Protobuf 不是人讀的,比 JSON 難 debug
實務做法:對外用 REST / GraphQL,對內用 gRPC——這是大多數團隊的最佳組合。
WebSocket:雙向即時通訊
特性:HTTP upgrade 後升級成 TCP 雙向連線。
該用的場景:
- 真正雙向:聊天室、協作編輯(Figma / Google Docs)、即時遊戲、競標
- 客戶端要主動 push 訊息給 server(不只接收)
不該用的場景:
- 單向 server → client 推——應該選 SSE(更輕、HTTP 原生、自動重連)
- 大多數通知 / 狀態推送——SSE 夠用,不需要 WebSocket 的雙向能力
- 需要透過 corporate proxy / firewall(WebSocket 比 HTTP/SSE 容易被擋)
WebSocket 常常被過度使用——很多人「需要即時推送」就上 WebSocket,但其實 SSE 在 90% 場景夠且更簡單。
SSE(Server-Sent Events):單向推送的最佳解
特性:HTTP 長連接、text/event-stream 格式、瀏覽器自動重連。
該用的場景:
- 訂單狀態推送(追蹤頁進度條)
- Dashboard 即時更新(股票、監控)
- 通知推送(信件、訊息提醒)
- AI chat streaming(ChatGPT / Claude 介面就是 SSE)
- 長任務進度回報
不該用的場景:
- 雙向溝通(用 WebSocket)
- 需要 binary 資料(SSE 純文字)
SSE 是 2024+ 被嚴重低估的協定。AI streaming 的興起讓它再度被重視——你寫 LLM-based 應用幾乎一定會用到。
Webhook:當第三方要主動通知你
特性:對方的 server 主動打你的 endpoint,攜帶事件 payload。
該用的場景:
- 第三方服務通知你某個事件發生(Stripe 付款成功、GitHub PR merged、Slack 訊息送達)
- 你不能也不該 polling——對方 API rate limit、polling 頻率不夠即時、對方不希望你一直敲
不該用的場景:
- 你想「主動拿資料」的場景——這是 API call,不是 webhook
- 內部服務之間(用 message queue / event bus 比 webhook 更可靠)
實作必備:HMAC 簽名驗證、立刻回 200 + 把工作丟 queue、idempotent 處理(同一個事件可能重複收到)。詳見 44-webhook-design。
Webhook vs API:Push 跟 Pull 的根本差異
很多新手搞不清楚 webhook 跟 API 的差別。本質是方向相反:
| 維度 | API call | Webhook |
|---|---|---|
| 主動方 | 你 | 對方 |
| 觸發 | 你決定何時打 | 事件發生時對方自動打你 |
| 即時性 | 看你 polling 頻率 | 接近即時 |
| 對方 server 負擔 | 高(你一直敲) | 低(事件驅動) |
| 你需要 | client 程式碼 | server endpoint + 公開可達 |
該 polling API 的場景:
- 你的 server 不能對外公開(沒固定 IP / 在公司內網)
- 對方沒提供 webhook
- 事件頻率高到 webhook 反而塞爆
該用 webhook 的場景:
- 對方提供且你能接(有公開 endpoint)
- 事件相對稀疏(不是每秒幾百個)
- 你想要接近即時的反應,不想付 polling 成本
混合做法很常見——webhook 通知 + API 拉取詳細資料。例如 Stripe webhook 告訴你「付款成功」,你再用 API 拉付款明細。
「我該選哪個」決策樹
你要做什麼?
├─ 提供公開 API 給第三方接
│ └─ REST(成熟度最高,第三方最不會抱怨)
│
├─ 後端 API 給自家 web/app 用
│ ├─ 多端 client + 欄位需求差異大 → GraphQL
│ └─ 標準 CRUD → REST
│
├─ 微服務之間互打
│ ├─ 高頻、要強型別、要效能 → gRPC
│ └─ 服務少(< 5 個)→ REST 內部用就好
│
├─ 即時通訊
│ ├─ 雙向(聊天 / 協作 / 遊戲)→ WebSocket
│ └─ 單向(推播 / 進度 / streaming) → SSE
│
└─ 第三方事件通知
├─ 對方主動通知 → Webhook
└─ 你主動拉 → REST polling
90% 的選型可以套這棵樹解決。剩下 10% 是邊界 case(例如 polling 跟 webhook 混合用、SSE 跟 WebSocket 並存),那是 case-by-case 的工程判斷。
反思一句話
通訊協定的選型不是「哪個最強」,是「哪個最 fit 你的場景 + 團隊熟悉度」。
REST 不是「最弱」,是「最通用」。gRPC 不是「最強」,是「在對的場景才強」。GraphQL 不是「現代化」,是「解決特定問題」。
選錯協定的成本很高——遷移要重寫大量 code、要重訓 team、要動到 client 端。所以第一次選的時候多想一下,比之後後悔便宜很多。