GraphQL 伺服器架構指南:初學者入門

更新日期: 2025 年 3 月 19 日

當我們選擇使用 GraphQL 作為 API 架構時,會發現有不同的架構模式可供選擇,而這將直接影響到我們的伺服器設計與維運成本。

與 REST API 不同,GraphQL 提供更靈活的資料查詢方式,但其架構可以分為 單一應用伺服器模式(One Server Model)GraphQL Gateway 模式(Two Server Model),兩者各有適用場景。

本文將帶你了解這兩種架構模式的運作方式、適用場景,以及該如何選擇最適合你的專案。


GraphQL 伺服器是什麼類型的伺服器?

GraphQL 伺服器是一種 應用伺服器(Application Server)

它的主要工作是處理客戶端的 GraphQL 查詢(Query)、變更(Mutation)、訂閱(Subscription),並從資料庫或其他 API 來源擷取數據,最後將結果回傳給客戶端。

簡單來說,GraphQL 伺服器的角色與傳統的 REST API 伺服器 相似,但它的查詢方式更加靈活,讓客戶端可以自訂請求的數據,而不是只能依賴固定的 API 端點。

GraphQL 伺服器的運作方式

當客戶端發送 GraphQL 請求時,GraphQL 伺服器的處理流程如下:

  1. 接收請求:透過 /graphql 端點接收查詢或變更請求(類似 REST API 的 /api/users)。
  2. 解析請求:檢查查詢的格式是否正確,並依據 GraphQL Schema 確定請求內容。
  3. 執行查詢 / 變更:透過 Resolvers(解析器)查詢資料庫或呼叫其他 API 來獲取數據。
  4. 組合回應:將獲取的數據轉換成符合 GraphQL 查詢的格式,回傳給客戶端。

這使得 GraphQL 伺服器能夠靈活地回應不同的請求,避免 REST API 常見的「過多請求(Overfetching)」或「請求不足(Underfetching)」問題。

GraphQL 伺服器的技術選擇

不同技術棧都有對應的 GraphQL 伺服器實作,例如:

Node.js 環境

  • 使用 Express + Apollo Server 搭建 GraphQL API,例如:
const { ApolloServer, gql } = require("apollo-server-express");
const express = require("express");

const typeDefs = gql`
  type Query {
    hello: String
  }
`;

