API 設計範式完全指南:REST / GraphQL / gRPC / WebSocket / SSE

比較主流 API 設計範式的原理、優缺點與適用場景,搞懂何時該選 REST、GraphQL、gRPC 或即時通訊


目錄


什麼是 API 範式?

API(Application Programming Interface) 是系統之間溝通的約定。「範式」指的是用什麼風格與協定來設計這個溝通介面。不同範式在「資料怎麼取、誰主動、型別多嚴格、即時性」上有不同取捨。

主流範式大致分兩類:

請求—回應型(client 問、server 答):REST、GraphQL、gRPC
即時/推送型(持續連線、server 可主動推):WebSocket、SSE

沒有「最好的範式」,只有「最適合場景的範式」——這也是本篇的重點。


REST

REST(Representational State Transfer) 是目前最普遍的 Web API 風格:把所有東西當成資源(resource),用 HTTP 動詞操作,以 URL 定位。

核心原則

資源用 URL 表示:     /users/123
動作用 HTTP 動詞表示:
  GET    /users        取得列表
  GET    /users/123    取得單一
  POST   /users        新增
  PUT    /users/123    整筆更新
  PATCH  /users/123    部分更新
  DELETE /users/123    刪除
  • 無狀態(Stateless):每個請求自帶所有必要資訊,server 不保存 session 狀態
  • 以 HTTP 狀態碼表達結果:200 成功、201 已建立、400 請求錯誤、401 未認證、404 找不到、500 伺服器錯誤
  • 資源導向:URL 是名詞(資源),不是動詞(動作)

優缺點

優點 缺點
簡單、直覺、生態成熟 Over-fetching:回傳整個物件,常拿到用不到的欄位
善用 HTTP 快取、狀態碼 Under-fetching:一個畫面要打很多支 API(N+1 請求)
工具 / 文件(OpenAPI)完備 多端點,版本演進需 /v1//v2/
人類可讀、易除錯 沒有強制的型別契約

REST 是 80% 場景的合理預設;多數公開 API(GitHub、Stripe)都是 REST。


GraphQL

GraphQL 由 Facebook 提出:用單一端點,讓客戶端自己描述要哪些欄位,server 精準回傳,解決 REST 的 over/under-fetching。

核心概念

# 客戶端的查詢:只要這些欄位
query {
  user(id: "123") {
    name
    orders(last: 3) {     # 一次查到關聯資料,不必再打一支
      amount
    }
  }
}
  • 單一端點(通常 /graphql),用查詢內容決定回傳
  • 三種操作:Query(讀)、Mutation(寫)、Subscription(即時訂閱)
  • 強型別 Schema:API 的結構由 schema 定義,自帶文件與型別檢查

優缺點

優點 缺點
精準取資料,解決 over/under-fetching 學習曲線、伺服器端較複雜
一次請求取多種關聯資料 HTTP 快取較難(多為單一 POST 端點)
強型別 schema、自帶 introspection 文件 N+1 查詢問題(需 DataLoader 批次解決)
前端不必等後端加欄位 複雜查詢可能拖垮後端,需限制深度/複雜度

適合前端需求多變、關聯資料多的場景(如多種裝置共用一套 API)。


gRPC

gRPC 是 Google 的高效能 RPC 框架:以 Protocol Buffers 定義介面與訊息,透過 HTTP/2 傳輸二進位資料,把「呼叫遠端方法」做得像呼叫本地函式。

核心概念

// .proto:先定義服務與訊息(強型別契約)
service UserService {
  rpc GetUser (UserRequest) returns (UserReply);
}
message UserRequest { int32 id = 1; }
message UserReply  { string name = 1; }
  • Protocol Buffers(protobuf):二進位序列化,比 JSON 小且快
  • HTTP/2:多工、標頭壓縮,支援四種串流(一元、server 串流、client 串流、雙向串流)
  • 強型別契約 + 自動產生各語言 client/server 程式碼

優缺點

優點 缺點
效能高、payload 小(二進位) 瀏覽器不能直接用(需 gRPC-Web 代理)
強型別契約、跨語言自動生成程式碼 二進位不可讀,除錯較難
原生支援雙向串流 生態與工具不如 REST 普及
適合微服務間高頻通訊 對外公開 API 較少用

典型用途:微服務之間的內部通訊(東西向流量),不是給瀏覽器/公開用。


即時通訊:輪詢 / SSE / WebSocket

當需要「server 有更新就讓 client 知道」時,請求—回應型不夠用,有三種做法:

1. 輪詢(Polling)

client 定時打 API 問「有沒有新資料」。

client ──每 3 秒問一次──► server
  • ✅ 最簡單,用一般 REST 就能做
  • ❌ 浪費請求、有延遲;多數請求是「沒有新資料」

2. SSE(Server-Sent Events)

基於 HTTP 的單向推送:連線開著,server → client 持續送事件。

