۱۴۰۵ مهر ۱۵, چهارشنبه
دلار آمریکا۲۶۲٬۲۰۵▼ ۲٫۵۲٪یورو۲۹۴٬۸۳۰▼ ۲٫۸۴٪درهم امارات۷۱٬۷۷۶▼ ۲٫۲۹٪سکه امامی۲۶۷٬۳۸۵٬۰۰۰▼ ۱٫۶۹٪طلای ۱۸ عیار (گرم)۲۶٬۲۶۷٬۶۰۰▼ ۱٫۷۹٪انس طلا۴٬۱۱۶ $▼ ۱٫۱۴٪تتر۲۶۲٬۶۷۸▼ ۲٫۴۱٪بیت‌کوین۸۳٬۷۰۹ $▼ ۲٫۳٪اتریوم۲٬۵۸۴ $▼ ۴٫۲۶٪سولانا۱۱۷٫۵۵ $▼ ۳٫۰۱٪اپل۳۳۳٫۶۳ $▲ ۰٫۲۲٪انویدیا۲۳۹٫۲۴ $▲ ۰٫۱۴٪مایکروسافت۵۲۹٫۳۰ $▲ ۰٫۷۸٪آلفابت (گوگل)۳۴۷٫۶۸ $▲ ۰٫۳۵٪تسلا۳۸۰٫۶۸ $▲ ۰٫۵۲٪شاخص نزدک۲۷٬۶۰۰ $▲ ۰٫۴۵٪
نرخ ارز

API چیست؛ مقایسه‌ی REST، GraphQL و gRPC با مثال کد

API چیست و چطور دو نرم‌افزار با هم حرف می‌زنند؟ REST، GraphQL و gRPC را با مثال کد، جدول مقایسه و معیار انتخاب برای پروژه‌تان بشناسید.

کاور گرافیکی DevNA با عنوان «API Styles»: مقایسه REST، GraphQL و gRPC با مثال کد
کاور گرافیکی DevNA با عنوان «API Styles»: مقایسه REST، GraphQL و gRPC با مثال کد
فهرست مطالب
  1. API چیست؛ یک تعریف ساده
  2. REST؛ رایج‌ترین سبک طراحی API
  3. GraphQL؛ هرچه لازم دارید، نه بیشتر
  4. gRPC؛ ارتباط سریع و دقیق بین سرویس‌ها
  5. مقایسه‌ی REST، GraphQL و gRPC در یک نگاه
  6. کدام سبک API را انتخاب کنیم؟
  7. نکته‌های امنیتی و عملی برای هر API
  8. جمع‌بندی

API چیست و چرا تقریباً هر نرم‌افزاری که هر روز با آن کار می‌کنید به آن وابسته است؟ رابط برنامه‌نویسی نرم‌افزار (Application Programming Interface) یا به اختصار API، قراردادی است که مشخص می‌کند یک برنامه چطور می‌تواند از برنامه‌ی دیگر داده بخواهد یا کاری را به آن بسپارد. در این راهنما مفهوم API را از پایه توضیح می‌دهیم و سه سبک رایج آن را، یعنی REST، GraphQL و gRPC، با مثال کد کنار هم می‌گذاریم تا بدانید هرکدام کجا به کار می‌آید.

API چیست؛ یک تعریف ساده

منوی یک رستوران را در نظر بگیرید. شما وارد آشپزخانه نمی‌شوید و لازم نیست بدانید غذا چطور پخته می‌شود. منو می‌گوید چه چیزهایی را می‌توانید سفارش دهید و گارسون سفارش شما را می‌برد و نتیجه را برمی‌گرداند. API همان منو و گارسون است: فهرستی از کارهای مجاز، به‌همراه قالب دقیق درخواست و پاسخ.