const resolvers = {
  Query: {
    hello: () => "Hello, GraphQL!",
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

const app = express();
server.applyMiddleware({ app });

app.listen(4000, () => console.log("Server is running on http://localhost:4000/graphql"));
  • 這個伺服器會在 /graphql 端點提供 GraphQL 服務,類似傳統的 REST API 端點。

Django 環境

  • 使用 Graphene-Django 來建立 GraphQL API:
from graphene_django.views import GraphQLView
from django.urls import path

urlpatterns = [
    path("graphql", GraphQLView.as_view(graphiql=True)),  # 提供 GraphQL API
]
  • Django 本身是一個應用伺服器,而 Graphene 讓它能夠處理 GraphQL 查詢,使 Django 能夠同時支援 REST API 和 GraphQL API。

Hasura(自動產生 GraphQL API)

  • Hasura 是一種特殊的 GraphQL 伺服器,它直接將 PostgreSQL 資料庫轉換為 GraphQL API,而不需要開發者手動撰寫後端程式碼。
  • 這意味著,當你建立好資料表後,Hasura 會自動提供 GraphQL API,像這樣:
query {
  users {
    id
    name
    email
  }
}
  • Hasura 適合需要快速開發的專案,特別是如果你的後端主要是資料庫 CRUD 操作,而沒有太多自訂的業務邏輯。

GraphQL 伺服器與 HTTP 伺服器的關係

GraphQL 伺服器本質上仍然是一個應用程式,它通常會運行在一個 HTTP 伺服器 上,透過 /graphql 這樣的 API 端點對外提供服務。例如:

  • Node.js 環境 → 使用 ExpressKoaFastify 作為 HTTP 伺服器,然後在上面運行 Apollo Server 或其他 GraphQL 伺服器。
  • Python 環境 → 使用 Django(Gunicorn、Uvicorn)Flask 作為 HTTP 伺服器,然後透過 Graphene 提供 GraphQL API。
  • Hasura → 本身內建 HTTP 伺服器,可以直接作為 GraphQL 伺服器使用,無需額外的應用伺服器。

這樣的架構使得 GraphQL 伺服器可以與現有的 Web 應用整合,或者作為獨立的 API 服務提供數據。

flowchart LR
    A([客戶端<br>React/Vue/iOS/Android]) --> B([Web 伺服器<br>Nginx/Apache])
    B --> C([GraphQL 伺服器<br>Apollo Server/Hasura])
    
    subgraph 應用伺服器層
        D1([用戶服務<br>Node.js/Express])
        D2([訂單服務<br>Python/Django])
        D3([產品服務<br>Go/Gin])
    end
    
    C --> D1
    C --> D2
    C --> D3
    
    D1 --> E1[(MongoDB<br>使用者資料)]
    D2 --> E2[(PostgreSQL<br>訂單資料)]
    D3 --> E3[(MySQL<br>產品資料)]
    
    C --> F[(Redis<br>快取查詢結果)]

單一應用伺服器模式(One Server Model)

在這種模式下,GraphQL API 直接內建在應用伺服器內,不需要額外的 GraphQL Gateway。

因此,它與傳統 REST API 的架構相似,只是 API 端點從 /api/users 變成 /graphql

架構概覽

flowchart LR
    A([客戶端]) --> B([應用伺服器<br>Django / Express / NestJS]) --> C([資料庫])

特點

僅需一個應用伺服器,GraphQL API 直接在這個伺服器上運行。
與 REST API 架構類似,方便從 REST 過渡到 GraphQL。
適合小型或中型專案,因為所有 GraphQL Resolvers 都直接在應用伺服器內處理。

範例:Django + Graphene

假設我們使用 Django + Graphene 來建立 GraphQL API,那麼 Django 既是應用伺服器,也是 GraphQL 伺服器:

from django.http import JsonResponse
from graphene_django.views import GraphQLView
from django.urls import path

urlpatterns = [
    path("graphql", GraphQLView.as_view(graphiql=True)),  # Django 直接提供 GraphQL 服務
]

這種方式下,我們的 GraphQL API 直接由 Django 負責,與 REST API 的架構沒有太大區別,且維護成本低,非常適合初學者或小型專案。


GraphQL Gateway 模式(Two Server Model)

在這種模式下,GraphQL API 由**獨立的 GraphQL 伺服器(Gateway)**負責處理,而應用伺服器則專注於業務邏輯。

架構概覽

flowchart LR
    A([客戶端]) --> B([GraphQL Gateway<br>Hasura / Apollo Server])
    B --> C([應用伺服器<br>Django / Express])
    C --> D([資料庫])

特點

GraphQL 伺服器不處理業務邏輯,僅負責 API 查詢與請求轉發。
應用伺服器專注於業務邏輯,如身份驗證、付款處理等。
適合大型專案或微服務架構,可以整合多個後端服務的數據。

為何使用這種架構?

如果你的 GraphQL API 需要:

  1. 即時訂閱(Subscriptions) → 例如 WebSocket 支援(Hasura)。
  2. 多數據源整合 → 例如從多個後端服務(Django、微服務)獲取數據。
  3. 自動產生 API → 例如 Hasura 可直接將 PostgreSQL 轉換為 GraphQL API,節省 API 開發時間。

範例:Hasura + Django

假設我們使用 Hasura 作為 GraphQL Gateway,而 Django 負責業務邏輯,那麼架構如下:

flowchart LR
    A([客戶端]) --> B([Hasura<br>GraphQL Gateway])
    B --> C[(PostgreSQL)]
    B --> D([Django<br>REST API, 處理業務邏輯])
  • Hasura 提供 GraphQL API,處理一般的查詢與變更。
  • Django 處理複雜的業務邏輯(如身份驗證、付款等)。
  • Hasura 可透過 Remote Schema 或 Webhooks 呼叫 Django,讓 GraphQL API 具備更強大的業務邏輯處理能力。

這樣一來,GraphQL API 的開發變得更快,而 Django 只在必要時被調用,大幅提升系統的可擴展性。


如何選擇適合的架構?

選擇單一應用伺服器模式還是 GraphQL Gateway 模式,取決於你的專案需求與規模。

需求單一應用伺服器模式GraphQL Gateway 模式
專案規模小型 / 中型大型 / 微服務
架構簡單度簡單複雜
開發速度快速上手需要學習 Hasura 或 Apollo
維護成本需要管理多個伺服器
即時訂閱(WebSocket)❌ 支援較弱✅ 強大
多數據源整合❌ 需要手動處理✅ 內建支援

適用場景

如果你的專案較小,建議使用「單一應用伺服器模式」,例如 Django + Graphene,這樣你只需要維護一個應用伺服器,不會增加額外的架構複雜度。

如果你的專案較大,或希望加快開發速度,可以考慮「GraphQL Gateway 模式」,例如 Hasura + Django,讓 GraphQL 伺服器自動處理 API,而 Django 則專注於複雜的業務邏輯。


結論

  • 使用 REST API → 只需要 一個應用伺服器,如 Django + Apache
  • 使用 GraphQL API
    • 如果是內建 GraphQL API(Graphene-Django / Apollo Server)仍然只需一個應用伺服器
    • 如果使用 GraphQL Gateway(Hasura / Apollo Federation) → 需要 兩個應用伺服器,一個是 GraphQL 伺服器,一個是應用伺服器。

📌 如果你是初學者,且專案規模不大,建議從「單一應用伺服器模式」開始,這樣能減少開發與維護成本,並讓你更快熟悉 GraphQL 的概念。

📌 如果你想要建立更具彈性的 API 或處理即時數據,可考慮「GraphQL Gateway 模式」,透過 Hasura 或 Apollo Gateway 來整合不同的後端服務,提高開發效率。

希望這篇文章能幫助你更清楚地理解 GraphQL 伺服器的架構選擇,讓你能根據自己的需求選擇最適合的解決方案!

Similar Posts