GraphQL 查詢語言 (GraphQL)

核心定義

GraphQL 是由 Facebook 提出的 API 查詢語言 + 執行環境

核心理念

客戶端決定要什麼資料,伺服器只回應請求的欄位。

設計導向 REST GraphQL
對象 Resource Query
URI 多個資源 URI 單一 /graphql
決定方 伺服器定義欄位 客戶端決定欄位

四大核心特徵

1. 單一端點(Single Endpoint)

REST:    GET /users/123
         GET /users/123/orders
         GET /users/123/profile

GraphQL: POST /graphql  (所有操作都走這一個)

2. 精準查詢(Client-driven query)

客戶端只拿需要的欄位 → 解決 REST 的 over-fetching / under-fetching。

3. 強型別 Schema(Strongly Typed)

type User {
  id: ID!
  name: String!
  email: String
  orders: [Order!]!
}

type Order {
  id: ID!
  total: Float!
}

type Query {
  user(id: ID!): User
}

4. 單一請求跨多資源(Nested Queries)

一次查詢「使用者 + 訂單 + 通知」,REST 需要多次 call。


三種操作類型

操作 對應 HTTP 動詞類比 用途
Query GET 讀取資料
Mutation POST/PUT/DELETE 修改資料(新增、更新、刪除)
Subscription 長連線推送 即時資料推送(類似 WS/SSE)

Query 範例

query {
  user(id: 123) {
    name
    email
    orders {
      id
      total
    }
  }
}

回應精確對應:

{
  "data": {
    "user": {
      "name": "Bohr",
      "email": "bohr@example.com",
      "orders": [
        { "id": "101", "total": 250 },
        { "id": "102", "total": 100 }
      ]
    }
  }
}

Mutation 範例

mutation {
  createUser(name: "Bohr", email: "bohr@example.com") {
    id
    name
  }
}

Subscription 範例

subscription {
  newOrder {
    id
    total
  }
}

底層通常走 WebSocket。


優點

優點 說明
精準取數 客戶端控制欄位 → 避免 over/under-fetching
強型別 Schema 即文件,前後端契約清楚
一次取多資源 減少 API call 次數,降低延遲
彈性演進 欄位可標 @deprecated,新舊客戶端共存

缺點與對策

1. 伺服器實作複雜

對策:Query complexity / depth limit、rate limiting、persisted queries

2. N+1 問題 ⚠️

N+1 的成因

因為 resolver 是 field-based,巢狀查詢會導致:

1 次查詢:SELECT * FROM users LIMIT 10
N 次查詢:SELECT * FROM orders WHERE user_id = ?  (每個 user 跑一次)
總計:1 + N 次資料庫查詢

對策

方案 原理
DataLoader 批次合併同一 tick 內的查詢成 IN (...) 查詢
Resolver 層 join 直接在 resolver 做 JOIN / aggregation
Persisted queries 只允許白名單 query,可預先最佳化

3. Cache 機制弱

REST 靠 URL 當 cache key(CDN/瀏覽器),GraphQL 所有查詢都 POST 到同一個 /graphql,body 不同回應不同 → 無法直接用 HTTP cache。

對策


REST vs GraphQL 決策

場景 選 REST 選 GraphQL
對外公開 API、需廣泛相容
依賴瀏覽器/CDN HTTP caching
簡單 CRUD
行動裝置 / 弱網路 / 節省流量
前端畫面複雜、需組合多資源
前端需求常變、後端不想改 schema
多團隊對重疊資料做廣泛查詢

面試中如何談 GraphQL

  1. 定位:前端需要靈活查詢或一次取多種資源時用
  2. 典型案例
    • 行動裝置 / 弱網路 → 只抓需要欄位
    • 複雜 Dashboard → 一次查詢解決
  3. 比較 REST
    • REST → 資源固定、快取好、簡單直觀
    • GraphQL → 查詢彈性,但後端要處理查詢成本與 cache
  4. 設計考量
    • 資料結構複雜 + 前端需求常變 → GraphQL 有優勢
    • 簡單 CRUD 或高效快取場景 → REST 更直接
面試建議

在固定需求的面試題中,GraphQL 的優勢較不明顯。
只在問題明顯聚焦於查詢彈性 / over-fetching 時才提出 GraphQL。


Simplification-with-exceptions

邊界情況

  • GraphQL 不是只能配 HTTP:Subscription 通常走 WebSocket
  • GraphQL 也能 GET:query 短時可走 GET /graphql?query=...,支援 CDN cache
  • 不一定比 REST 快:後端若沒優化 resolver,可能比 REST 慢很多
  • 不適合檔案上傳:multipart 需額外規範(graphql-multipart-request-spec)