اپلیکیشن هواشناسی گوشی شما نمی‌داند سرور داده‌ها را در چه پایگاه داده‌ای نگه می‌دارد. فقط طبق قرارداد API درخواست می‌فرستد و پاسخی ساختاریافته می‌گیرد. همین جدایی باعث می‌شود تیم سرور بتواند پیاده‌سازی را عوض کند، بی‌آنکه اپلیکیشن‌ها خراب شوند.

API فقط مخصوص وب نیست. سیستم‌عامل، کتابخانه‌ها و مرورگر هم API دارند؛ مثلاً fetch و localStorage در مرورگر، یا متد map روی آرایه‌های جاوااسکریپت. اما در این مقاله تمرکز ما روی API تحت وب است؛ یعنی ارتباط دو برنامه از طریق شبکه.

اجزای اصلی یک API تحت وب

  • نقطه‌ی پایانی (Endpoint): آدرسی که درخواست به آن فرستاده می‌شود.
  • درخواست و پاسخ (Request/Response): پیامی که کلاینت می‌فرستد و جوابی که سرور برمی‌گرداند.
  • قالب داده: معمولاً JSON که برای انسان خواناست، یا قالب‌های دودویی مثل Protocol Buffers.
  • احراز هویت (Authentication): کلید API یا توکن که نشان می‌دهد درخواست‌دهنده کیست.
  • مستندات: متن قرارداد؛ API بدون مستندات عملاً قابل‌استفاده نیست.

REST؛ رایج‌ترین سبک طراحی API

REST (Representational State Transfer) سبکی معماری است که روی فیلدینگ (Roy Fielding) آن را در فصل پنجم رساله‌ی دکترای خود تعریف کرد. REST پروتکل نیست؛ مجموعه‌ای از قیدهاست: جدایی کلاینت و سرور، بی‌حالت بودن (Stateless) یعنی هر درخواست همه‌ی اطلاعات لازم را با خودش دارد، قابلیت کش شدن پاسخ‌ها، رابط یکنواخت و سیستم لایه‌لایه.

در عمل، REST یعنی هر داده یک منبع (Resource) با آدرس مشخص است و با متدهای HTTP روی آن کار می‌کنید:

متد کاربرد ایمن (فقط خواندنی) Idempotent
GET خواندن منبع بله بله
POST ساختن منبع یا ارسال داده خیر خیر
PUT جایگزینی کامل منبع خیر بله
PATCH تغییر بخشی از منبع خیر خیر
DELETE حذف منبع خیر بله

متد Idempotent یعنی اگر یک درخواست را چند بار تکرار کنید، نتیجه‌ی نهایی روی سرور همان یک بار است. این ویژگی برای تکرار خودکار درخواست بعد از قطعی شبکه اهمیت دارد.

پاسخ‌ها هم با کد وضعیت (Status Code) همراه‌اند: 200 یعنی موفق، 201 یعنی منبع ساخته شد، 400 یعنی درخواست نادرست است، 401 یعنی احراز هویت لازم است، 404 یعنی منبع پیدا نشد و 500 یعنی خطا در سرور رخ داده است.

یک درخواست REST واقعی

API عمومی GitHub نمونه‌ی خوبی برای تمرین است. در ترمینال اجرا کنید:

curl https://api.github.com/users/octocat

پاسخ یک شیء JSON است که بخشی از آن این شکلی است:

{
  "login": "octocat",
  "id": 583231,
  "html_url": "https://github.com/octocat"
}

همین درخواست را از داخل کد هم می‌توانید بفرستید. این نمونه فقط از کتابخانه‌ی استاندارد پایتون استفاده می‌کند (اگر تازه با پایتون آشنا می‌شوید، آموزش پایتون از صفر را ببینید):

import json
from urllib.request import urlopen

with urlopen("https://api.github.com/users/octocat") as response:
    user = json.load(response)

print(user["login"], user["public_repos"])

برای ساختن داده معمولاً از POST با بدنه‌ی JSON و توکن احراز هویت استفاده می‌شود. آدرس زیر نمونه است و به سرویس واقعی اشاره نمی‌کند:

