🔵 REST
Nhiều endpoints, mỗi resource 1 URL. HTTP methods (GET, POST, PUT, DELETE). Stateless.
🩷 GraphQL
Một endpoint duy nhất, client query đúng data cần. Giải quyết over/under-fetching.
1. REST API
# REST: Mỗi resource = 1 endpoint
GET /api/users → Danh sách users
GET /api/users/123 → User 123
POST /api/users → Tạo user mới
PUT /api/users/123 → Cập nhật user 123
DELETE /api/users/123 → Xóa user 123
GET /api/users/123/orders → Orders của user 123
Vấn đề Over-fetching: Client cần tên user nhưng API trả về TẤT CẢ fields:
// GET /api/users/123
// Response: trả về TẤT CẢ, dù client chỉ cần name
{
"id": 123,
"name": "Nguyễn Văn A", // ← cần
"email": "a@example.com", // ← không cần
"phone": "0901234567", // ← không cần
"address": { ... }, // ← không cần
"avatar": "...", // ← không cần
"created_at": "..." // ← không cần
}
// → Over-fetching: nhận quá nhiều data
Vấn đề Under-fetching: Cần gọi NHIỀU requests để lấy đủ data:
// Trang profile cần: user + orders + friends
// → 3 requests riêng biệt (Under-fetching)
const user = await fetch('/api/users/123');
const orders = await fetch('/api/users/123/orders');
const friends = await fetch('/api/users/123/friends');
2. GraphQL
# GraphQL: 1 endpoint, client chọn đúng data cần
# POST /graphql
query {
user(id: 123) {
name # ← chỉ lấy name
orders { # ← lấy orders IN CÙNG REQUEST
id
total
status
}
friends(limit: 5) {
name
avatar
}
}
}
# → 1 request duy nhất, nhận đúng data cần!
// GraphQL Server (Apollo Server)
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
orders: [Order!]!
friends: [User!]!
}
type Order {
id: ID!
total: Float!
status: String!
}
type Query {
user(id: ID!): User
users: [User!]!
}
`;
const resolvers = {
Query: {
user: (_, { id }) => getUserById(id),
},
User: {
orders: (user) => getOrdersByUserId(user.id),
friends: (user) => getFriendsByUserId(user.id),
},
};
3. Bảng So Sánh
| Tiêu chí | 🔵 REST | 🩷 GraphQL |
|---|---|---|
| Endpoints | Nhiều (1 per resource) | Một duy nhất (/graphql) |
| Data fetching | Server quyết định response | Client chọn fields cần |
| Over-fetching | Thường xảy ra | Không (client chọn chính xác) |
| Under-fetching | Cần nhiều requests | 1 request lấy mọi thứ |
| Caching | HTTP caching (dễ) | Phức tạp hơn (cần Apollo Cache) |
| Versioning | /api/v1, /api/v2 | Không cần (thêm fields mới) |
| Learning curve | Thấp | Cao hơn |
| Dùng bởi | Đa số companies | Facebook, GitHub, Shopify |
4. Khi Nào Chọn?
Chọn REST khi:
• API đơn giản, CRUD cơ bản
• Cần HTTP caching mạnh
• Public API cho third-party
• Team chưa quen GraphQL
Chọn GraphQL khi:
• Frontend phức tạp, nhiều views khác nhau
• Mobile app (tiết kiệm bandwidth)
• Microservices gateway (aggregate data)
• Data relationships phức tạp