「我這個功能該用 REST 還是 GraphQL?該用 WebSocket 還是 SSE?要不要開 webhook?」

這個問題很多人問,但網路上找到的答案通常分散在 5-6 篇文章裡——每篇講一種協定,沒有放在一起比較的「全景」。讀完還是不知道自己的場景該選哪個。

這篇就是來解這個問題的。6 種協定放同一頁、同一張比較表、同一個決策樹。讀完你會知道:你的 use case 該選哪個、為什麼。


一張表先講結論

協定方向連線型態格式瀏覽器原生支援Streaming適合場景
RESTClient → Server短連接,每次重連JSONCRUD / 對外 API / 公開 API
GraphQLClient → Server短連接JSON⚠️ subscription 需 WS前端要彈性查詢 / 多端 client / over-fetching 嚴重
gRPC雙向長連接 HTTP/2Protobuf❌(要 grpc-web 轉)✅ 雙向 streaming微服務之間 / 高效能內部通訊
WebSocket雙向長連接 TCP自訂 / JSON✅ 雙向聊天 / 協作編輯 / 即時遊戲 / 競標
SSEServer → Client長連接 HTTPtext/event-stream✅ 單向通知推送 / 進度條 / Dashboard / AI chat streaming
WebhookServer → 你的 server對方主動打你JSONN/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 callWebhook
主動方對方
觸發你決定何時打事件發生時對方自動打你
即時性看你 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 端。所以第一次選的時候多想一下,比之後後悔便宜很多。