curl -X POST https://api.example.com/v1/articles \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_TOKEN" \
  -d '{"title": "What is an API?", "category": "web"}'

اگر می‌خواهید خودتان یک API ساده بسازید، بخش Route Handler در آموزش Next.js App Router نشان می‌دهد چطور در چند خط یک endpoint که JSON برمی‌گرداند راه بیندازید.

نقاط قوت REST: سادگی، ابزارهای فراوان، استفاده‌ی مستقیم از کش HTTP و خوانایی. نقاط ضعف: دریافت داده‌ی اضافه (Over-fetching) وقتی فقط دو فیلد لازم دارید، و دریافت داده‌ی ناکافی (Under-fetching) وقتی برای یک صفحه باید چند endpoint را جداگانه صدا بزنید.

GraphQL؛ هرچه لازم دارید، نه بیشتر

GraphQL زبان پرس‌وجو برای API است که بر یک سیستم نوع (Type System) قوی تکیه دارد. سرور در یک اسکیما (Schema) انواع داده و روابطشان را تعریف می‌کند و کلاینت دقیقاً مشخص می‌کند کدام فیلدها را می‌خواهد. همه‌ی درخواست‌ها هم معمولاً به یک نقطه‌ی پایانی واحد، مثلاً /graphql، فرستاده می‌شوند.

یک اسکیمای ساده:

type Author {
  id: ID!
  name: String!
}

type Article {
  id: ID!
  title: String!
  author: Author!
}

type Query {
  article(id: ID!): Article
}

و پرس‌وجویی که فقط عنوان مقاله و نام نویسنده را می‌خواهد:

query {
  article(id: "42") {
    title
    author {
      name
    }
  }
}

پاسخ دقیقاً همان شکل پرس‌وجو را دارد:

{
  "data": {
    "article": {
      "title": "What is an API?",
      "author": { "name": "DevNA Newsroom" }
    }
  }
}

در REST احتمالاً باید یک بار مقاله و یک بار نویسنده را جداگانه می‌گرفتید. GraphQL برای تغییر داده Mutation و برای داده‌ی بلادرنگ Subscription دارد و با قابلیت درون‌نگری (Introspection) می‌توانید خود اسکیما را از سرور بپرسید؛ ابزارهای توسعه از همین قابلیت برای تکمیل خودکار استفاده می‌کنند.

نقاط ضعف GraphQL: چون همه‌چیز به یک آدرس می‌رود، کش HTTP به‌سادگی REST کار نمی‌کند. کلاینت ممکن است پرس‌وجوی بسیار عمیق و سنگینی بفرستد، پس باید برای عمق و پیچیدگی پرس‌وجو محدودیت بگذارید. در سمت سرور هم اگر Resolverها بی‌دقت نوشته شوند، یک پرس‌وجو به ده‌ها درخواست پایگاه داده تبدیل می‌شود (مشکل N+1).

gRPC؛ ارتباط سریع و دقیق بین سرویس‌ها

gRPC چارچوبی متن‌باز برای فراخوانی رویه‌ی دور (Remote Procedure Call) است. ایده‌اش این است که کلاینت متدی را روی سروری دیگر صدا بزند، انگار که یک شیء محلی است. gRPC به‌طور پیش‌فرض از Protocol Buffers هم به‌عنوان زبان تعریف رابط و هم به‌عنوان قالب پیام استفاده می‌کند و روی HTTP/2 کار می‌کند.

قرارداد در یک فایل .proto نوشته می‌شود:

syntax = "proto3";

package news.v1;

service ArticleService {
  rpc GetArticle (GetArticleRequest) returns (Article);
  rpc StreamLatest (StreamLatestRequest) returns (stream Article);
}

message GetArticleRequest {
  string id = 1;
}

message StreamLatestRequest {
  string category = 1;
}

message Article {
  string id = 1;
  string title = 2;
  string author = 3;
}

