GraphQL — یک زبان پرسوجو برای API و محیط اجرایی برای انجام این پرسوجوها است که توسط فیسبوک در سال ۲۰۱۲ توسعه یافت و در سال ۲۰۱۵ به صورت متنباز منتشر شد. برخلاف REST، که در آن سرور ساختار پاسخ را تعیین میکند، GraphQL به مشتری اجازه میدهد دقیقاً مشخص کند چه دادههایی نیاز دارد و مشکلات overfetching و underfetching را کاملاً از بین میبرد. بر اساس نظرسنجی State of JavaScript (2025)، ۳۵٪ از توسعهدهندگان شرکتکننده از GraphQL استفاده میکنند و از میان شرکتهای بزرگ، GitHub، Shopify، Airbnb و The New York Times آن را پیادهسازی کردهاند. GraphQL از سه نوع عملیات پشتیبانی میکند: query (خواندن)، mutation (نوشتن) و subscription (بهروزرسانی بلادرنگ از طریق WebSocket).
نکات اصلی
GraphQL — یک مشخصات و محیط اجرایی برای API است که به مشتری کنترل کامل بر دادههای دریافتی میدهد. این مشخصات توسط مهندسان فیسبوک برای حل مشکلات برنامه موبایل News Feed توسعه یافت و در سال ۲۰۱۵ به عنوان یک استاندارد باز منتشر شد. از سال ۲۰۱۸، GraphQL تحت مدیریت GraphQL Foundation با پشتیبانی Linux Foundation و شرکتهایی مانند Apollo، AWS، GitHub، SAP و دیگران قرار دارد.
برخلاف REST، که در آن هر endpoint ساختار داده ثابتی را برمیگرداند، GraphQL از یک endpoint واحد استفاده میکند که یک رشته پرسوجو را دریافت میکند. مشتری در پرسوجو مشخص میکند که به چه فیلدهایی نیاز دارد و سرور دقیقاً همانها را برمیگرداند. برای مثال، پرسوجوی { user(id: «1») { name email } } فقط name و email کاربر را برمیگرداند، بدون فیلدهای اضافی مانند address، phone یا createdAt که در REST باید دریافت میشدند.
GraphQL به هیچ پایگاه داده یا زبان خاصی وابسته نیست. مشخصات فقط قالب پرسوجوها و پاسخها را تعریف میکند. پیادهسازیهای سرور در Node.js (graphql-js، Apollo Server)، Kotlin (graphql-kotlin، Netflix DGS Framework)، Python (Graphene، Strawberry)، Ruby (graphql-ruby) و زبانهای دیگر وجود دارد. کتابخانههای مشتری برای همه پلتفرمهای اصلی از جمله Apollo Client برای iOS، Android و وب در دسترس هستند.
معماری GraphQL از سه مؤلفه کلیدی تشکیل شده است: طرحواره (Schema)، حلکنندهها (Resolvers) و موتور اجرایی (GraphQL Engine). طرحواره تعیین میکند چه نوع دادههایی در دسترس هستند، چه پرسوجوهایی میتوان انجام داد و چه آرگومانهایی میپذیرند. حلکنندهها توابعی در سمت سرور هستند که برای هر فیلد طرحواره داده برمیگردانند. موتور اجرایی پرسوجوی ورودی را دریافت میکند، آن را بر اساس طرحواره اعتبارسنجی میکند، حلکنندههای مربوطه را فراخوانی کرده و پاسخ را میسازد.
فرایند پردازش پرسوجو به این صورت است:
مزیت کلیدی معماری GraphQL حلوفصل در سطح فیلد است. در REST، توسعهدهنده یا تمام فیلدهای منبع را دریافت میکند (احتمالاً با دادههای اضافی)، یا به افزونههایی مانند ?fields=name,email متوسل میشود. در GraphQL چنین فیلتراسیونی در زبان تعبیه شده است: هر پرسوجو به صراحت مشخص میکند چه فیلدهایی نیاز است و سرور دقیقاً همانها را برمیگرداند. این برای برنامههای موبایل که حجم دادههای منتقل شده مستقیماً بر سرعت بارگذاری و مصرف ترافیک تأثیر میگذارد، بسیار مهم است.
GraphQL سه نوع عملیات را تعریف میکند که هر کدام مربوط به سناریوی خاصی از تعامل هستند. Query — برای خواندن دادهها، مشابه GET در REST. Mutation — برای تغییر دادهها (ایجاد، بهروزرسانی، حذف)، مشابه POST/PUT/DELETE. Subscription — برای بهروزرسانی بلادرنگ از طریق WebSocket، که معادل مستقیمی در REST کلاسیک ندارد (نیاز به راهحلهای اضافی مانند WebSocket یا Server-Sent Events دارد).
نحو پایه پرسوجوها بصری و قابل درک است:
// پرسوجوی ساده با آرگومان
query {
user(id: "42") {
name
email
avatarUrl
}
}
// Mutation با بازگرداندن دادههای تغییر یافته
mutation {
updateProfile(name: "ایوان") {
id
name
updatedAt
}
}
// Subscription — بهروزرسانیهای بلادرنگ را گوش میدهد
subscription {
newMessage(chatId: "chat_1") {
id
text
sender { name }
}
}
Query به صورت موازی اجرا میشود — همه فیلدها در یک سطح به طور همزمان بارگذاری میشوند. این امکان بارگذاری دادههای مرتبط (کاربر و پستهای او) را با یک پرسوجو بدون round-tripهای متعدد فراهم میکند. Mutation به صورت ترتیبی اجرا میشود — جهشها در یک پرسوجو یکی پس از دیگری به ترتیب اعلان اجرا میشوند. Subscription یک اتصال دائمی از طریق WebSocket برقرار میکند که از طریق آن سرور هنگام وقوع رویداد داده ارسال میکند.
عملیاتها میتوانند متغیرها را برای جدا کردن دادهها از پرسوجو، دستورالعملها (@include، @skip) برای گنجاندن شرطی فیلدها و قطعات را برای استفاده مجدد از مجموعه فیلدها بپذیرند. این قابلیتها پرسوجوهای GraphQL را انعطافپذیر و قابل استفاده مجدد میکند، که در پروژههای بزرگ با صفحات و مؤلفههای متعدد بسیار مهم است.
در قلب GraphQL سیستم انواع قرار دارد که تمام دادهها و عملیات API را توصیف میکند. طرحواره (Schema) توصیفی از انواعی است که سرور میتواند برگرداند و پرسوجوهایی که میپذیرد. طرحواره به زبان Schema Definition Language (SDL) نوشته میشود و به عنوان قراردادی بین مشتری و سرور عمل میکند. مشتری میتواند طرحواره را از طریق دروننگری (introspection) — یک پرسوجوی ویژه __schema که توصیف کامل API را برمیگرداند — به دست آورد.
نمونه طرحواره برای یک وبلاگ:
// SDL — Schema Definition Language
type User {
id: ID!
name: String!
email: String
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String
author: User!
}
type Query {
user(id: ID!): User
posts(page: Int): [Post!]!
}
علامت تعجب (!) به معنای فیلد non-null است — تضمین شده در پاسخ وجود دارد. براکتهای مربع [ ] نشاندهنده لیست هستند. GraphQL از انواع اسکالر (Int، Float، String، Boolean، ID)، انواع شیء، enum، union، interface و input-types (برای آرگومانهای جهش) پشتیبانی میکند. تایپبندی سختگیرانه API را خود-مستند میکند و به ابزارهای مشتری اجازه تولید کد میدهد: انواع TypeScript، کلاسهای داده Kotlin، ساختارهای Swift.
دروننگری — یک قابلیت منحصربهفرد GraphQL که در REST وجود ندارد. مشتری میتواند یک پرسوجو به طرحواره ارسال کند و توصیف کاملی از همه انواع، فیلدها، آرگومانها و دستورالعملها دریافت کند. این اساس ابزارهایی مانند GraphiQL و Apollo Studio است که به طور خودکار مستندات و تکمیل خودکار را برای توسعهدهندگان تولید میکنند. دروننگری همچنین امکان نوشتن تستهای خودکار را فراهم میکند که مطابقت طرحواره با ساختار مورد انتظار را بررسی میکنند.
انتخاب بین GraphQL و REST یکی از سؤالات معماری کلیدی هنگام طراحی API است. هر دو رویکرد نقاط قوت و ضعف خود را دارند و انتخاب به نیازهای خاص پروژه بستگی دارد. REST از نظر سادگی و جهانی بودن برنده است، GraphQL — از نظر انعطافپذیری و کارایی پرسوجو. بیایید جدول مقایسه را بررسی کنیم.
| معیار | REST | GraphQL |
|---|---|---|
| ساختار پاسخ | ثابت، سمت سرور | انعطافپذیر، سمت مشتری |
| Overfetching | اغلب — سرور همه فیلدها را برمیگرداند | خیر — مشتری فقط موارد نیاز را درخواست میکند |
| تعداد درخواستها | round-tripهای متعدد | یک درخواست برای همه دادهها |
| ذخیرهسازی موقت | ذخیرهسازی بومی HTTP | نیاز به پیکربندی دستی دارد |
| تایپبندی | داخلی نیست (به فرمت بستگی دارد) | سختگیرانه، از طریق طرحواره SDL |
| ابزارها | curl، Postman، Swagger | GraphiQL، Apollo Studio، Introspection |
| آپلود فایل | بومی از طریق multipart | نیاز به پروتکلهای اضافی دارد |
| عملکرد | قابل پیشبینی، بهینهسازی آسانتر | به پیچیدگی پرسوجوهای تودرتو بستگی دارد |
عیب اصلی GraphQL دشواری ذخیرهسازی موقت است. در REST، ذخیرهسازی HTTP در سطح URL کار میکند: یک درخواست به /api/users/42 همیشه ساختار یکسانی را برمیگرداند و پاسخ را میتوان بر اساس URL ذخیره کرد. در GraphQL، همه درخواستها به یک endpoint میروند، ساختار پاسخ به بدنه درخواست بستگی دارد. برای حل این مشکل، Apollo Client از یک حافظه نهان نرمالسازی شده در سمت مشتری استفاده میکند که پاسخها را به موجودیتهای جداگانه بر اساس id تقسیم میکند و هنگام دریافت دادههای جدید به طور خودکار آنها را بهروزرسانی میکند.
یکی دیگر از جنبههای مهم مشکل N+1 است. هنگام درخواست دادههای تودرتو (مثلاً پستهای کاربر و نظرات هر پست)، GraphQL ممکن است برای هر عنصر لیست یک پرسوجوی SQL جداگانه اجرا کند. این مشکل با DataLoader حل میشود — ابزاری برای دستهبندی و ذخیرهسازی پرسوجوهای پایگاه داده که پرسوجوهای جداگانه را در یک پرسوجوی دستهای گروهبندی میکند. در REST، این مشکل کمتر مشخص است، زیرا توسعهدهنده ساختار پاسخ را در سمت سرور کنترل میکند.
بیایید نمونههای عملی استفاده از GraphQL را در یک برنامه موبایل با Kotlin و Apollo Client بررسی کنیم. نمونهها سناریوهای معمول را نشان میدهند: بارگذاری دادهها برای صفحه پروفایل (query)، ایجاد پست جدید (mutation) و اشتراک در نظرات جدید (subscription). هر نمونه شامل پرسوجوی GraphQL و کد سمت مشتری است.
یک پرسوجوی GraphQL کاربر، آخرین پستهای او و تعداد کل دنبالکنندگان را بارگذاری میکند. در REST حداقل به ۲-۳ درخواست نیاز بود: /users/42، /users/42/posts، /users/42/stats. GraphQL آنها را در یک round-trip ترکیب میکند و زمان بارگذاری صفحه در اتصالات کند را کاهش میدهد.
// پرسوجوی GraphQL (در فایل .graphql)
query ProfileScreen($userId: ID!) {
user(id: $userId) {
name
bio
avatarUrl
posts(limit: 10) {
id
title
createdAt
}
followersCount
followingCount
}
}
// فراخوانی سمت مشتری (Apollo Client + Kotlin)
val response = apolloClient
.query(ProfileScreenQuery(userId = "42"))
.execute()
binding.nameText.text = response.data?.user?.name
جهش نه تنها منبع را ایجاد میکند، بلکه دادههای بهروز آن را برای بهروزرسانی UI برمیگرداند. فیلد __typename توسط Apollo Client برای نرمالسازی حافظه نهان استفاده میشود — مشتری به طور خودکار رکورد Post را در حافظه نهان پس از پاسخ موفق جهش بهروزرسانی میکند.
// جهش GraphQL
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
createdAt
author {
id
name
}
}
}
// فراخوانی جهش با نوع ورودی
val input = CreatePostInput(
title = "پست جدید درباره GraphQL",
content = "GraphQL کار با API را ساده میکند..."
)
val result = apolloClient
.mutation(CreatePostMutation(input))
.execute()
مزیت مهم GraphQL نسبت به REST در زمینه توسعه موبایل تولید خودکار کد است. Apollo Client برای Kotlin (Apollo GraphQL) کلاسهای نوع-امن را از فایلهای .graphql در مرحله ساخت تولید میکند. اگر سرور طرحواره را تغییر دهد، پروژه تا بهروزرسانی پرسوجوها ساخته نخواهد شد. این از خطاهای زمان اجرا که مشخصه REST هستند، جلوگیری میکند، جایی که تغییر ساختار پاسخ ممکن است در هنگام توسعه نادیده گرفته شود.
اکوسیستم GraphQL شامل چندین کتابخانه و ابزار کلیدی است که توسعه و بهرهبرداری را ساده میکنند. Apollo Client — محبوبترین کتابخانه مشتری است که از React، iOS، Android و Kotlin Multiplatform پشتیبانی میکند. Relay از فیسبوک — جایگزینی برای برنامههای React با رویکردی منحصربهفرد در مدیریت داده و ذخیرهسازی است. انتخاب بین Apollo و Relay به پلتفرم و نیازهای عملکرد بستگی دارد.
در سمت سرور، Apollo Server (Node.js)، Netflix DGS Framework (Kotlin/Java) و graphql-ruby پیشرو هستند. برای توسعه طرحواره و آزمایش پرسوجوها از GraphiQL — یک IDE تعاملی تعبیه شده در مرورگر استفاده میشود. Apollo Studio معیارهای عملکرد، ردیابی پرسوجو و مدیریت طرحواره را برای محیط تولید فراهم میکند. جداگانه باید به GraphQL Code Generator اشاره کرد — ابزاری که انواع TypeScript، Kotlin، Swift و Dart را از طرحواره SDL تولید میکند.
برای توسعه موبایل، Apollo Kotlin (Apollo GraphQL) مورد توجه ویژه است — کتابخانهای که کاملاً به زبان Kotlin با پشتیبانی از کوروتین، Flow و Multiplatform نوشته شده است. این کتابخانه امکان استفاده از پرسوجوهای GraphQL یکسان را برای Android و iOS در پروژههای Kotlin Multiplatform فراهم میکند. Apollo Kotlin حافظه نهان را نرمالسازی میکند، از خطاها در سطح فیلد (partial errors) پشتیبانی میکند و به طور خودکار مدلهای داده را از فایلهای .graphql تولید میکند. این GraphQL را به انتخاب ارجح برای پروژههای بزرگ موبایل تبدیل میکند، جایی که سرعت توسعه و ایمنی انواع اهمیت دارند.
سوالات متداول
GraphQL جایگزین REST نمیشود، بلکه یک رویکرد جایگزین ارائه میدهد. REST برای APIهای CRUD ساده، ذخیرهسازی از طریق HTTP و APIهای عمومی با بار قابل پیشبینی مناسبتر است. GraphQL برای رابطهای پیچیده با دادههای مرتبط متعدد بهینه است.
مهاجرت تدریجی امکانپذیر است: GraphQL میتواند به عنوان یک لایه میانی (gateway) در مقابل سرویسهای REST موجود کار کند. بسیاری از شرکتها GraphQL را در کنار REST اضافه میکنند، بدون اینکه API قدیمی را غیرفعال کنند. جایگزینی کامل نیاز به بازنویسی resolverها دارد.
N+1 زمانی رخ میدهد که برای هر عنصر لیست یک پرسوجوی جداگانه به پایگاه داده اجرا شود. با DataLoader — کتابخانهای که پرسوجوهای جداگانه را در یک پرسوجو دستهبندی میکند و نتایج را در چارچوب یک درخواست HTTP ذخیره میکند — حل میشود.
مشخصات GraphQL آپلود فایل را مستقیماً تعریف نمیکند. در عمل از: کدگذاری base64 (ساده اما ناکارآمد برای فایلهای بزرگ)، درخواستهای multipart بر اساس پروتکل graphql-multipart-request-spec یا یک endpoint REST جداگانه برای فایلها استفاده میشود.
امنیت GraphQL نیاز به اقدامات اضافی دارد: محدود کردن عمق تودرتو، محدودیت پیچیدگی پرسوجو، rate limiting در سطح عملیات. دروننگری عمومی طرحواره میتواند ساختار داده را افشا کند — در محیط تولید توصیه میشود آن را غیرفعال کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید