Apa itu GraphQL? — GraphQL

Pernah panggil REST API dapet response 50 field padahal kamu cuma butuh `name` + `avatar`? Atau sebaliknya, butuh data dari 3 endpoint berbeda (user → posts →…

GraphQL adalah bahasa untuk menanyakan data ke sebuah API (query language), sekaligus mesin di server yang menjalankan pertanyaan itu. Client menulis field apa saja yang dia butuhkan, dan server menjawab dengan JSON yang bentuknya sama dengan pertanyaannya. Bayangin formulir di loket toko buku: kamu tulis "judul, harga, nama penulis" untuk buku nomor 1, petugas mengisi tiga kotak itu saja, dengan urutan yang sama, lalu mengembalikan formulirnya.

🧪 Tebakan cepat: Kamu minta field isbn, padahal server gak punya field itu. Apa jawabannya: isbn diisi null dan field lain tetap dikirim, atau seluruh query ditolak? Jawabannya ada di bagian "Kalau ada yang salah: errors".

Masalahnya: halaman detail buku

Contoh di seluruh jalur GraphQL ini adalah Toko Buku, toko yang sama dengan di jalur API: tiga buku dan empat penulis.

id title Penulis price stock
1 Laskar Pelangi Andrea Hirata 89000 12
2 Bumi Manusia Pramoedya Ananta Toer 125000 0
3 Cantik Itu Luka Eka Kurniawan 110000 5

Penulis keempat, Ahmad Tohari, belum punya buku di toko.

Halaman detail buku cuma butuh tiga hal: judul, harga, dan nama penulis. Dengan REST, client memanggil dua URL:

GET https://api.tokobuku.test/books/1
→ {"id":1,"title":"Laskar Pelangi","author_id":1,"price":89000,"stock":12}   (72 byte)

GET https://api.tokobuku.test/authors/1
→ {"id":1,"name":"Andrea Hirata"}   (31 byte)

Totalnya 2 request berurutan, 103 byte diterima. Hitungan di sini cuma body JSON, tanpa header HTTP.

Query pertamamu

Dengan GraphQL, client menulis apa yang dibutuhkan dalam satu query:

query {
  book(id: 1) {
    title
    price
    author {
      name
    }
  }
}

Server menjawab:

{
  "data": {
    "book": {
      "title": "Laskar Pelangi",
      "price": 89000,
      "author": {
        "name": "Andrea Hirata"
      }
    }
  }
}

Satu request, 92 byte diterima. Gak ada field yang berlebih, dan gak perlu request kedua.

Satu endpoint, dikirim lewat POST

API GraphQL biasanya cuma punya satu URL, misalnya https://api.tokobuku.test/graphql. Semua query dikirim ke situ. Yang membedakan tiap permintaan bukan URL-nya, tapi isi query-nya. Dari JavaScript, cukup pakai fetch biasa:

const response = await fetch("https://api.tokobuku.test/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query: "{ book(id: 1) { title price author { name } } }" }),
});
const result = await response.json();
console.log(result.data.book.author.name); // "Andrea Hirata"

Kalau ada yang salah: errors

Response GraphQL punya dua tempat: data untuk hasilnya, errors untuk masalahnya. Coba minta field yang gak ada, misalnya isbn:

query {
  book(id: 1) {
    title
    isbn
  }
}
{
  "errors": [
    {
      "message": "Cannot query field \"isbn\" on type \"Book\".",
      "locations": [{ "line": 4, "column": 5 }]
    }
  ]
}

Gak ada data sama sekali. Server memeriksa seluruh query sebelum menjalankannya, namanya validasi. Satu field yang gak dikenal sudah cukup bikin seluruh query ditolak, jadi title pun gak dikirim. Itu jawaban tebakannya. locations menunjuk baris 4 kolom 5, tempat isbn ditulis.

Beda lagi kalau query-nya valid tapi gagal waktu dijalankan, misalnya book(id: 99) padahal buku nomor 99 gak ada (query-nya sama dengan di atas, cuma id-nya 99 dan field-nya title saja):

{
  "errors": [
    {
      "message": "Book not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["book"]
    }
  ],
  "data": {
    "book": null
  }
}

Sekarang data ada, isinya book: null, dan errors menjelaskan kenapa. path menunjuk field yang gagal. Pesan "Book not found" ditulis sendiri oleh server Toko Buku. Status HTTP untuk dua kasus ini dibahas di pelajaran berikutnya.

Yang menentukan field apa saja yang ada: schema

Server GraphQL punya schema: daftar type dan field yang boleh diminta, beserta type nilainya. Potongan schema Toko Buku:

type Query {
  book(id: ID!): Book
}

type Book {
  title: String!
  price: Int!
  author: Author!
}

Tiap field punya resolver, yaitu fungsi di server yang mencari nilainya, misalnya membaca dari database. Schema lengkapnya dibahas di pelajaran "Schema & Type System".

⚠️ Jebakan yang sering ketemu

📌 Spesifikasinya

GraphQL dibuat di Facebook tahun 2012, lalu dibuka sebagai standar terbuka tahun 2015, dan sekarang dikelola GraphQL Foundation. Aturannya ditulis di spesifikasi di spec.graphql.org: rilis terbarunya edisi September 2025, sebelumnya edisi Oktober 2021, dan ada working draft untuk perubahan yang sedang dikerjakan. Spesifikasi itu sengaja gak mengatur HTTP. Cara mengirim GraphQL lewat HTTP ditulis di spesifikasi terpisah, GraphQL over HTTP, yang masih berstatus draft.

Server GraphQL ada di banyak bahasa: graphql-js (implementasi rujukan di JavaScript), Apollo Server, GraphQL Yoga, Lighthouse untuk Laravel, dan lainnya. Semuanya mengikuti spesifikasi yang sama, jadi bentuk query dan response-nya sama. Lab di halaman ini memakai mesin GraphQL kecil yang pesan error-nya disamakan dengan graphql-js 17.0.2.

TL;DR: GraphQL adalah query language untuk API: client menulis field yang dibutuhkan, server menjawab dengan JSON yang bentuknya sama, gak lebih dan gak kurang. Itu mengatasi over-fetching (data kebanyakan) dan under-fetching (data kurang sehingga butuh request tambahan): halaman detail buku turun dari 2 request REST (103 byte) jadi 1 query (92 byte). Semua query dikirim lewat POST ke satu endpoint, body-nya {"query": "..."}. Response-nya punya data, errors, atau keduanya: query yang gak valid ditolak utuh tanpa data, sedangkan field yang gagal waktu dijalankan jadi null dengan penjelasan di errors. Field apa saja yang ada ditentukan schema, dan nilainya dicari oleh resolver.

Yang akan kamu pelajari