GraphQL vs REST — Khi Nào Dùng Cái Nào?
So sánh GraphQL và REST: ưu nhược điểm, use case, và cách chọn đúng cho dự án của bạn.
REST là tiêu chuẩn API truyền thống. GraphQL là “REST killer” được Facebook tạo ra. Bài này sẽ giúp bạn quyết định dùng cái nào.
REST API — Quen Thuộc, Đơn Giản#
GET /users/1
→ { "id": 1, "name": "Alice", "email": "alice@example.com" }
GET /users/1/posts
→ [{ "id": 10, "title": "Hello" }]httpREST Ưu Điểm#
- Đơn giản, dễ hiểu, dùng đúng HTTP semantics
- Cache dễ dàng (URL là cache key)
- Tooling phong phú (bất kỳ HTTP client nào)
- Dễ versioning (
/api/v1/)
REST Nhược Điểm#
- Over-fetching — API trả về nhiều field hơn cần
- Under-fetching — cần gọi nhiều endpoint để có đủ data
- Khó thay đổi — thêm field có thể break client
- N+1 problem — gọi API trong loop
GraphQL — Linh Hoạt, Chính Xác#
query {
user(id: 1) {
name
email
posts {
title
}
}
}graphql{
"data": {
"user": {
"name": "Alice",
"email": "alice@example.com",
"posts": [{ "title": "Hello" }]
}
}
}jsonGraphQL Ưu Điểm#
- Client quyết định — lấy đúng field cần
- Một request — lấy user + posts + comments trong 1 lần
- Strongly typed — schema là hợp đồng giữa client và server
- Tự động docs — GraphiQL/GraphQL Playground
GraphQL Nhược Điểm#
- Cache phức tạp — không dùng URL cache được
- Rate limiting khó — một request có thể trigger nhiều resolver
- N+1 — resolver lồng nhau có thể gọi DB nhiều lần (cần DataLoader)
- Learning curve — cần hiểu schema, resolver, query optimization
So Sánh Chi Tiết#
| Tiêu chí | REST | GraphQL |
|---|---|---|
| Data fetching | Server quyết định | Client quyết định |
| Cache | URL-based (dễ) | Complex (cần tool) |
| Versioning | URL path | Evolve schema |
| File upload | Multipart | Cần thư viện |
| Tooling | Browser, curl, Postman | GraphiQL, Apollo DevTools |
| Performance | Dễ predict | Khó predict (nested query) |
| Real-time | SSE, WebSocket riêng | Subscription built-in |
| Complexity | Thấp | Trung bình-Cao |
Khi Nào Dùng REST#
- API đơn giản, CRUD basic
- Public API cho bên thứ ba
- File upload/download nhiều
- Microservice internal communication
- Cache là yêu cầu quan trọng
Khi Nào Dùng GraphQL#
- Dashboard/UI phức tạp, nhiều loại data
- Mobile app (băng thông hạn chế)
- Nhiều client khác nhau (web, mobile, IoT)
- Bạn muốn schema làm single source of truth
Thực Tế — Hybrid#
Không nhất thiết phải chọn 1. Nhiều công ty dùng cả hai:
Public API → REST (ổn định, cache tốt)
Internal API → GraphQL (linh hoạt cho nhiều client)textHoặc: REST cho CRUD đơn giản, GraphQL cho complex query.
Triển Khai GraphQL#
Server với Yoga (Node.js)#
import { createYoga, createSchema } from 'graphql-yoga';
import { createServer } from 'node:http';
const schema = createSchema({
typeDefs: `
type Query {
user(id: ID!): User
posts(limit: Int): [Post]
}
type User {
id: ID!
name: String!
email: String!
posts: [Post]
}
type Post {
id: ID!
title: String!
content: String!
}
`,
resolvers: {
Query: {
user: (_, { id }) => db.getUser(id),
posts: (_, { limit }) => db.getPosts(limit),
},
User: {
posts: (parent) => db.getPostsByUser(parent.id),
},
},
});
const server = createServer(createYoga({ schema }));
server.listen(4000);typescriptDataLoader — Giải Quyết N+1#
import DataLoader from 'dataloader';
const postLoader = new DataLoader(async (userIds: number[]) => {
const posts = await db.getPostsByUsers(userIds);
// Group by userId
return userIds.map(id => posts.filter(p => p.userId === id));
});
const resolvers = {
User: {
posts: (parent) => postLoader.load(parent.id),
},
};typescriptBảo Mật GraphQL#
// Giới hạn độ sâu query
import depthLimit from 'graphql-depth-limit';
const yoga = createYoga({
schema,
plugins: [
useDepthLimit({ maxDepth: 5 }),
],
});typescript// Giới hạn complexity
const schema = createSchema({
typeDefs: `
type Query {
users: [User] @complexity(value: 10)
expensiveQuery: Data @complexity(value: 100)
}
`,
});typescriptKết Luận#
REST và GraphQL không phải kẻ thù — mỗi cái có chỗ đứng riêng. REST cho đơn giản, ổn định. GraphQL cho linh hoạt, hiệu quả. Chọn theo nhu cầu.
Nếu bạn chưa biết bắt đầu — chọn REST. Khi REST đau quá (over-fetching, multiple round trips), hãy nghĩ đến GraphQL.