提示:本网站现在为维护调试状态

GraphQL vs REST:7つの視点から深く比較

Choyeon
Choyeon
2026年9月19日 1 分で読了 405 閲覧
492 字 2,808 文字 更新日 2026年11月8日
GraphQL vs REST:7つの視点から深く比較
目次

GraphQL vs REST: 7-Dimension Deep Comparison

GraphQL is marketed as REST killer but each excels in different scenarios. Blind GraphQL adoption brings N+1, complexity explosion, cache invalidation; pure REST suffers over/under-fetching. Compare rationally.

Reference Architecture and Complexity Guards

GraphQL exposes one endpoint accepting declarative queries fetching exactly requested fields - fixing REST's "20 endpoints to assemble" and "80% fields unused" problems. But gateways MUST enforce complexity analysis, field-level auth, and depth limits.

import express, { Request, Response } from "express";
import { graphqlHTTP } from "express-graphql";
import { buildSchema, parse, visit, Kind } from "graphql";

const app = express();
app.use(express.json());

const schema = buildSchema(`
  type User { id: ID!; username: String!; orders(limit: Int = 10): [Order!]! }
  type Order { id: ID!; total: Float!; items(limit: Int = 20): [OrderItem!]! }
  type OrderItem { productId: ID!; qty: Int!; price: Float! }
  type Query { user(id: ID!): User; users(limit: Int = 20): [User!]! }
  schema { query: Query }
`);

class ComplexityGuard {
    private costs: Record<string, number> = { orders: 5, items: 2, users: 10 };
    private readonly MAX = 150;
    analyze(query: string): { total: number; exceeded: boolean } {
        const doc = parse(query); let total = 1;
        visit(doc, {
            Field: (node) => {
                const base = this.costs[node.name.value] || 1;
                const args = Object.fromEntries((node.arguments || []).map(a => [a.name.value, (a.value as any).value]));
                const mult = args.limit ? Math.ceil(Number(args.limit) / 10) : 1;
                total += base * mult;
            },
        });
        return { total, exceeded: total > this.MAX };
    }
}

const root = {
    user: ({ id }: { id: string }) => ({
        id, username: `u${id}`,
        orders: ({ limit = 10 }: any) => Array.from({ length: limit }, (_, i) => ({
            id: `o${i}`, total: 99.5 + i,
            items: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, k) => ({ productId: `p${k}`, qty: k + 1, price: 9.9 })),
        })),
    }),
    users: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, i) => root.user({ id: String(i + 1) })),
};

const guard = new ComplexityGuard();
app.get("/rest/users/:id", (req: Request, res: Response) => {
    res.json({ data: { id: req.params.id, username: `u${req.params.id}` }, _links: { orders: { href: `/rest/users/${req.params.id}/orders` } } });
});
app.use("/graphql", (req: Request, res: Response, next) => {
    const q = (req.body?.query) || (req.query.query as string) || "";
    const r = guard.analyze(q);
    if (r.exceeded) return res.status(400).json({ error: `Complexity ${r.total} exceeds cap 150` });
    res.setHeader("X-GraphQL-Complexity", String(r.total));
    next();
}, graphqlHTTP({ schema, rootValue: root, graphiql: process.env.NODE_ENV !== "production" }));

app.listen(3000, () => console.log("[compare] REST+GraphQL on :3000"));

Seven Dimensions Side by Side

Dimension REST (JSON:API style) GraphQL Winner
Network efficiency Multi-trip over/under fetch Single exact fetch, POST hurts CDN REST wins simple/GraphQL complex views
Frontend DX New fields = new backend endpoint Self-service + introspect TS types GraphQL
Backend evolution Versioned routes /v1 /v2 Smooth deprecation but resolver complexity explodes REST
HTTP caching Native GET support Requires persisted query IDs + custom REST
Type safety Needs OpenAPI codegen Strong schema + SDK generation built in GraphQL
Security surface Standard CRUD auth Depth/complexity/batch injection guard needed REST smaller surface
Tooling ecosystem OpenAPI/Postman mature Apollo Studio/GraphiQL mature Tied

