ข้ามไปยังเนื้อหา

GraphQL vs REST

REST รับใช้เว็บมาดีตลอดสองทศวรรษ และทีมส่วนใหญ่ที่หันมาใช้ GraphQL ก็ย้ายมาจาก REST คำถามที่ตรงประเด็นจึงไม่ใช่ “อันไหนดีกว่า” แต่เป็น “แต่ละอันออกแบบมาเพื่ออะไร และเรากำลังแลกอะไรอยู่” บทนี้จะวางทั้งสองเทียบกันแบบเคียงข้าง

REST API จำลอง resource เป็น URL หากต้องการสร้างหน้าโปรไฟล์ คุณอาจต้องเรียกถึงสามตัว:

GET /users/42
GET /users/42/posts
GET /posts/99/comments

request ของ GraphQL ที่เทียบเท่าคือ query เดียวไปยัง endpoint เดียว เดินจาก user ไปยัง posts ของพวกเขา ไปยัง comments ของแต่ละ post ใน round trip เดียว:

{
user(id: "42") {
name
posts {
title
comments {
body
}
}
}
}
flowchart TB
  subgraph REST["REST — three round trips"]
    direction LR
    R1["GET /users/42"] --> R2["GET /users/42/posts"] --> R3["GET /posts/99/comments"]
  end
  subgraph GQL["GraphQL — one round trip"]
    direction LR
    G1["POST /graphql"] --> G2["user -> posts -> comments"]
  end
round trip สามครั้งของ REST ยุบเหลือ query เดียวของ GraphQL

นี่คือจุดที่สัมผัสได้ถึงความแตกต่างในแต่ละวัน

  • กับ REST นั้น GET /users/42 คืน payload คงที่ หากคุณต้องการแค่ name คุณก็ยังได้รับ record ทั้งหมดอยู่ดี (over-fetching) หากคุณต้องการ posts ที่เกี่ยวข้องคุณก็ต้องเรียกอีกครั้ง (under-fetching)
  • กับ GraphQL คุณระบุ field ที่ต้องการได้แม่นยำ ครอบคลุม type ที่เกี่ยวข้อง แล้วได้ทั้งหมดกลับมาใน response เดียว ปัญหาทั้งสองข้อจึงไม่เกิดตั้งแต่แรก
ประเด็นRESTGraphQL
Endpointหลายตัว หนึ่งตัวต่อหนึ่ง resourceendpoint graph เดียว
รูปร่าง responseกำหนดโดย serverเลือกโดย client
Over/under-fetchingเกิดบ่อยเลี่ยงได้ตั้งแต่การออกแบบ
Versioningมักใช้ URL อย่าง /v1, /v2วิวัฒน์ schema; deprecate field
HTTP cachingง่าย — URL cache ได้ดียากกว่า — ต้องใช้ caching ระดับแอปหรือ persisted-query
ความค้นพบได้OpenAPI/เอกสาร ตามธรรมเนียมintrospection ที่มีในตัว schema
ความชันในการเรียนรู้คุ้นเคยสำหรับทีมส่วนใหญ่ต้องเรียน schema, resolver และ N+1

REST API มักทำ version ผ่าน URL — /v1/users แล้วก็ /v2/users ส่วน GraphQL ใช้ การวิวัฒน์อย่างต่อเนื่อง แทน คือเพิ่ม field ใหม่ได้อิสระ (เป็น opt-in อยู่แล้ว client เก่าจึงไม่กระทบ) และ mark field เก่าด้วย @deprecated เพื่อค่อย ๆ พา client ออกจาก field นั้น แทบไม่ต้องกระโดดเวอร์ชันแบบหักดิบเลย

นี่คือต้นทุนที่จริงที่สุดของ GraphQL GET /posts/99 ของ REST คือ URL ที่นิ่ง browser CDN และ proxy จึง cache ให้ฟรี ส่วน query ของ GraphQL มักมาในรูป POST ที่มี query อยู่ใน body ชั้น HTTP caching จึงใช้ไม่ได้ทันทีตามค่าเริ่มต้น ทีมต่าง ๆ ทวงคืนด้วยเทคนิคอย่าง persisted query (ส่ง hash ที่นิ่งแทนข้อความ query เต็ม) และ normalized client cache (แบบที่ Apollo Client หรือ urql มีให้) แก้ได้อยู่ แต่ไม่ฟรี

