Apa Itu GraphQL?
November 4, 2022
Apa Itu GraphQL? Seberapa Populer Itu?
GraphQL adalah bahasa manipulasi query yang berorientasi pada API yang dirilis oleh Facebook pada tahun 2015. Berbeda dengan desain API lainnya, GraphQL memungkinkan klien untuk membentuk pernyataan query berdasarkan struktur data yang telah disepakati sebelumnya dan memungkinkan server untuk mengurai pernyataan tersebut dan hanya mengembalikan data yang diperlukan. Dengan cara ini, GraphQL memberikan kekayaan dan fleksibilitas sambil menghindari kehilangan performa yang disebabkan oleh data yang berlebihan, yang membuat GraphQL menjadi pilihan yang bagus untuk aplikasi yang memerlukan penanganan banyak objek data yang kompleks.
Pada tahun 2018, GraphQL merilis spesifikasi lengkap dan versi stabil. Pada tahun yang sama, Facebook menyumbangkan proyek GraphQL ke GraphQL Foundation di bawah Linux Foundation. Sejak itu, GraphQL telah diadopsi oleh banyak proyek open-source dan organisasi komersial. Hingga saat ini, ada beberapa implementasi utama GraphQL di sisi klien di pasaran. Implementasi di sisi server tersedia dalam semua bahasa pemrograman server utama, bahkan dalam bahasa niche seperti D dan R.
Beberapa Skenario Nyata dan Tantangan untuk GraphQL
Contoh paling terkenal dari GraphQL adalah API GraphQL GitHub.
Sebelum mengadopsi GraphQL, GitHub menyediakan REST API untuk mengekspos data kaya yang dihasilkan oleh jutaan proyek yang dihosting, yang sangat sukses sehingga menjadi model untuk ditiru ketika merancang REST API. Namun, seiring dengan bertambahnya jumlah objek data dan bidang dalam objek tersebut, REST API mulai menunjukkan semakin banyak kelemahan. Di sisi server, GitHub harus menetapkan batasan ketat pada frekuensi panggilan untuk mengurangi biaya karena jumlah data yang dihasilkan dengan setiap panggilan. Di sisi pengembang, mereka harus menghadapi batasan ini karena meskipun satu panggilan mengembalikan banyak data, sebagian besar data tersebut tidak berguna. Untuk mendapatkan informasi tertentu, pengembang sering kali perlu meluncurkan beberapa query dan kemudian menulis banyak kode perekat untuk menyatukan data yang bermakna dari hasil query menjadi konten yang diinginkan. Dalam prosesnya, mereka juga harus mematuhi batasan "jumlah panggilan".
Oleh karena itu, Github mengadopsi GraphQL segera setelah dirilis. GitHub menjadi "duta besar" GraphQL, menyampaikan aplikasinya kepada ribuan pengembang. API GraphQL sekarang menjadi pilihan utama untuk Github. Sejak pengumuman pertama dukungan untuk GraphQL, GitHub telah memposting beberapa artikel tentang GraphQL setiap tahun. Untuk memungkinkan pengembang bermigrasi ke GraphQL, GitHub telah menulis aplikasi query interaktif khusus untuk tujuan ini: https://docs.github.com/en/graphql/overview/explorer. Pengembang dapat mempelajari cara menulis GraphQL melalui aplikasi ini.
Namun, GraphQL bukanlah obat mujarab. Baru-baru ini, GitHub menghentikan implementasi GraphQL sendiri untuk API paket. Banyak orang juga mulai mendiskusikan beberapa kekurangan GraphQL. Banyak masalah dengan GraphQL berasal dari fakta bahwa strukturnya sangat berbeda dari standar HTTP sehingga tidak ada cara mudah untuk memetakan beberapa konsep GraphQL ke dalam struktur seperti path/header HTTP. Memperlakukan GraphQL sebagai API HTTP normal memerlukan pekerjaan pengembangan tambahan. Akibatnya, pengembang yang ingin mengelola API GraphQL mereka sendiri harus menggunakan gateway API yang mendukung GraphQL.
Bagaimana APISIX Mendukung GraphQL
Saat ini, APISIX mendukung routing dinamis melalui beberapa properti GraphQL. Dengan kemampuan ini, kita dapat menerima hanya permintaan GraphQL tertentu atau memiliki GraphQL yang berbeda yang diteruskan ke upstream yang berbeda.
Ambil contoh pernyataan GraphQL berikut:
query getRepo { owner { name } repo { created } }
APISIX mengekstrak tiga properti GraphQL berikut untuk routing:
- graphql_operation
- graphql_name
- graphql_root_fields
Dalam pernyataan GraphQL di atas:
graphql_operationsesuai denganquerygraphql_namesesuai dengangetRepographql_root_fieldssesuai dengan["owner", "repo"]
Mari buat rute untuk menunjukkan kemampuan routing halus APISIX untuk GraphQL:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' { "methods": ["POST"], "uri": "/graphql", "vars": [ ["graphql_operation", "==", "query"], ["graphql_name", "==", "getRepo"], ["graphql_root_fields", "has", "owner"] ], "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:2022": 1 } } }'
Selanjutnya, gunakan permintaan dengan pernyataan GraphQL untuk mengakses:
curl -i -H 'content-type: application/graphql' \ -X POST http://127.0.0.1:9080/graphql -d ' query getRepo { owner { name } repo { created } }' HTTP/1.1 200 OK ...
Kita dapat melihat bahwa permintaan mencapai upstream karena pernyataan query cocok dengan ketiga kondisi.
Sebaliknya, jika kita mengakses dengan pernyataan yang tidak cocok, misalnya, bidang owner tidak disertakan:
curl -i -H 'content-type: application/graphql' \ -X POST http://127.0.0.1:9080/graphql -d ' query getRepo { repo { created } }' HTTP/1.1 404 Not Found ...
Ini tidak akan cocok dengan aturan routing yang sesuai.
Kita juga dapat membuat rute yang memungkinkan pernyataan yang tidak mengandung bidang owner untuk diarahkan ke upstream lain:
curl http://127.0.0.1:9180/apisix/admin/routes/2 \ -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' { "methods": ["POST"], "uri": "/graphql", "vars": [ ["graphql_operation", "==", "query"], ["graphql_name", "==", "getRepo"], ["graphql_root_fields", "!", "has", "owner"] ], "upstream": { "type": "roundrobin", "nodes": { "192.168.0.1:2022": 1 } } }'
curl -i -H 'content-type: application/graphql' \ -X POST http://127.0.0.1:9080/graphql -d ' query getRepo { repo { created } }' HTTP/1.1 200 OK ...
Prospek Dukungan APISIX untuk GraphQL di Masa Depan
Selain routing dinamis, APISIX mungkin juga akan memperkenalkan lebih banyak operasi berdasarkan bidang tertentu dari GraphQL di masa depan. Misalnya, API GraphQL GitHub memiliki formula khusus untuk pembatasan kecepatan, dan kita dapat menerapkan aturan serupa untuk mengubah satu permintaan GraphQL menjadi jumlah "panggilan virtual" yang sesuai untuk mencapai pembatasan kecepatan khusus GraphQL.
Kita juga dapat memikirkan masalah ini dengan cara yang berbeda. Aplikasi itu sendiri masih menyediakan REST API, dan gateway mengubah permintaan GraphQL menjadi permintaan REST dan mengubah respons REST menjadi respons GraphQL di lapisan terluar. API GraphQL yang disediakan dengan cara ini dapat melakukan fungsi seperti RBAC, pembatasan kecepatan, caching, dll., tanpa mengembangkan plugin khusus. Dari sudut pandang teknis, ide ini tidak terlalu sulit untuk diimplementasikan. Lagi pula, pada tahun 2022, bahkan REST API cenderung menyediakan spesifikasi OpenAPI sebagai skema, yang hanya transfer antara skema GraphQL dan skema OpenAPI, ditambah dengan penyaringan bidang khusus GraphQL. (Tentu saja, saya harus mengakui bahwa saya belum mempraktikkannya sendiri. Mungkin ada tantangan dalam beberapa detail yang belum teratasi.)
Pembaca yang cermat akan menemukan bahwa API GraphQL yang dikonversi dengan cara ini hanya dapat beroperasi pada satu model pada satu waktu, yang jelas tidak memenuhi persyaratan fleksibilitas GraphQL dan tidak lebih dari REST API yang berpakaian GraphQL. Namun, GraphQL memiliki konsep yang disebut schema stitching yang memungkinkan implementator untuk menggabungkan beberapa skema bersama.
Sebagai contoh, kita memiliki dua API, satu disebut GetEvent dan yang lainnya disebut GetLocation, yang masing-masing mengembalikan tipe Event dan Location.
type Event { id: string location_id: string } type Location { id: string city: string } type Query { GetEvent(id: string): Event GetLocation(id: string): Location }
Kita dapat menambahkan konfigurasi yang menggabungkan kedua API ini menjadi API baru yang disebut GetEventWithLocation, yang terlihat seperti ini:
type EventWithLocation { id: string location: Location } type Query { GetEventWithLocation(id: string): EventWithLocation }
Implementasi spesifik dari penggabungan diselesaikan oleh gateway. Dalam contoh di atas, gateway membagi API menjadi dua, memanggil GetEvent untuk mendapatkan location_id dan kemudian GetLocation untuk mendapatkan data gabungan.
Singkatnya, dengan mengubah REST menjadi GraphQL, setiap REST API dapat diubah menjadi model GraphQL yang sesuai; dan dengan bantuan schema stitching, beberapa model dapat digabungkan menjadi satu API GraphQL. Dengan cara ini, kita dapat membangun API GraphQL yang kaya dan fleksibel di atas REST API yang ada dan mengelola plugin tertentu pada tingkat granularitas REST API. Desain ini secara tidak sengaja menyelesaikan beberapa masalah orkestrasi API. Seperti dalam contoh di atas, kita mengambil output dari satu API (Event.location_id) sebagai input dari API lain (Location.id).