📋 目錄
選 API 架構不是在選「最好」的技術,而是在選「最適合你團隊當下狀況」的工具。本文提供一個決策框架,幫你在 REST、GraphQL、tRPC 三條路之間做出不後悔的選擇。
前端工程師為什麼要關心這個選擇
大多數前端工程師每天都在跟 API 打交道,但很少有機會參與「該用什麼 API 架構」的決策。往往是你進公司的時候,架構就已經選好了,你只能適應。
但當你有機會參與這個決策時,問題就來了:GraphQL 很潮,但學習曲線不低;tRPC 寫起來很爽,但只支援 TypeScript;REST 最傳統,但面對複雜前端需求時 fetch 加 Redux 的組合又顯得冗長。
2026 年的現在,這三條路的生態系都已經成熟,選擇反而比過去更困難——因為每一條路都有大量成功案例。本文的目的不是告訴你「哪個最好」,而是提供一個決策框架,讓你根據自己的團隊規模、專案特性、與長期維護成本,做出有根據的選擇。
REST:老牌穩健,但不是萬靈丹
REST 的核心哲學
REST(Representational State Transfer)是一種 API 設計風格,不是標準,所以「RESTful」這個詞在不同團隊的實作裡可能差異很大。但大原則是:每個資源有一個 URL,用 HTTP 方法(GET/POST/PUT/DELETE)表達操作, stateless(無狀態)。
# REST 的 URL 設計風格
GET /users # 取得所有使用者
GET /users/42 # 取得 ID 為 42 的使用者
POST /users # 新增使用者
PUT /users/42 # 更新 ID 為 42 的使用者
DELETE /users/42 # 刪除 ID 為 42 的使用者
REST 的真實優點
1. 學習曲線低,生態系龐大 幾乎所有工程師都熟悉 REST,不論後端用什麼語言、什麼框架,都有成熟的 HTTP 客戶端庫。curl、Postman、瀏覽器 DevTools 都能直接測試,不需要特殊工具。
2. 快取機制天然友善 HTTP 本身就支援快取(ETag、Last-Modified、Cache-Control),CDN 對 REST API 的支援也最完整。如果你的 API 主要用於讀取(read-heavy),REST 的快取優勢很明顯。
3. 適合公共 API 和第三方整合 Stripe、GitHub、Twilio,這些開放平台的 API 都是 REST。因為 REST 的 HTTP 動詞模型已經是業界共識,第三方開發者不需要學任何新東西。
REST 的真實痛點
Over-fetching 和 Under-fetching
// 你只想要使用者的名字,但 REST 一次給你全部欄位
// GET /users/42
// 回傳:{ id: 42, name: "小明", email: "...", createdAt: "...", role: "admin", ... }
// 前端只用了 name,其他統統浪費頻寬
// Under-fetching:一次 GET 不夠,要湊多次
// GET /users/42 → 取得使用者
// GET /users/42/posts → 取得該使用者的文章
// GET /users/42/followers → 取得粉絲
// 前端一個頁面要發 3-5 個 request,並且這些 request 是瀑布式的
這兩個問題在簡單的 CRUD 應用裡不明顯,但當你的前端 UI 需要組合多個資源時,就會變成顯著的效能瓶頸。
如何評估 REST 是否適合你
如果你符合以下大部分條件,REST 是合理的起點:
- 你的前端 UI 主要顯示簡單的 CRUD 資料
- 你有對外的公開 API,需要第三方整合
- 你的團隊成員 HTTP 背景深淺不一
- 你需要良好的 HTTP 快取支援
- 你的專案沒有全端 TypeScript
GraphQL:強大的代價
GraphQL 的核心設計
GraphQL 不是 API 架構,而是一種查詢語言。你的伺服器定義一個 schema(類型系統),客戶端可以指定自己要什麼欄位。伺服器只回你需要的东西,一次請求可以跨多個資源。
# 客戶端發出的查詢
query {
user(id: 42) {
name
posts(first: 5) {
title
createdAt
}
followers(last: 3) {
name
avatar
}
}
}
# 伺服器只回這個形狀的資料,沒有其他東西
GraphQL 的真實優點
1. 精確取得你需要的数据,沒有 Over-fetching
GraphQL 的查詢形狀由客戶端決定,伺服器根據查詢只返回請求的欄位。一個使用者的 profile 頁本來要發 5 個 REST 請求,GraphQL 一個請求就夠。
2. 強型別 Schema,開發體驗好
伺服器明確定義資料結構和關係,GraphQL Codegen 可以根據 Schema 自動生成 TypeScript 類型,前端和後端的介面在編譯期就能發現不一致。
3. 一個 Endpoint,版本控制壓力小
REST 需要 URL 版本(/v1/users、/v2/users),GraphQL 的 Schema 演進可以向後相容,客戶端指定欄位,不會因為新增欄位就壞掉。
GraphQL 的真實代價
1. N+1 查詢問題是頭號敵人
// 如果你取出 100 篇文章,每篇都要查作者
query {
posts {
title
author { name } // 沒有 DataLoader 的話,會變成 1 + 100 = 101 次資料庫查詢
}
}
// 解決方案:DataLoader(批次 + 快取)
// 但這是需要另外實作的基础設施,不是 GraphQL 本身提供的
2. 快取比 REST 複雜太多
HTTP 層級的快取對 GraphQL 無效(因為 query 字串每次都可能不同)。你需要在客戶端實作快取策略——Apollo Client、Relay Modern 這些庫有自己的快取機制,但不是 native HTTP 快取。
3. 錯誤處理模型不同
REST 用 HTTP status code(404、500),GraphQL 即使遇到錯誤仍然返回 200 OK,錯誤在 response body 裡。這讓監控、快取、CDN 整合都比 REST 複雜。
# GraphQL 的錯誤在同一個 response 裡
{
"data": { "user": null },
"errors": [
{ "message": "User not found", "path": ["user"] }
]
}
如何評估 GraphQL 是否適合你
符合以下條件,GraphQL 的價值會很明顯:
- 你的前端 UI 組合多個相關資源,over-fetching/under-fetching 問題明顯
- 你的團隊有能力維護 GraphQL 伺服器(含 DataLoader、N+1 處理)
- 你有 Power User(內部工具、Partner API)需要彈性查詢
- 你願意投資在客戶端快取基礎設施上
tRPC:TypeScript 全端的最短路徑
tRPC 的核心設計
tRPC(Type-safe RPC)不是 API 格式,是一個讓前端直接呼叫後端函式的 TypeScript 庫。只要你在後端定義一個 procedure(類似 API endpoint),前端就可以直接呼叫,享有完整的 TypeScript 類型推導。
// 後端:定義一個 procedure
// server/routers/user.ts
import { z } from 'zod';
import { router, publicProcedure } from '../trpc';
export const userRouter = router({
getById: publicProcedure
.input(z.object({ id: z.number() }))
.query(async ({ input }) => {
return await db.user.findUnique({ where: { id: input.id } });
}),
});
// 前端:直接呼叫,TypeScript 類型自動推導
// 沒有 code generation,沒有 schema 檔,類型從後端直接流到前端
const user = await trpc.user.getById.query({ id: 42 });
// user 的型別會根據後端的回傳值自動推導
tRPC 的真實優點
1. 零 schema 檔,零 codegen,依賴 TypeScript 的結構相容性
GraphQL 需要 SDL(Schema Definition Language)和 Codegen,tRPC 不需要——類型推導完全靠 TypeScript 的 structural typing(結構相容性)。後端改了 return type,前端立刻出現型別錯誤。
2. 開發體驗極佳
前端在呼叫 API 時有完整的自動完成(autocomplete),而且錯誤不是在 runtime 才出現,是在 VS Code 裡寫 code 的時候就出現。
3. 非常適合 TypeScript Monorepo 全端專案
tRPC 在 Next.js 生態系裡非常受歡迎。因為整個 stack 都是 TypeScript,可以直接共享型別,不需要額外工具。
tRPC 的真實限制
1. 只能用 TypeScript,JavaScript 專案完全不考慮
tRPC 的價值建立在 TypeScript 的靜態型別上。如果你的後端是 Java、Go、Python,tRPC 完全不適用。
2. 不是 HTTP API,第三方無法呼叫
tRPC 的 request body 是二進制(Protocol Buffers 或其他),沒有標準的 HTTP endpoint可供外部使用。如果你需要對外開放 API,這條路走不通。
3. 錯誤監控和既有工具鏈整合需要心力
不像 REST 可以直接用現成的 HTTP 監控工具,tRPC 需要自行整合錯誤追蹤(錯誤如何在網路層暴露)、API 文件生成等基礎設施。
// tRPC 的錯誤處理
throw new TRPCError({ code: 'NOT_FOUND', message: 'User not found' });
// 前端收到的錯誤有完整類型
try {
const user = await trpc.user.getById.query({ id: 42 });
} catch (err) {
if (err instanceof TRPCError) {
console.log(err.code); // 'NOT_FOUND'
console.log(err.message); // 'User not found'
}
}
如何評估 tRPC 是否適合你
符合以下條件,tRPC 會讓你工作效率大幅提升:
- 你是 TypeScript Monorepo,前後端都是 TS
- 你用 Next.js 或 Remix 這類全端框架
- 你不需要對外開放 API(純內部使用)
- 你的團隊人數少,希望減少介面定義的維護成本
決策框架:三維評估表
選擇 API 架構時,我建議從三個維度評估:
維度一:團隊 TypeScript 成熟度
| TypeScript 成熟度 | 推薦方案 |
|---|---|
| 全部 TypeScript,全端一體 | tRPC(最有價值) |
| 前端 TS,後端多種語言 | GraphQL 或 REST |
| 大量 JavaScript 積累 | REST(逐步謹慎遷移) |
維度二:前端 UI 複雜度
| UI 複雜度 | 推薦方案 |
|---|---|
| 簡單 CRUD,列表 + 表單 | REST(不需要Over-fetching 解決方案) |
| 中等複雜,3-5 個資源組合 | REST + API Composition(前端自己湊)或 GraphQL |
| 高度複雜,多視圖、多關聯 | GraphQL(Schema 把關係建模清楚) |
維度三:對外開放需求
| 對外開放需求 | 推薦方案 |
|---|---|
| 純內部工具,無第三方整合 | tRPC(最乾淨) |
| Partner API 或公開平台 | GraphQL(彈性查詢)或 REST(容易理解) |
| 公共開發者平台 | REST(生態系最完整) |
2026 年的真實選擇:不是三選一
大多數中型 SaaS 產品的實際架構,是三種並用:
外部用戶瀏覽器/APP
│
▼
Public REST API ← 第三方整合、公共 API
│
▼
GraphQL Gateway ← 組合多個內部服務
│
┌────┴────┐
▼ ▼
服務 A 服務 B
│ │
▼ ▼
tRPC tRPC ← 服務內部通訊,全 TypeScript
(Internal API) (Internal API)
這個架構的核心邏輯:
- REST 用於對外:公共性、第三方整合、易理解
- GraphQL 用於 BFF(Backend for Frontend)層:讓前端靈活組合多個微服務的資料
- tRPC 用於服務間或全端 Monorepo:最小化介面定義成本,享受完整 TypeScript 推導
結語:沒有銀彈,但有最佳路徑
三條路的選擇,本質上是在問三個問題:
- 你的團隊 TypeScript 成熟嗎? → Yes → tRPC 值得評估
- 你的前端 UI 對資料組合的需求有多複雜? → 複雜 → GraphQL 的價值會體現
- 你需要對外開放嗎? → Yes → REST 或 GraphQL;No → tRPC 值得一試
多數新專案的合理起點:Next.js + tRPC 內部 API + REST 對外 API。等你真的有 GraphQL 的需求了(複雜的多視圖、多团队協作前端),再評估加進來。
技術選擇的錯誤往往不是「選錯了」,而是「太早選了太複雜的方案」。從簡單開始,有足夠理由時才升級。
延伸閱讀
- 2026 前端框架比較 — 框架選擇的整體策略
- Bun vs Node.js vs Deno 2026 — Runtime 選擇與 API 的整合
本文是「2026 前端工具選擇」系列文章之一。如果你想看針對特定場景的深入分析(例如「我的新創專案該怎麼選」),歡迎留言告訴我。