GraphQL Basics — API

GraphQL adalah query language untuk API yang dikembangkan oleh Facebook (2015). Perbedaan utama dengan REST: Aspek REST GraphQL Endpoint Banyak (/users…

GraphQL adalah cara lain meminta data dari API: client menulis bentuk data yang dia mau, dan server menjawab persis bentuk itu, lewat satu endpoint (biasanya /graphql). Bayangin warung yang cuma jual paket. Pesan "paket nasi goreng" selalu dapat nasi, telur, kerupuk, dan acar, walaupun kamu cuma mau nasi dan telur. Mau es teh? Antre lagi di meja minuman. GraphQL itu formulir pesanan: kamu centang yang kamu mau, kirim sekali, dan yang datang persis yang dicentang.

🧪 Tebakan cepat: kamu minta book(id: 99), padahal buku 99 gak ada. Status HTTP berapa yang kamu terima? Tebak dulu, jawabannya ada di bagian "Error datang dengan status 200".

Masalah REST yang mau diselesaikan

Layar daftar buku di aplikasi Toko Buku cuma butuh judul buku dan nama penulisnya. Dengan REST, client melakukan ini:

Request Yang datang Yang dipakai
GET /books/1 id, title, author_id, price, stock title saja
GET /authors/1 id, name name saja

Dua masalah sekaligus:

Untuk 3 buku, layar itu butuh 1 request daftar buku plus 3 request penulis: 4 request.

Query pertamamu

Dengan GraphQL, client menulis query, operasi untuk membaca data:

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

Jawabannya:

{ "data": { "book": { "title": "Laskar Pelangi", "price": 89000 } } }

Relasi dalam satu request

Field bisa bersarang. Penulis buku diminta di dalam buku itu:

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

Jawabannya {"data": {"book": {"title": "Laskar Pelangi", "author": {"name": "Andrea Hirata"}}}}. Satu request, dua "tabel", tanpa field yang gak dipakai. Over-fetching dan under-fetching hilang. Field yang isinya objek (author) wajib punya selection set sendiri; field biasa (title) gak boleh punya.

Schema: daftar yang boleh diminta

Server GraphQL punya schema, daftar type dan field yang boleh diminta:

type Query {
  book(id: Int!): Book
  books: [Book!]!
}

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

type Author {
  id: Int!
  name: String!
  books: [Book!]!
}

Minta field yang gak ada di schema, misalnya isbn, dan query ditolak sebelum jalan dengan pesan Cannot query field "isbn" on type "Book". Banyak server (Apollo, misalnya) menjawabnya dengan 400 tanpa data.

Mutation: mengubah data

Operasi yang mengubah data (create, update, delete) namanya mutation. Bentuknya sama dengan query, cuma kata kuncinya beda:

mutation {
  createBook(title: "Ronggeng Dukuh Paruk", authorId: 4, price: 95000) {
    id
    title
  }
}

Argumen membawa datanya, dan selection set memilih apa yang mau dibaca balik dari buku barunya: {"data": {"createBook": {"id": 4, "title": "Ronggeng Dukuh Paruk"}}}.

Latihan memakai schema blog, polanya sama persis. User nomor 1 dengan nama dan judul tulisannya, lalu user baru, dalam satu dokumen:

query AmbilUser { user(id: 1) { name posts { title } } }

mutation BuatUser { createUser(name: "Andi", email: "[email protected]") { id name email } }

Satu dokumen yang berisi dua operasi wajib memberi nama keduanya (AmbilUser, BuatUser), supaya server tahu mana yang dijalankan. Tanpa nama, dokumennya ditolak dengan This anonymous operation must be the only defined operation.

Memanggil GraphQL dari JavaScript

Semua operasi masuk ke satu URL dengan POST. Query-nya dikirim sebagai teks di dalam body JSON:

const res = await fetch("https://api.tokobuku.test/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query: "query { book(id: 1) { title price } }" }),
});
const { data, errors } = await res.json();

Error datang dengan status 200

Query book(id: 99) lolos validasi (field dan argumennya benar), lalu server mencari dan gak ketemu. Jawabannya tetap 200 OK, dan kabar buruknya ada di body:

{ "errors": [{ "message": "Book not found", "path": ["book"] }], "data": { "book": null } }

Itu jawaban tebakannya: 200. Di REST, GET /books/99 menjawab 404. Di GraphQL, satu request bisa berisi beberapa field, dan sebagian bisa berhasil sementara yang lain gagal, jadi status HTTP gak bisa mewakili semuanya. path menunjuk field yang gagal. Karena itu client wajib mengecek errors, bukan cuma status.

🤔 Kapan GraphQL, kapan REST

⚠️ Jebakan yang sering ketemu

TL;DR: GraphQL memakai satu endpoint (POST /graphql); client menulis bentuk data yang dia mau, jadi gak ada over-fetching (field berlebih) dan under-fetching (request tambahan). query membaca, mutation mengubah data. book(id: 1) { title author { name } }: field, argumen, dan selection set yang bisa bersarang; field objek wajib punya selection set. Schema menentukan apa yang boleh diminta; field yang gak ada ditolak sebelum jalan. Error saat menjalankan query datang dengan status 200 dan array errors, jadi selalu cek errors.

Yang akan kamu pelajari