Best Practices

Decision tree: Team runs BFF with fast frontend iteration → GraphQL. Inter-service calls or pure resource CRUD → REST. Hybrid (GraphQL BFF composing multiple REST microservices) is today's major-factory mainstream pattern.

X微博Telegram

筆者について

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

コメント (6)

0 / 3000
测试小瓢虫
测试小瓢虫2026年9月11日

好文!但是我觉得第三部分那个消息队列选型对比表有点偏向 Kafka 了,RocketMQ 在事务消息这块其实优势挺明显的。

自由撰稿人阿秋
自由撰稿人阿秋qiuwrites.blog2026年9月11日

建议加一下关于幂等性的讨论,现在的分布式系统里这个真的太重要了,很多坑都是没处理好幂等导致的。

东京留学僧
东京留学僧2026年9月11日

补充一点:实际使用中如果遇到 MySQL 的 8 小时超时问题,可以在连接串里加 autoReconnect=true 参数,虽然官方不推荐但挺好用的。

机器学习萌新
机器学习萌新2026年9月11日

有个小问题:你文中用的是 @Async 注解,这个默认用的是 SimpleAsyncTaskExecutor,生产环境是不是最好手动配一个线程池?

奶茶味程序媛
奶茶味程序媛2026年9月11日

代码示例里那个 SQL 查询是不是应该加个 LIMIT?不然数据量大的时候全表扫描会很慢哦。

咖啡与代码
咖啡与代码2026年9月10日

受益匪浅,感谢大佬分享!

関連記事

JWT 認証セキュリティ + OAuth2 vs SAML

JWT 認証セキュリティ + OAuth2 vs SAML

JWT脆弱性と対策:alg混乱攻撃、鍵総当たり、KIDインジェクション、リプレイ対策。さらにOAuth2+PKCE、OIDC、SAML2.0の3プロトコル多次元比較。

1 分で読了
Prompt Engineering 入門:Few-Shot + CoT + 構造化出力

Prompt Engineering 入門:Few-Shot + CoT + 構造化出力

Prompt Engineering体系入門:3つのコアテクニック——Few-Shot例示学習でドメインスタイル注入、Chain-of-Thoughtで複雑推論誘導、JSON Schema強制構造化出力で下流システム連携。実テンプレートとアンチパターン集付き。

1 分で読了
CQRS + Event Sourcing アーキテクチャ解説

CQRS + Event Sourcing アーキテクチャ解説

高度な分散パターン:CQRS読み書き分離でクエリ性能、Event Sourcingはイベントを唯一の源として監査+時間遡行。一貫性・スナップショット・べき等とアンチパターンを解説。

1 分で読了
FastAPI クイックスタート - 高性能 REST API の構築

FastAPI クイックスタート - 高性能 REST API の構築

FastAPI は現代の Python Web フレームワークの中でも傑出しており、型ヒントによる自動ドキュメント生成、非同期サポート、Node.js 並みのパフォーマンスを提供します。この実践ガイドでは、ルート定義、リクエスト検証、依存性注入、データベース統合を含む完全な CRUD API をゼロから構築します。

この記事は閲覧パスワードが必要です 4 分で読了
Astro 静的サイト:アイランドアーキテクチャ & コンテンツコレクション

Astro 静的サイト:アイランドアーキテクチャ & コンテンツコレクション

Astroの革新:最小JSのアイランドアーキテクチャ、型安全なMarkdown/MDXのコンテンツコレクション、ゼロJSの高速静的サイト構築。

1 分で読了
テストピラミッド:単体/結合/E2E 比率と実践

テストピラミッド:単体/結合/E2E 比率と実践

テストピラミッド体系解説:下層 単体テスト(多数・高速・Mock分離)、中層 結合テスト(実DB/メッセージ協調)、上層 E2E(少数・重要ユーザーフロー)。推奨比率 70/20/10、カバレッジ指標と実践ガイド。

1 分で読了