سپس کامپایلر protoc از روی همین فایل برای زبان‌های مختلف مثل Go، Java یا Python کد کلاینت و سرور تولید می‌کند. یعنی سرویسی به زبان Go و کلاینتی به زبان Python، بدون نوشتن دستی کد سریال‌سازی، با قراردادی مشترک با هم حرف می‌زنند.

gRPC چهار نوع متد دارد:

  1. Unary: یک درخواست، یک پاسخ؛ مثل فراخوانی تابع معمولی.
  2. Server streaming: یک درخواست و دنباله‌ای از پاسخ‌ها؛ مثل StreamLatest در مثال بالا.
  3. Client streaming: دنباله‌ای از پیام‌ها از کلاینت و یک پاسخ نهایی.
  4. Bidirectional streaming: هر دو طرف مستقل از هم پیام می‌فرستند.

نقاط ضعف gRPC: پیام‌های دودویی برای انسان خوانا نیستند و اشکال‌زدایی ابزار مخصوص می‌خواهد. مرورگر هم نمی‌تواند مستقیم با سرویس gRPC حرف بزند و به gRPC-Web و یک پراکسی مثل Envoy نیاز دارد.

مقایسه‌ی REST، GraphQL و gRPC در یک نگاه

معیار REST GraphQL gRPC
قالب رایج داده JSON JSON Protocol Buffers (دودویی)
نقطه‌ی پایانی برای هر منبع یک آدرس معمولاً یک آدرس متدهای تعریف‌شده در سرویس
قرارداد اختیاری (مثلاً OpenAPI) اسکیمای اجباری فایل proto اجباری
کش HTTP ساده و طبیعی دشوارتر معمولاً در سطح برنامه
پشتیبانی مرورگر کامل کامل با gRPC-Web و پراکسی
استریم محدود با Subscription چهار حالت، از جمله دوطرفه
مناسب برای API عمومی و CRUD فرانت‌اند با داده‌ی ترکیبی ارتباط داخلی میکروسرویس‌ها

کدام سبک API را انتخاب کنیم؟

  • REST را انتخاب کنید اگر API عمومی می‌سازید، عملیات بیشتر خواندن و نوشتن ساده است و می‌خواهید هر توسعه‌دهنده‌ای با یک curl کار را شروع کند.
  • GraphQL را انتخاب کنید اگر چند کلاینت (وب، موبایل، پنل مدیریت) دارید که هرکدام برش متفاوتی از داده را می‌خواهند و تعداد رفت‌وبرگشت‌ها برایتان مهم است.
  • gRPC را انتخاب کنید اگر سرویس‌های داخلی زیادی دارید، تأخیر و حجم پیام اهمیت دارد، به استریم نیاز دارید یا تیم‌ها با زبان‌های مختلف کار می‌کنند. اگر بین Rust و Go برای بک‌اند مردد هستید، هر دو پشتیبانی خوبی از gRPC دارند.

در بسیاری از سیستم‌های واقعی این سه با هم ترکیب می‌شوند: سرویس‌ها در داخل با gRPC حرف می‌زنند و یک لایه‌ی REST یا GraphQL در لبه، داده را به مرورگر و اپلیکیشن موبایل می‌رساند.

نکته‌های امنیتی و عملی برای هر API

  • همیشه از HTTPS استفاده کنید و کلید API را هرگز در کد فرانت‌اند یا مخزن Git قرار ندهید.
  • ورودی‌ها را در سرور اعتبارسنجی کنید؛ به داده‌ای که کلاینت می‌فرستد اعتماد نکنید.
  • برای جلوگیری از سوءاستفاده، محدودیت نرخ درخواست (Rate Limiting) بگذارید.
  • مجوز دسترسی را برای هر شیء بررسی کنید، نه فقط برای هر endpoint. خطاهای رایج این حوزه را در راهنمای OWASP Top 10 مرور کرده‌ایم.
  • برای تغییرات ناسازگار نسخه‌بندی داشته باشید تا کلاینت‌های قدیمی ناگهان از کار نیفتند.

