Brief by evilfactorylabs

Brief by evilfactorylabs • Untuk obrolan makan siangmu seputar dunia pemrograman. Terbit sebelum jam 13.37 WIB setiap hari Senin & Selasa.

GraphQL

Like "SELECT something, anotherThing from someSource" but for API.

Arsitektur dalam membuat sebuah aplikasi web semakin kompleks modern. Dari Monolithic, Microservices, sampai ke yang paling panas: Serverless. Sebagaimana evolusi yang terjadi dalam membuat bangunan "nyata" juga, rancangan disesuaikan dengan zaman; kebutuhan, dan tentunya biaya yang ada pada waktu sekarang.

Tren Service-oriented architecture yang membuat pemisahan antara Service Provider (API) & Service Consumer (UI) seperti dari microservices dan backend for frontend pun mulai banyak digunakan demi alasan availability; reliability, modularity, reusability, dan produktivitas.

Pada dasarnya prosesnya adalah client melakukan request ke server secara, lalu server memberikan response yang bisa dikonsumsi oleh client entah itu dalam format plain text, binary, HTML, XML, ataupun JSON.

Proses "pertukaran" diatas bisa via protokol HTTP/1.1 (REST), HTTP/2 (gRPC), ataupun WebSocket tergantung kebutuhan & konteks. Yang paling umum adalah REST, meskipun bisa menggunakan protokol HTTP/2 juga tapi response yang diterima tetaplah UTF-8 yang biasanya berbentuk JSON.

Facebook's scale data-fetching problem

Facebook adalah salah satu sosial media terbesar yang pastinya memiliki jumlah pengguna yang sangat banyak. Selain itu, Facebook juga memberikan kesempatan kepada 3rd-party developer untuk mengembangkan aplikasi yang dibuat diatas platform Facebook.

Salah satu hal yang paling sulit dalam merancang & mengembangkan API adalah versioning, baik dari sisi penambahan ataupun penghapusan. Kita tidak akan berdebat antara SOA vs ROA, mari kita fokus di versioning saja dibagian ini.

API adalah tentang komunikasi antara client dan server yang biasanya melibatkan data, dan Facebook adalah sebuah aplikasi yang memiliki; menampilkan, dan membutuhkan banyak data.

Dan seperti yang kita tau, ada biaya yang harus dibayar dalam melakukan request. Adalah latensi yang paling laris. Jika melihat salah satu halaman yang ada di Facebook, lihat kira-kira ada berapa request yang harus dilakukan?

Facebook Timeline's page (old design) - Sumber

Perlu diingat, untuk menampilkan UI beserta datanya Facebook mostly melakukannya di client-side. Silahkan hitung ada berapa request kira-kira yang dilakukan di halaman tersebut?

Meet GraphQL, a query language for your API

Bagaimana bila kita bisa mengambil banyak data (yang kompleks) dalam satu request? Bagaimana bila kita bisa membuat API tanpa mempusingkan versioning, namun tetap menjaga codebase kita mudah dipelihara?

Ya, GraphQL salah duanya menjawab pertanyaan tersebut. Yang mana, adalah masalah yang dihadapi oleh Facebook juga, mengingat GraphQL adalah tool yang dipelopori oleh Facebook.

Di landing page nya, GraphQL menawarkan "only ask & get data you need" dan type system sebagai fitur utamanya.

Tidak lupa dengan "no API versioning" nya mengingat kita tidak berurusan dengan URI (path, in this context), mime type, dan HTTP method di GraphQL.

Konsep dasarnya, GraphQL memiliki 3 fondasi: Queries, Resolvers, dan Schema.

Query adalah tentang data yang diinginkan, Resolver adalah tentang "yang memproses" query, dan Schema adalah tentang struktur yang merefleksikan data tersebut.

GraphQL adalah query language untuk API, bukan sebuah ataupun query language untuk database. Pikirkan seperti SELECT column, anotherColumn from someTable tapi untuk API dan ya, memiliki type system.

Mari kita bahas satu-satu seputar fondasinya.

Query

Bagaimana cara mengambil data pengguna logged in via REST API? Sederhana, tinggal kirim GET request ke API endpoint (misal /v1/me), lalu client akan mendapatkan response yang berisi data tersebut berformat JSON berdasarkan "session" yang diterima oleh API.

Bagaimana bila ingin hanya mengambil data userId dan email saja? Bisa via validasi di server (bawa "parameter query" contohnya) atau bisa dilakukan di client (via map atau reduce misalnya).

Bagaimana bila ingin mengambil data "teman" dari user tersebut? Bisa request ke /v1/friends dengan membawa userId sebagai parameter, atau bisa ke /v1/<user_id>/friends tergantung desain.

Dan ya, bagaimana bila ingin mengambil data teman namun hanya bagian name dan profilePic nya saja? Sama seperti contoh yang sudah kita sebut.

Yang pastinya harus mengambil data dari /v1/me dulu, bukan?

Di GraphQL, mungkin "gambarannya" sesingkat ini:

query {
  User {
    userId
    email
    friends {
      name
      profilePic
    }
  }
}

Maka data yang didapat persis dengan data yang diminta, misal seperti ini:

{
  "data": {
    "User": {
      "userId": "666xnxxl0lz",
      "email": "[email protected]",
      "friends": [{
        "name": "teman",
        "profiePic": "https://someprofile.wtf/teman.png"
      }]
    }
  }
} 

Ter-prediksi, tidak overload, dan produktif (yang berkaitan dengan Schema)

Resolvers

Resolver adalah tentang bagaimana memproses query yang masuk oleh API. Sebagai contoh, bila kita mengambil kasus diatas, mungkin resolvernya adalah seperti ini (di Node.js):