client ──開一條連線──► server ══事件流══► client(單向,server 推)
  • ✅ 比 WebSocket 簡單、走純 HTTP、瀏覽器原生 EventSource、自動重連
  • ✅ 適合只需 server 推的場景:通知、即時報價、AI 串流回覆
  • ❌ 單向(client 要傳資料仍走一般請求)、舊版 IE 不支援

3. WebSocket

升級成全雙工持久連線,雙向即時傳訊。

client ◄══雙向即時══► server(兩邊都能主動送)
  • ✅ 真雙向、低延遲,適合聊天、多人遊戲、協作編輯
  • ❌ 非 HTTP 請求—回應模型,需額外處理連線管理、重連、擴展(sticky session / pub-sub)

三者怎麼選

需求 選擇
偶爾更新、要最簡單 輪詢
只需 server 單向推(通知 / 串流) SSE
雙向即時(聊天 / 遊戲 / 協作) WebSocket

全範式比較

面向 REST GraphQL gRPC WebSocket SSE
傳輸 HTTP/1.1+ HTTP(多為 POST) HTTP/2 TCP(HTTP 升級) HTTP
資料格式 JSON JSON 二進位(protobuf) 任意 文字事件流
通訊方向 請求—回應 請求—回應 請求—回應 + 串流 雙向 server→client
型別契約 無強制(可配 OpenAPI) 強(schema) 強(.proto)
取資料精準度 固定(易 over-fetch) 精準(client 決定) 固定
HTTP 快取 ✅ 佳 ⚠️ 較難 ⚠️
瀏覽器直接用 ❌(需 gRPC-Web)
典型場景 公開 API、CRUD 多變前端、關聯資料 微服務內部 聊天/遊戲 通知/AI 串流

怎麼選

要對外公開 / 一般 CRUD / 想善用 HTTP 快取
  → REST

前端需求多變、一個畫面要拼很多關聯資料、想避免 over/under-fetch
  → GraphQL

微服務之間高頻內部通訊、要效能與強型別、要串流
  → gRPC

需要即時:
  ├─ 只 server 單向推(通知、即時報價、AI 逐字輸出)→ SSE
  └─ 雙向互動(聊天、多人遊戲、協作)→ WebSocket

實務常混用:對外 REST、內部服務間 gRPC、即時功能用 WebSocket/SSE。不必非黑即白。


常見問題

問題 1:REST 和 GraphQL 該選哪個?

REST 適合單純 CRUD、想善用 HTTP 快取、API 結構穩定;GraphQL 適合前端需求多變、一次要取多種關聯資料、想避免 over/under-fetching。前端裝置多樣、欄位需求常變時 GraphQL 較划算。

問題 2:gRPC 為什麼瀏覽器不能直接用?

gRPC 依賴 HTTP/2 的底層控制與二進位 framing,瀏覽器的 fetch/XHR 無法完全操控,因此需要 gRPC-Web + 代理層轉換。所以 gRPC 主要用於後端服務之間,不直接面向瀏覽器。

問題 3:SSE 和 WebSocket 差在哪?

SSE 是單向(server→client)、走純 HTTP、瀏覽器原生支援且自動重連,適合通知 / 串流;WebSocket 是雙向全雙工,適合聊天 / 遊戲等互動。只需 server 推就用 SSE,要雙向才用 WebSocket。

問題 4:為什麼 AI 聊天的逐字輸出常用 SSE?

因為那是單向串流(server 把 token 一個個推給前端),SSE 剛好夠用、又比 WebSocket 簡單、走標準 HTTP。OpenAI 等串流回應多以 SSE 實作。

問題 5:GraphQL 的 N+1 問題是什麼?

一個查詢取列表再取每筆的關聯資料時,可能對每筆都打一次 DB(1 + N 次)。解法是用 DataLoader 之類的批次機制,把多次查詢合併。這與 資料庫索引 的關聯查詢效能也相關。


總結

核心要點

  • 沒有最好的範式,只有最適合場景的範式
  • REST:資源 + HTTP 動詞,簡單通用、快取好,但有 over/under-fetching
  • GraphQL:單一端點、client 決定欄位,解決取資料問題,但快取難、有 N+1
  • gRPC:protobuf + HTTP/2,高效強型別、支援串流,但瀏覽器不能直連,適合微服務內部
  • 即時:單向推用 SSE、雙向互動用 WebSocket、最簡單用輪詢
  • 實務常混用:對外 REST、內部 gRPC、即時 WebSocket/SSE

快速參考

範式 一句話 招牌場景
REST 資源 + HTTP 動詞 公開 API、CRUD
GraphQL client 點菜、單端點 多變前端
gRPC protobuf + HTTP/2 RPC 微服務內部
WebSocket 雙向持久連線 聊天、遊戲
SSE server 單向推 通知、AI 串流

建立日期:2026-06-18

🔗相關文章