Mobil tətbiqdə profil ekranını təsəvvür edin: istifadəçinin adı, son iki postu və izləyicilərinin sayı. Sadə tapşırıqdır — amma API REST üzərində qurulubsa, tətbiq üç fərqli ünvana üç sorğu göndərməli olacaq və hər cavab ekrana lazım olandan daha çox sahə qaytaracaq. Bu dərsdə GraphQL-in hansı problemi həll etdiyini, necə qurulduğunu və nə vaxt onu seçməyin (və seçməməyin) lazım olduğunu araşdıracağıq.
Problem: bir ekran — çoxlu sorğu
REST-də hər resursun öz ünvanı var. Profil ekranını yığmaq üçün müştəri (client) belə edir:
GET /users/42 → id, name, email, avatar, createdAt, settings…
GET /users/42/posts → every post in full: text, tags, dates…
GET /users/42/followers → the full list of followersBurada eyni anda iki problem var:
- Under-fetching (məlumatın azlığı) — bir sorğu kifayət etmir, bir neçəsini göndərmək lazım gəlir. Mobil internetdə serverə hər əlavə «gediş-gəliş» (round trip) yüzlərlə millisaniyəyə başa gəlir.
- Over-fetching (artıq məlumat) — server resurs haqqında bildiyi hər şeyi qaytarır, ekrana isə 2–3 sahə lazımdır. Artıq kilobaytlar trafik və batareya sərf edir.
Adətən bu problemləri /users/42/profile-screen kimi xüsusi endpoint-lərlə «müalicə» edirlər. Amma ekranlar çoxalır, veb və mobil tətbiqin ehtiyacları fərqlidir — və backend demək olar ki, eyni olan marşrutlar zooparkına çevrilir.
GraphQL nədir
GraphQL — API üçün sorğu dili və bu sorğuları serverdə icra edən mühitdir. Onu 2012-ci ildə Facebook-da mobil tətbiqlər üçün yaradıblar, 2015-ci ildə hamı üçün açıblar, indi isə dilin inkişafı ilə müstəqil GraphQL Foundation məşğul olur.
Əsas ideya: müştəri ona lazım olan məlumatın formasını özü təsvir edir, server isə məhz bunu qaytarır — nə artıq, nə əskik. Bütün sorğular bir ünvana (endpoint) gedir, adətən /graphql.
Həmin profil ekranı — bir sorğu ilə:
query ProfileScreen {
user(id: 42) {
name
posts(last: 2) {
title
}
followersCount
}
}Və serverin cavabı:
{
"data": {
"user": {
"name": "Leyla",
"posts": [
{ "title": "Hello GraphQL" },
{ "title": "Schemas 101" }
],
"followersCount": 128
}
}
}Diqqət edin: cavab sorğunun formasını təkrarlayır. name istədiniz — name aldınız. email istəmədiniz — cavabda o yoxdur. Cavabın kökü həmişə data obyektidir.
💡 GraphQL verilənlər bazası deyil və konkret dil üçün kitabxana da deyil — bu, spesifikasiyadır. GraphQL serverlərini JavaScript, Python, Go, Java, PHP və digər dillərdə yazırlar, məlumat isə istənilən yerdə ola bilər: PostgreSQL, MongoDB, başqa REST API və ya keşdə.
Üç əməliyyat növü
| Əməliyyat | Nə üçün | REST-də oxşarı |
|---|---|---|
query | məlumatın oxunması | GET |
mutation | yaratma, dəyişdirmə, silmə | POST, PUT, PATCH, DELETE |
subscription | real vaxt hadisələri | WebSocket və ya SSE |
Sorğuları (query) növbəti dərslərdə ətraflı araşdıracağıq, mutation-lara və subscription-lara da ayrıca mövzular həsr olunub.
Sxem — frontend və backend arasında müqavilə
GraphQL serveri öz məlumatını həmişə sxem ilə — tiplər və sahələr toplusu ilə təsvir edir. Sxemi SDL (Schema Definition Language) dilində yazırlar:
type User {
id: ID!
name: String!
posts(last: Int): [Post!]!
followersCount: Int!
}
type Post {
id: ID!
title: String!
}
type Query {
user(id: ID!): User
}Sxem üç mühüm üstünlük verir:
- Ciddi tipləşdirmə. Server hansı sahələrin mövcud olduğunu və onların tipini əvvəlcədən bilir. Mövcud olmayan sahəsi olan sorğu hələ icradan əvvəl rədd edilir.
- Özünü sənədləşdirmə. Sxemi serverin özündən soruşmaq olar (buna introspection deyilir), buna görə Apollo Sandbox kimi alətlər sənədləri və avtomatik tamamlamanı göstərir.
- Müqavilə. Frontend və backend sxem barədə razılaşır və sonra paralel işləyir: backend sorğuları hələ reallaşdırarkən frontend onları yaza bilər.
! işarəsi «sahə heç vaxt null olmur» deməkdir. Bütün tipləri növbəti dərsdə ətraflı araşdıracağıq.
Server sorğunu necə icra edir
GraphQL serverinə gələn hər sorğu eyni dörd mərhələdən keçir:
- Parse (təhlil) — sorğunun mətni sintaksis ağacına çevrilir. Unudulmuş mötərizə — xəta artıq bu addımdadır.
- Validate (yoxlama) — sorğu sxemlə tutuşdurulur: sahələr mövcuddurmu, arqumentlərin tipi düzgündürmü.
- Execute (icra) — sorğuda istənilən hər sahə üçün məlumatı gətirən resolver funksiyası çağırılır: bazadan, başqa API-dən və ya keşdən.
- Respond (cavab) — nəticələr sorğu ilə eyni formada JSON-a yığılır:
{ "data": …, "errors": … }.
Texniki baxımdan GraphQL sorğusu JSON gövdəli adi HTTP POST sorğusudur. Onu hətta terminaldan da göndərmək olar:
curl -X POST http://localhost:4000/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ user(id: 42) { name followersCount } }"}'Xətalar və HTTP statusları
REST-də xəta barədə cavabın statusu xəbər verir: 404, 400, 500. GraphQL-də isə server adətən 200 OK cavabı verir, xətaları isə errors massivinə qoyur — əldə etməyin mümkün olduğu məlumatın yanında:
{
"data": { "user": null },
"errors": [
{
"message": "User 42 not found",
"path": ["user"],
"extensions": { "code": "NOT_FOUND" }
}
]
}path sahəsi xətanın sorğunun hansı sahəsində baş verdiyini, extensions.code isə müştərinin nə edəcəyinə qərar verdiyi maşınla oxunan kodu göstərir.
⚠️ Yeni başlayanların tez-tez etdiyi xəta — yalnız
response.okyoxlamaqdır. GraphQL-də cavab 200 statusu ilə gəlib eyni zamanda xətalar da saxlaya bilər.errorssahəsini həmişə yoxlayın.
JavaScript-dən sorğu
Başlamaq üçün xüsusi kitabxana lazım deyil — adi fetch kifayətdir:
const query = `
query ProfileScreen($id: ID!) {
user(id: $id) {
name
followersCount
}
}
`;
const res = await fetch('http://localhost:4000/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables: { id: '42' } }),
});
const { data, errors } = await res.json();
if (errors) console.error(errors);
else console.log(data.user.name); // LeylaDəyərlər sorğunun mətninə yapışdırılmır, ayrıca variables ilə ötürülür — bu həm təhlükəsiz, həm də rahatdır. Dəyişənləri sorğular haqqında dərsdə ətraflı araşdıracağıq.
REST, yoxsa GraphQL: müqayisə
| Meyar | REST | GraphQL |
|---|---|---|
| Ünvanlar | çoxlu endpoint (/users, /posts) | bir endpoint (/graphql) |
| Məlumatın forması | server müəyyən edir | müştəri müəyyən edir |
| Artıq və çatışmayan məlumat | tez-tez rast gəlinən problem | sorğunun özü ilə həll olunur |
| Tiplər və sənədlər | OpenAPI — istəyə görə | sxem məcburidir |
| Versiyalaşdırma | /v1, /v2 | sxemin təkamülü və @deprecated |
| HTTP keşləmə | sadə: GET və Cache-Control | daha çətin: adətən POST, keş müştəridə |
| Xətalar | HTTP statusları | errors massivi, status adətən 200 |
| Faylların yüklənməsi | təbii | ayrıca həllər vasitəsilə |
| Başlanğıc çətinliyi | aşağı | yüksək: sxem, resolver-lər, alətlər |
GraphQL-i nə vaxt seçmək lazımdır
- Məhsulun bir neçə müştərisi var (veb, iOS, Android) və onlara eyni məlumatın fərqli hissələri lazımdır.
- Məlumatlar güclü əlaqəlidir (istifadəçilər → postlar → şərhlər → müəlliflər) və ekranlar onları müxtəlif kombinasiyalarda yığır.
- Frontend sürətlə dəyişir və hər ekran üçün yeni endpoint gözləmək istəmir.
- Bir neçə servis üzərində vahid şlüz lazımdır — BFF (Backend for Frontend) pattern-i.
Məsələn, GitHub və Shopify-ın açıq GraphQL API-ləri var.
REST nə vaxt daha sadə və yaxşıdır
- Sadə CRUD və bir-iki forma — GraphQL fayda vermədən mürəkkəblik əlavə edəcək.
- HTTP keşləmə və CDN vacib olan açıq API.
- Fayllar və binar məlumatla çox iş.
- Backend-i hələ yenicə öyrənən kiçik komanda.
💡 REST və GraphQL düşmən deyil. Bir çox şirkət hər ikisindən istifadə edir: REST — webhook-lar və faylların yüklənməsi üçün, GraphQL — tətbiqin məlumatları üçün.
Ekosistem
- Apollo Server, GraphQL Yoga — Node.js üçün serverlər. Kursda Apollo Server-dən istifadə edirik.
- Apollo Client, urql, Relay — React və digər freymvorklar üçün keşləməli müştərilər.
- GraphQL Code Generator — sxemdən və sorğulardan TypeScript tiplərini yaradır.
- Apollo Sandbox, GraphiQL — avtomatik tamamlama və sənədlərlə sorğular üçün «qum qutuları».
Nəticələr
- GraphQL — API üçün sorğu dilidir: müştəri lazım olan sahələri təsvir edir, server məhz onları qaytarır.
- Bir endpoint
/graphqlvə üç əməliyyat növü:query,mutation,subscription. - Sxem tipləri təsvir edir və frontend ilə backend arasında müqavilə rolunu oynayır.
- Sorğu parse → validate → execute → respond mərhələlərindən keçir; sahələr üçün məlumatı resolver-lər gətirir.
- Xətalar
errorsmassivində, çox vaxt 200 statusu ilə birlikdə gəlir. - GraphQL əlaqəli məlumat və fərqli müştərilər üçün yaxşıdır; sadə CRUD üçün çox vaxt REST kifayətdir.