با پیشرفت و پیچیدهتر شدن نرمافزارهای وب و موبایل، توسعهدهندگان روشهای هوشمندانهای برای بهبود تعامل بین کلاینت و سرور ابداع کردهاند. یکی از بزرگترین تغییرات چند سال اخیر در این زمینه، GraphQL است؛ یک زبان کوئری و رانتایم متنباز برای مدیریت APIها. GraphQL در سال ۲۰۱۲ توسط فیسبوک طراحی شد (و در ۲۰۱۵ به صورت عمومی منتشر شد) تا مشکلات معماری سنتی REST را حل کند و سیستمی توصیفی، کنترل شده توسط کلاینت و پرکارآمد ایجاد نماید.
در این مقاله با GraphQL آشنا میشوید، با مفاهیم و اصطلاحات مهم آن آشنا خواهید شد و نحوهی مقایسه مشخصات GraphQL با معماری REST را بررسی میکنید.
معرفی GraphQL
GraphQL مخفف Graph Query Language است اما برخلاف زبانهای کوئری مانند SQL، این زبان برای تعامل مستقیم با پایگاه داده نیست بلکه قراردادی است برای ارتباط کلاینت با سرور API. مشخصات GraphQL یک استاندارد باز است که قوانین و ویژگیهای زبان را تعریف میکند و نحوه اجرای کوئریها را مشخص مینماید.
چون GraphQL به صورت یک استاندارد باز تعریف شده، هیچ پیادهسازی رسمی برای آن وجود ندارد و میتوان آن را با هر زبان برنامهنویسی و هر نوع پایگاه دادهای پیادهسازی کرد. فقط کافی است قوانین این استاندارد رعایت شود. یکی از معروفترین پیادهسازیهای تجاری، Apollo GraphQL است که مجموعهای از کلاینت و سرور GraphQL را ارائه میدهد اما استفاده از Apollo برای کار با GraphQL الزامی نیست.
ویژگیهای کلیدی طراحی GraphQL
- کوئریهای توصیفی و سلسلهمراتبی: کلاینت دقیقاً تعیین میکند به کدام فیلدها نیاز دارد و پاسخ تنها شامل همان فیلدها است.
- اسکیما قوی و تایپ اسکریپت شده: ساختار دادهها با تایپهای قوی تعریف میشود که صحت کوئریها را قبل از اجرا تضمین میکند.
- قابلیت introspection (بازشناسی): کلاینت میتواند ساختار اسکیما را با کوئری بپرسد و ابزارهایی مانند GraphiQL برای ساخت اسناد خودکار و تست کوئریها فراهم شود.
نمونه کوئری در GraphQL
یک کوئری نمونه برای یک API بازی خیالی که یک wizard با آیدی “1” را همراه با نام و نژاد درخواست میکند:
{
wizard(id: "1") {
name
race
}
}
پاسخ در قالب JSON داده میشود و فقط شامل همان دو فیلد نام و نژاد است. پاسخ صرفاً همان دادههای خواسته شده را ارسال میکند که باعث بهینه شدن درخواست میشود.
کوئریها سلسلهمراتبی هستند یعنی دادهها مطابق ساختار کوئری بازگردانده میشوند. مثلاً اگر فیلد جادویی spells نیز اضافه شود، همه جادوهای مرتبط با wizard برگردانده میشوند:
{
wizard(id: "1") {
name
race
spells {
name
attack
}
}
}
اگرچه wizard و spells ممکن است در جداول مختلف پایگاه داده ذخیره شوند، یک کوئری GraphQL میتواند هر دو را به صورت همزمان درخواست کند.
سیستم تایپ قوی GraphQL
GraphQL دارای سیستم Type است که امکان تعریف تایپهای مختلف مانند scalars (مقادیر اولیه مثل string، boolean و عدد) و تایپهای پیچیدهتر مثل object را میدهد. سرور با استفاده از اسکیما میتواند اعتبارسنجی کوئری را قبل از اجرا بررسی کند.
type Spell {
name: String
manaCost: Int
attack: Int
}
قابلیت Introspection
به کمک introspection، کلاینت و ابزارهای مختلف میتوانند ساختار اسکیما را جویا شوند. ابزارهایی مانند GraphiQL این امکان را فراهم میآورند تا در مرورگر کوئری نوشته و آزمایش شود.
عملکرد GraphQL در سمت سرور
توسعه یک API GraphQL در سمت سرور اتفاق میافتد، جایی که اسکیما تعریف و پیادهسازی میشود. کلاینت از طریق کوئریهای توصیفی تعیین میکند چه دادهای میخواهد و این باعث میشود توسعه سریعتر و مستقلتر پیش برود.
GraphQL در لایه اپلیکیشن بین کلاینت و داده قرار میگیرد و معمولاً از یک endpoint واحد مانند /graphql خدماتدهی میکند. گرافکیوال میتواند روی هر پروتکل حمل داده شود اما معمولاً روی HTTP اجرا میشود.
میتوان سرور GraphQL را با هر زبان برنامهنویسی ساخت؛ برای مثال از میانافزار express-graphql در Node.js استفاده کرد تا API بر مبنای express ایجاد شود. همچنین داده میتواند از هر پایگاه دادهای مثل MySQL، PostgreSQL، MongoDB یا حتی ترکیبی از چند REST API تامین شود، به شرطی که در اسکیما تعریف شده باشد.
عملیات در GraphQL
درخواستها به GraphQL به صورت document ارسال میشود که شامل عملیات مختلفی مانند query برای خواندن و mutation برای نوشتن دادهها است.
کلاینتها و روش درخواستها
اگرچه کلاینتهای پیشرفتهای مانند Apollo Client یا Relay وجود دارد که caching و امکانات بیشتر ارائه میدهند، هیچ کلاینت خاصی برای ارسال درخواست به سرور GraphQL اجباری نیست. میتوان با fetch یا XMLHttpRequest از مرورگر درخواست ارسال کرد.
fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `{
wizard(id: "1") {
name
race
}
}` }),
})
.then(res => res.json())
.then(data => console.log(data));
مقایسه GraphQL و REST
GraphQL و REST هر دو برای ارتباط بین سیستمها استفاده میشوند اما مفاهیم و کاربردهای متفاوتی دارند. REST یک سبک معماری نرمافزار است، با ویژگیهای خاص مانند ایستایی، قابلیت cache و رابط یکنواخت. APIهای RESTful چندین endpoint مجزا دارند در حالی که GraphQL برای تبادل داده از یک endpoint واحد استفاده میکند.
- معماری: REST شامل چند endpoint مختلف است اما GraphQL همه دادهها را از یک endpoint دریافت میکند و میتواند دادههای پیچیدهای را با یک درخواست برگرداند.
- دریافت داده: REST دادههایی را که سرور تعیین میکند میفرستد و ممکن است کم یا زیاد باشد، اما GraphQL دقیقاً همان دادهای که کلاینت میخواهد باز میگرداند و از over- و under-fetching جلوگیری میکند.
- خطاها: GraphQL معمولاً همیشه پاسخ HTTP ۲۰۰ میدهد و خطاها را در بدنه پاسخ و با یک بخش errors ارسال میکند؛ در حالی که REST از کدهای مختلف HTTP برای خطاها و موفقیت استفاده میکند.
- نسخهبندی: GraphQL تلاش میکند به صورت backward compatible کار کند و نسخهبندی کمتر رایج است اما در REST معمولا endpointها با شماره نسخه مشخص میشوند.
- کشینگ: REST میتواند از مکانیزمهای کشینگ HTTP استفاده کند چون endpointهای مجزایی دارد، ولی GraphQL با endpoint واحد و کوئریهای متغیر نمیتواند از کشینگ HTTP بهره ببرد و باید توسط کلاینت مدیریت شود.
هر دو فناوری مزایا و معایب خود را دارند و میتوانند در کنار هم استفاده شوند؛ مثلاً GraphQL به عنوان دروازهای برای ترکیب چند REST API عمل کند.
جمعبندی
GraphQL یک زبان کوئری متنباز و رانتایم برای API است که برای رفع مشکلات REST مانند over-/under-fetching داده و کاهش تعداد درخواستها طراحی شده است. در این مقاله با مفهوم GraphQL، تفاوتها و شباهتهای آن با REST و نحوه عملکرد کلی آن آشنا شدید.
با تشکر از همراهی شما با پارمین کلود.






نظرات کاربران