So sánh công nghệ

REST vs GraphQL: Khi nào nên dùng? So sánh chi tiết cho Backend Developer

So sánh chi tiết REST API và GraphQL - Ưu nhược điểm, performance, use cases và hướng dẫn chọn đúng cho dự án của bạn.

newspaper

BlogDev Team

12 tháng 12, 2024
REST vs GraphQL: Khi nào nên dùng? So sánh chi tiết cho Backend Developer
Featured Image

Giới thiệu

REST hay GraphQL? Đây là decision phổ biến khi thiết kế API cho ứng dụng mới. Cả hai đều có ưu nhược điểm riêng, và không có winner tuyệt đối.

Bài viết này sẽ so sánh chi tiết từ góc độ Backend Developer - với các ví dụ thực tế và recommendations cụ thể.

Tổng quan nhanh

REST (Representational State Transfer)

  • Kiến trúc dựa trên resourcesHTTP methods
  • Mỗi endpoint trả về fixed data structure
  • Industry standard từ nhiều năm
GET    /api/users/1        → Get user
POST   /api/users          → Create user
PUT    /api/users/1        → Update user
DELETE /api/users/1        → Delete user

GraphQL

  • Query language cho APIs
  • Client quyết định data cần lấy
  • Single endpoint, flexible queries
query {
  user(id: 1) {
    name
    email
    posts {
      title
    }
  }
}

So sánh chi tiết

1. Data Fetching

REST: Fixed responses

// GET /api/users/1
{
  "id": 1,
  "name": "John",
  "email": "john@example.com",
  "address": { ... },
  "preferences": { ... },
  "createdAt": "2024-01-01"
}

Vấn đề: Over-fetching - client nhận data không cần.

GraphQL: Client specifies

query {
  user(id: 1) {
    name
    email
  }
}

Response chỉ chứa những gì request.

2. Multiple Resources

REST: Multiple requests

// Lấy user + posts + comments
const user = await fetch('/api/users/1');
const posts = await fetch('/api/users/1/posts');
const comments = await fetch('/api/posts/1/comments');

3 HTTP requests = Higher latency

GraphQL: Single request

query {
  user(id: 1) {
    name
    posts {
      title
      comments {
        text
        author { name }
      }
    }
  }
}

1 request = Lower latency

3. API Versioning

REST: Version trong URL

/api/v1/users
/api/v2/users  → Breaking changes

Phải maintain multiple versions.

GraphQL: Deprecation thay vì versioning

type User {
  name: String!
  fullName: String! @deprecated(reason: "Use name instead")
}

Không cần versioning, evolve schema gradually.

4. Caching

REST: HTTP caching tự nhiên

GET /api/users/1
→ Cache-Control: max-age=3600
→ ETag: "abc123"

Browser và CDN có thể cache.

GraphQL: Caching phức tạp hơn

# Tất cả requests đều POST /graphql
# Không tận dụng được HTTP caching tự nhiên

Cần implement caching layer riêng (Apollo Client, Relay).

5. Error Handling

REST: HTTP status codes

// 200 OK, 404 Not Found, 500 Server Error
if (response.status === 404) {
  // Handle not found
}

Clear, standardized.

GraphQL: Always 200, errors in response

{
  "data": { "user": null },
  "errors": [
    {
      "message": "User not found",
      "extensions": { "code": "NOT_FOUND" }
    }
  ]
}

Partial success possible, nhưng cần handle khác đi.

6. Type Safety

REST: OpenAPI/Swagger

# openapi.yaml
paths:
  /users/{id}:
    get:
      responses:
        200:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

Generated docs, nhưng không enforce ở runtime.

GraphQL: Schema built-in

type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

Strong typing, validation automatic.

Performance Comparison

Request Overhead

ScenarioRESTGraphQL
Get user profile1 request1 request
User + posts + comments3+ requests1 request
List with relationsN+1 risk1 request

GraphQL wins cho complex data fetching.

Payload Size

ScenarioRESTGraphQL
Fixed structureLarger (over-fetch)Exact (specify fields)
Simple CRUDOptimalOverhead (query syntax)

Depends on use case.

Server Load

AspectRESTGraphQL
Query parsingNoneRequired
N+1 databaseEasy to optimizeDataLoader needed
CachingEasyComplex

REST simpler ở server side.

Implementation Examples

REST with Laravel

// routes/api.php
Route::apiResource('users', UserController::class);
Route::apiResource('users.posts', PostController::class);

// UserController.php
public function show(User $user)
{
    return new UserResource(
        $user->load(['posts', 'profile'])
    );
}

GraphQL with Laravel

// graphql/schema.graphql
type Query {
    user(id: ID! @eq): User @find
    users: [User!]! @paginate
}

type User {
    id: ID!
    name: String!
    posts: [Post!]! @hasMany
}

// Resolvers automatic với Lighthouse PHP

Khi nào chọn REST?

✅ Use REST when:

  1. Simple CRUD operations

    • Blog, CMS, e-commerce basics
    • Well-defined resources
  2. Caching critical

    • Public APIs
    • CDN-heavy applications
  3. Team không familiar GraphQL

    • Learning curve exists
    • REST is universal knowledge
  4. Third-party integration

    • Partners expect REST
    • Webhooks, callbacks
  5. File uploads

    • Native support
    • GraphQL cần workarounds

Example: Blog API

GET    /posts           → List posts
GET    /posts/{id}      → Get post
POST   /posts           → Create post
PUT    /posts/{id}      → Update post
DELETE /posts/{id}      → Delete post

Simple, clear, cacheable.

Khi nào chọn GraphQL?

✅ Use GraphQL when:

  1. Complex, nested data

    • Social networks
    • Dashboard với nhiều widgets
  2. Multiple clients với needs khác nhau

    • Mobile app cần ít data
    • Web app cần nhiều data
  3. Rapid iteration

    • Frontend team tự serve
    • Không cần API changes
  4. Real-time features

    • Subscriptions built-in
    • Live updates
  5. Microservices aggregation

    • API Gateway pattern
    • Federated GraphQL

Example: Social Feed

query {
  feed {
    posts {
      id
      content
      author {
        name
        avatar
      }
      likes { count }
      comments(first: 3) {
        text
        author { name }
      }
    }
  }
}

Single request replaces 5+ REST calls.

Hybrid Approach

Không nhất thiết phải chọn một:

Public API:     REST (cacheable, documented)
Mobile App:     GraphQL (flexible, efficient)
Internal:       REST (simple CRUD)
Dashboard:      GraphQL (complex queries)

Decision Framework

┌─────────────────────────────────────┐
│  Data fetching phức tạp?            │
│  (nested, multiple resources)       │
└────────────┬────────────────────────┘

      ┌──────┴──────┐
      │             │
     YES           NO
      │             │
      ▼             ▼
┌─────────┐   ┌─────────┐
│ GraphQL │   │  REST   │
└─────────┘   └─────────┘

Thêm considerations:

  • Caching critical? → REST
  • Real-time? → GraphQL (subscriptions)
  • Team expertise? → Dùng cái team biết
  • Third-party integration? → REST

Common Mistakes

❌ GraphQL cho Simple CRUD

# Over-engineering
mutation {
  createUser(input: { name: "John", email: "john@test.com" }) {
    id
    name
  }
}

REST đơn giản hơn cho case này.

❌ REST cho Complex Dashboard

// Dashboard cần 10 API calls
await Promise.all([
  fetch('/api/users/stats'),
  fetch('/api/orders/recent'),
  fetch('/api/revenue/monthly'),
  // ...7 more
]);

GraphQL sẽ efficient hơn nhiều.

❌ Không dùng DataLoader với GraphQL

// N+1 query problem
// 100 posts → 100 queries for authors

Luôn implement DataLoader cho relationships.

Kết luận

CriteriaWinner
Simple CRUDREST
Complex queriesGraphQL
CachingREST
Type safetyGraphQL
Learning curveREST
FlexibilityGraphQL
ToolingTie

Final Recommendations:

Choose REST if:

  • Team mới với API development
  • Simple, cacheable resources
  • Third-party integration needs

Choose GraphQL if:

  • Complex data requirements
  • Multiple clients (web, mobile, etc.)
  • Need rapid frontend iteration

Pro tip: Bắt đầu với REST cho MVP, migrate sang GraphQL khi complexity tăng. Migration không khó nếu có clear data layer.

history_edu Góc học tập & giải trí

Thử Thách Kiến Thức Lịch Sử?

Khám phá hàng trăm câu hỏi trắc nghiệm lịch sử thú vị tại HistoQuiz. Vừa học vừa chơi, nâng cao kiến thức ngay hôm nay!

Chơi Ngay arrow_forward