const resolvers = {
  Query: {
    User: async (id) => await getUserById(id) // from your model
  },
  UserSchema: {
    userId: parent => parent.id,
    email: parent => parent.email,
    friends: parent => getFriendsFromUserId(parent.id)
  }
}

Kurang lebih seperti itu, yang biasanya bisa juga di generate secara otomatis via tool untuk membuat resolver. Menggunakan graphqlgen dari Prisma salah satunya.

Schema

Schema adalah tentang data. Pikirkan tentang "struktur" data yang memiliki type. Mengambil dari contoh diatas, mungkin skemanya seperti ini kurang lebih:

type User {
  userId: String!
  email: String!
  friends: [Friend]!
}

Benefitnya, sama seperti benefit yang didapat ketika kita menggunakan type system: Validasi & Produktivitas. Untuk produktivitas di GraphQL adalah seperti ini misalnya:

https://graphql-pokemon.now.sh/

API sudah ter-dokumentasi, bisa "dicoba langsung", dan lebih terprediksi.

Miskonsepsi

Ada beberapa kesalahpahaman yang terjadi ketika mempelajari GraphQL.

GraphQL is a "database"

Bukan, GraphQL bukanlah MySQL, Postgres, ataupun MongoDB yakni sebuah database engine.

Jangan memusingkan "query language" dari QL adalah tentang SELECT * FROM BLABLABLA di SQL yang bertugas untuk mengambil data. QL di GraphQL mengarah ke API, bukan ke database. Singkatnya, it's like SELECT * FROM BLABLABLA but the * refer to "data" (payload) and BLABLABLA refer to "path" (in REST API term).

GraphQL works "automagically"

Biasanya ini terjadi kepada yang mempelajari GraphQL dari sumber yang diterbitkan oleh perusahaan yang membuat "implementasi" dari GraphQL Server.

Ya, GraphQL hanyalah sebuah spesifikasi.

Pikirkan tentang JavaScript, yang implementasinya adalah v8; SpiderMonkey, dan JSCore.

Implementasi untuk GraphQL ada di 2 target: Server & Client. Di lingkungan server ada graphql-js dan Apollo Server, dan di lingkungan client ada Apollo Client, Relay, dan masih banyak lagi.

GraphQL berada didepan API mu. Jika sebuah "ilustrasi" API mu sebelumnya adalah seperti ini:

[client] <--> [service] <--> [database]

Ketika kita menggunakan GraphQL, nantinya akan menjadi seperti ini kurang lebih:

[client] <--> [graphql] <--> [service] <--> [database]

Dan dibagian "graphql" dan "service" itulah magic berada. Sayangnya, kamulah yang menulis mantranya.

...Atau bisa gunakan layanan pihak ketiga yang menawarkan "magic" alias merekalah yang "menulis mantranya" untukmu.

GraphQL is only for JavaScript

Padahal gak juga, banyak implementasi yang diterapkan di server-side dan client-side yang dibuat bukan menggunakan JavaScript. Ada implementasi di Ruby, Go, Python, Kotlin, Swift, dll untuk dilingkungan client dan server nya.

Drawbacks

Ah, akhirnya.

Pertama (dan yang paling populer) adalah caching. Karena pertama proses "query" dilakukan di client dan kedua dikirim via HTTP POST. Dibanding dengan menggunakan REST biasa, caching bisa dilakukan di level jaringan.

Karena di "tradisional" REST, kita menggunakan "resource" sebagai identifier (/v1/posts). Di GraphQL, kita hanya mengakses 1 endpoint (biasanya /graphql) dan juga data yang diminta sangat unik (mungkin request pertama kita hanya minta data A, di request kedua minta data B, C, D).

Tapi masalah caching ini biasanya sudah di solve di level library (client) seperti Apollo berdasarkan strategi yang ada.

Kedua, biaya waktu. Pertama, kita harus membuat skema terlebih dahulu (cerita klasik typing system). Kedua, ada "waktu tambahan" untuk melakukan parsing query. Ketiga, ya, waktu untuk belajar. Karena GraphQL adalah teknologi yang masih "panas".

Terakhir, terlalu overkill untuk aplikasi yang kecil. Biasanya GraphQL lebih cocok untuk yang menggunakan arsitektur Microservices dan juga tidak sedikit yang menjadikannya sebagai API Gateway.

Jika aplikasi kita belum sekompleks yang harus diselesaikan oleh GraphQL, sepertinya lebih baik menggunakan tradisional REST aja? Dan hey, apakah tim kita sudah familiar dengan hal-hal yang ada di GraphQL?

GraphQL users in Indonesia

Sejauh ini yang saya tau antara lain Hijup, Sorabel, Tokopedia, Tiket, dan Kumparan.

Penutup

Ya, GraphQL is great.

Dia bisa mengurangi jumlah request yang harus dikirim oleh client, bisa mengambil data yang hanya dibutuhkan, bisa melakukan "self documenting" API, dsb.

Tapi sekali lagi, apakah kita sedang "benar-benar" membutuhkan sebuah teknologi bernama GraphQL ini dengan segala fitur dan implementasinya?

Karena bagaimanapun, teknologi hadir untuk lebih mempermudah pekerjaan manusia, bukan malah bikin nambah ribet.

Menikmati tulisan ini?

Blog ini tidak menampilkan iklan, yang berarti blog ini didanai oleh pembaca seperti kamu. Gabung bersama Loading... yang telah membantu blog ini agar terus bisa mencakup tulisan yang lebih berkualitas dan bermanfaat!

Pendukung

Dukung Mengapa saya harus mendukung?
You've successfully subscribed to Brief by evilfactorylabs
Great! Next, complete checkout for full access to Brief by evilfactorylabs
Welcome back! You've successfully signed in
Success! Your account is fully activated, you now have access to all content.