نکته برای توسعه‌دهنده‌های ایران: برخی سرویس‌های خارجی دسترسی از ایران را محدود می‌کنند. پیش از اینکه محصولتان را به یک API خارجی وابسته کنید، شرایط استفاده و دسترس‌پذیری آن را بررسی کنید و در کد برای قطعی یا رد شدن درخواست، مهلت زمانی (Timeout)، تلاش مجدد محدود و پیام خطای روشن در نظر بگیرید.

جمع‌بندی

API زبان مشترک نرم‌افزارهاست. REST با سادگی و هماهنگی کامل با HTTP هنوز انتخاب پیش‌فرض بیشتر پروژه‌هاست، GraphQL انعطاف را به کلاینت می‌دهد و gRPC سرعت و قرارداد دقیق را بین سرویس‌ها می‌آورد. هیچ‌کدام برنده‌ی مطلق نیست؛ معیار انتخاب، نوع کلاینت‌ها، الگوی داده و نیازهای عملکردی پروژه‌ی شماست. قدم بعدی عملی: با curl چند API عمومی را صدا بزنید و بعد یک endpoint ساده‌ی REST برای پروژه‌ی خودتان بسازید.

$ devna rate --article

—
هنوز رأیی ثبت نشده
  1. ۵۰
  2. ۴۰
  3. ۳۰
  4. ۲۰
  5. ۱۰

این مطلب چقدر به کارتان آمد؟

روی ستاره‌ها بزنید

واکنش شما

اولین نفری باشید که واکنش نشان می‌دهد.

پرسش‌های پرتکرار

API چیست و چه فرقی با وب‌سرویس دارد؟

API هر قراردادی است که نحوه‌ی ارتباط دو نرم‌افزار را تعریف می‌کند؛ از کتابخانه‌های داخل یک برنامه تا سرویس‌های تحت شبکه. وب‌سرویس نوعی API است که از طریق شبکه، و معمولاً با HTTP، در دسترس است.

آیا GraphQL جایگزین REST است؟

نه لزوماً. GraphQL برای رابط‌هایی که داده‌ی ترکیبی و متنوع می‌خواهند مناسب است، اما REST ساده‌تر است و از کش HTTP بهتر استفاده می‌کند. بسیاری از تیم‌ها هر دو را کنار هم به کار می‌برند.

چرا gRPC در مرورگر مستقیم کار نمی‌کند؟

مرورگرها به کد جاوااسکریپت کنترل کافی بر جزئیاتی از HTTP/2 نمی‌دهند که gRPC به آن‌ها نیاز دارد. برای همین میان مرورگر و سرور از gRPC-Web و یک پراکسی مثل Envoy استفاده می‌شود.

یادگیری API را از کجا شروع کنیم؟

با REST شروع کنید: متدهای HTTP، کدهای وضعیت و JSON را یاد بگیرید و با curl چند API عمومی را صدا بزنید. بعد سراغ GraphQL و gRPC بروید.

منابع

  1. Roy Fielding — Chapter 5: Representational State Transfer (REST)
  2. MDN — HTTP request methods
  3. GraphQL — Learn GraphQL
  4. gRPC — Introduction to gRPC
  5. gRPC — Core concepts, architecture and lifecycle
  6. gRPC Blog — The state of gRPC in the browser

خطایی در این مطلب دیدید؟ به تحریریه گزارش دهید؛ اصلاحیه‌ها طبق اصول تحریریه ثبت می‌شوند.

دیدگاه‌ها

۰/۲٬۰۰۰

دیدگاه‌ها پس از بررسی تحریریه منتشر می‌شوند. توهین، تبلیغ و لینک‌های بی‌ربط حذف می‌شوند؛ نقد فنی و مستند همیشه خوش‌آمد است.

$ comments --count۰

هنوز کسی چیزی ننوشته. اولین دیدگاه را شما ثبت کنید.

مطالب مرتبط