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:

http
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 followers

Burada 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.

REST: üç sorğu və artıq sahələr; GraphQL: bir sorğu və məhz lazım olan məlumat
REST: üç sorğu və artıq sahələr; GraphQL: bir sorğu və məhz lazım olan məlumat

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ə:

graphql
query ProfileScreen {
  user(id: 42) {
    name
    posts(last: 2) {
      title
    }
    followersCount
  }
}

Və serverin cavabı:

json
{
  "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.

Sorğunun hər sahəsi cavabda öz yerini tapır
Sorğunun hər sahəsi cavabda öz yerini tapır

💡 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əliyyatNə üçünREST-də oxşarı
queryməlumatın oxunmasıGET
mutationyaratma, dəyişdirmə, silməPOST, PUT, PATCH, DELETE
subscriptionreal vaxt hadisələriWebSocket 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:

graphql
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:

  1. 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.
  2. Ö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.
  3. 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:

  1. Parse (təhlil) — sorğunun mətni sintaksis ağacına çevrilir. Unudulmuş mötərizə — xəta artıq bu addımdadır.
  2. Validate (yoxlama) — sorğu sxemlə tutuşdurulur: sahələr mövcuddurmu, arqumentlərin tipi düzgündürmü.
  3. 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.
  4. Respond (cavab) — nəticələr sorğu ilə eyni formada JSON-a yığılır: { "data": …, "errors": … }.
Parse → Validate → Execute → Respond
Parse → Validate → Execute → Respond

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:

bash
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:

json
{
  "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.ok yoxlamaqdır. GraphQL-də cavab 200 statusu ilə gəlib eyni zamanda xətalar da saxlaya bilər. errors sahəsini həmişə yoxlayın.

JavaScript-dən sorğu

Başlamaq üçün xüsusi kitabxana lazım deyil — adi fetch kifayətdir:

javascript
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); // Leyla

Də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ə

MeyarRESTGraphQL
Ünvanlarçoxlu endpoint (/users, /posts)bir endpoint (/graphql)
Məlumatın formasıserver müəyyən edirmüştəri müəyyən edir
Artıq və çatışmayan məlumattez-tez rast gəlinən problemsorğunun özü ilə həll olunur
Tiplər və sənədlərOpenAPI — istəyə görəsxem məcburidir
Versiyalaşdırma/v1, /v2sxemin təkamülü və @deprecated
HTTP keşləməsadə: GET və Cache-Controldaha çətin: adətən POST, keş müştəridə
XətalarHTTP statuslarıerrors massivi, status adətən 200
Faylların yüklənməsitəbiiayrıca həllər vasitəsilə
Başlanğıc çətinliyiaş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 /graphql və üç ə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 errors massivində, ç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.