ตัวรันด้านล่างรัน query ของ GraphQL เพียงตัวเดียว ซึ่งในโลกของ REST จะต้องใช้การเรียกแยกกันถึงสามครั้ง สังเกตว่า request เดียวคืนโครงสร้างที่ซ้อนชั้นและพร้อม render

JavaScript

เลือก REST เมื่อ API ของคุณมีรูปร่างแบบ resource และเน้น cache หนัก (นึกถึงเนื้อหาสาธารณะที่อ่านเป็นหลักซึ่งให้บริการผ่าน CDN) เมื่อผู้บริโภคเรียบง่าย หรือเมื่อทีมส่ง REST ได้ดีอยู่แล้วและชิ้นส่วนเพิ่มเติมไม่คุ้มที่จะลงทุน

เลือก GraphQL เมื่อ client หลากหลายต้องการชิ้นส่วนข้อมูลชุดเดียวกันในแบบที่แตกต่างกัน เมื่อมุมมองต่าง ๆ รวบรวม resource ที่เกี่ยวข้องกันหลายตัว เมื่อทีมผลิตภัณฑ์ทำงานเร็วและต้องการเพิ่ม field โดยไม่ต้องประสานงานการปล่อย endpoint หรือเมื่อ strong typing และ introspection ทั่วทั้งพื้นผิวของ API นำมาซึ่งประโยชน์ที่แท้จริง

RESTGraphQL
Endpointหลาย endpointsingle /graphql
Responseserver กำหนดclient เลือก field
Versioning/v1/, /v2/schema evolution + deprecation
CachingHTTP cache ง่ายต้องใช้ persisted query
Type SafetyOpenAPI (optional)built-in schema
Learning Curveต่ำสูงกว่า
ใช้ REST เมื่อใช้ GraphQL เมื่อ
public API ที่ต้องการ HTTP cacheหลาย client ต้องการ data shape ต่างกัน
simple CRUD ที่ endpoint ชัดเจนmobile app ที่ bandwidth จำกัด
team ไม่มี GraphQL experienceschema ซับซ้อนและมี relationship หลายชั้น
file upload heavyต้องการ type-safe client code gen

ใช้ GraphQL เพราะ hype ไม่ใช่เพราะ problem อาการ:

  • API มี 5 endpoint ที่ชัดเจน แต่เปลี่ยนไปใช้ GraphQL เพราะ “modern”
  • ทีมเสียเวลา setup GraphQL แทนที่จะ ship feature

คิดว่า GraphQL เร็วกว่า REST เสมอ อาการ:

  • ไม่ implement DataLoader — N+1 ทำให้ GraphQL ช้ากว่า REST มาก
  • ไม่มี query depth limit — client ส่ง deeply nested query ทำให้ server overload

💡 ตัวอย่างจากของจริง

Twitter:

  • ใช้ REST API มาตลอดและ serve ได้ดี — ไม่จำเป็นต้องเปลี่ยน
  • พิสูจน์ว่า REST ยังเหมาะสำหรับ high-traffic public API

Airbnb:

  • ใช้ GraphQL Federation สำหรับ internal API ระหว่าง team
  • แต่ยัง expose REST สำหรับ partner API ที่ต้องการ HTTP caching
ปัญหาใดที่ GraphQL เลี่ยงได้ตั้งแต่การออกแบบ แต่ REST เจอบ่อย?
อะไรคือข้อแลกเปลี่ยนของ GraphQL ที่ถูกพูดถึงบ่อยที่สุดเมื่อเทียบกับ REST?
โดยทั่วไป GraphQL จัดการกับการวิวัฒน์ของ API อย่างไรแทนการทำ version ใน URL อย่าง /v1 และ /v2?
สถานการณ์ใดที่เหมาะกับ REST มากกว่า GraphQL?