57 Pengenalan WebSocket untuk Real-time GraphQL
Web telah berevolusi jauh dari sekadar dokumen HTML statis yang dikirim dari server ke browser. Sekarang, pengalaman pengguna menuntut interaksi yang real-time, sinkronisasi data instan, dan responsifitas ekstrem. Dalam dunia aplikasi modern, baik itu fitur chat, dashboard yang auto-refresh, atau feed yang terus diperbarui—semuanya membutuhkan satu hal: komunikasi real-time antara client dan server.
GraphQL telah menjadi standar de facto untuk API di banyak perusahaan karena fleksibilitas dan efisiensinya. Namun, bagaimana bila aplikasi kita membutuhkan update data yang bersifat real-time? Di sinilah WebSocket hadir dan berintegrasi mulus dengan GraphQL melalui fitur yang dikenal sebagai subscriptions.
Artikel ini akan membahas konsep dasar WebSocket, bagaimana ia bekerja dengan GraphQL, cara mengimplementasikan subscriptions, serta best practice-nya. Kita akan membahas kode, simulasi, tabel perbandingan, dan diagram alur. Ini bukan sekadar tutorial, melainkan peta jalan bagi siapapun yang ingin menghadirkan real-time pada API mereka.
Apa itu WebSocket?
WebSocket adalah protokol komunikasi network yang menyediakan saluran dua-arah (full-duplex) antara client dan server melalui koneksi TCP tunggal. WebSocket berbeda dengan HTTP yang tradisional (request-response), karena WebSocket memungkinkan server dapat mengirim pesan ke client kapan pun, tanpa harus menunggu request.
Kapan WebSocket Lebih Baik daripada HTTP?
HTTP (Polling/Long Polling) | WebSocket |
---|---|
Client harus memulai semua request | Server dapat push data ke client secara spontan |
Overhead besar, setiap request seperti handshake baru | Cuma 1 kali handshake, selanjutnya ringan |
Latensi lebih tinggi untuk data real-time | Latensi serendah mungkin |
Cocok untuk konten statis atau CRUD tradisional | Cocok untuk chat, notifikasi, game, live dashboard, dll |
GraphQL dan WebSocket: Mengapa Harus Subscriptions?
GraphQL memiliki tiga operation utama:
- Query: Mengambil data.
- Mutation: Mengubah data.
- Subscription: Mendengarkan perubahan data.
Subscriptions inilah fitur yang memungkinkan client mendapatkan data real-time begitu ada perubahan di server, melalui channel WebSocket.
Alur Data: Query vs Subscription
Query:
- Client mengirim query GraphQL (HTTP).
- Server mengembalikan response sekali saja.
- Koneksi selesai.
Subscription:
- Client membuka koneksi WebSocket.
- Client subscribe ke event tertentu.
- Setiap ada event atau perubahan, server push data secara otomatis ke client.
- Koneksi terus aktif selama client butuh.
Mari lihat diagram sederhana alur WebSocket dengan mermaid:
sequenceDiagram participant C as Client participant S as Server C->>S: Membuka koneksi WebSocket C->>S: Mengirim GraphQL Subscription S->>C: Kirim ACK (Berhasil subscribe) loop Setiap ada perubahan data S->>C: Kirim data terbaru (event) end C-->>S: Tutup koneksi WebSocket
Implementasi Dasar: GraphQL Subscription dengan WebSocket
Kita akan gunakan stack populer: Node.js (Express), Apollo Server, dan graphql-ws.
Setup Server
Install dependencies:npm install express apollo-server-express graphql graphql-ws
Schema GraphQL (subscription, query, mutation)
// schema.js const { gql } = require('apollo-server-express'); module.exports = gql` type Message { id: ID! content: String! user: String! } type Query { messages: [Message!] } type Mutation { postMessage(content: String!, user: String!): ID! } type Subscription { messagePosted: Message! } `;
Resolvers dengan PubSub
// resolvers.js const { PubSub } = require('graphql-subscriptions'); const pubsub = new PubSub(); const messages = []; module.exports = { Query: { messages: () => messages }, Mutation: { postMessage: (_, { content, user }) => { const id = messages.length + 1; const message = { id, content, user }; messages.push(message); pubsub.publish('MESSAGE_POSTED', { messagePosted: message }); return id; } }, Subscription: { messagePosted: { subscribe: () => pubsub.asyncIterator(['MESSAGE_POSTED']) } } };
Apollo Server + graphql-ws
// index.js const express = require('express'); const { ApolloServer } = require('apollo-server-express'); const { createServer } = require('http'); const { useServer } = require('graphql-ws/lib/use/ws'); const { WebSocketServer } = require('ws'); const typeDefs = require('./schema'); const resolvers = require('./resolvers'); async function start() { const app = express(); const httpServer = createServer(app); const apolloServer = new ApolloServer({ typeDefs, resolvers }); await apolloServer.start(); apolloServer.applyMiddleware({ app }); // WebSocket server const wsServer = new WebSocketServer({ server: httpServer, path: '/graphql', }); useServer({ schema: apolloServer.schema }, wsServer); httpServer.listen(4000, () => { console.log(`🚀 Server siap di http://localhost:4000${apolloServer.graphqlPath}`); console.log(`⚡ WS siap di ws://localhost:4000/graphql`); }); } start();
Client Subscriptions
Jika pakai Apollo Client di React:import { createClient } from 'graphql-ws'; import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { getMainDefinition } from '@apollo/client/utilities'; const wsLink = new GraphQLWsLink(createClient({ url: 'ws://localhost:4000/graphql', })); const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql', }); // Split based on operation type const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, httpLink ); const client = new ApolloClient({ link: splitLink, cache: new InMemoryCache(), });
Contoh subscribe di React:
import { gql, useSubscription } from '@apollo/client'; const MESSAGE_POSTED = gql` subscription { messagePosted { id content user } } `; function Chat() { const { data } = useSubscription(MESSAGE_POSTED); // render chat messages pakai data }
Simulasi: Workflow Real-time Chat
- User A mengirim pesan via mutation
postMessage
. - Server publish event ke semua subscriber.
- Semua client dengan subscription
messagePosted
otomatis menerima pesan baru tanpa reload.
Tabel Perbandingan Subscription vs Polling
Fitur | Polling setInterval | GraphQL Subscription (WebSocket) |
---|---|---|
Latency | Tertunda hingga interval | Hampir instan, waktu nyata |
Resource Server | Banyak connection & CPU | Satu koneksi & scalable |
Pengiriman Data | Tidak efisien, fetch ulang | Hanya data event terbaru |
Skala | Kurang baik | Dirancang untuk fanout ribuan client |
Real-time | Semu | Otentik real-time |
Best Practices dan Tantangan
- Scalability: Gunakan broker pub-sub (seperti Redis) untuk multi-instance server.
- Security: Selalu lakukan autentikasi saat handshake WebSocket.
- Backpressure & Disconnect: Siapkan logic untuk menangani jaringan buruk atau client disconnect.
- Protocol: Gunakan
graphql-ws
(bukan subscriptions-transport-ws, yang deprecated). - Monitoring: Pantau koneksi aktif dan throughput WebSocket.
Penutup
WebSocket + GraphQL Subscriptions adalah kunci menghadirkan aplikasi real-time yang scalable dan elegan. Implementasinya memang teknis, tapi dengan fondasi yang kokoh, kita dapat membangun fitur kolaborasi, notifikasi, dan pelaporan instan hanya dengan beberapa baris kode tambahan dari API GraphQL biasa.
Ingat, real-time bukan lagi kemewahan, tapi kebutuhan mutlak aplikasi masa kini.
Ingin mengulik lebih jauh? Coba tambahkan Redis PubSub untuk scaling, atau gunakan paket seperti Hasura untuk pebangunan GraphQL real-time out of the box. Selamat berkreasi!
Referensi:
79. gRPC Logging Terstruktur dengan Zap
Artikel Terhangat
79. gRPC Logging Terstruktur dengan Zap
08 Aug 2025
56 Apa Itu Subscription di GraphQL?
08 Aug 2025
78. Men-deploy gRPC Service di Docker
08 Aug 2025
77. gRPC di Kubernetes dengan LoadBalancer
08 Aug 2025
54 Menambahkan Rate Limiting dan Throttling
08 Aug 2025
76. Menyambungkan gRPC Service dengan Kafka
08 Aug 2025

79. gRPC Logging Terstruktur dengan Zap

56 Apa Itu Subscription di GraphQL?

78. Men-deploy gRPC Service di Docker

77. gRPC di Kubernetes dengan LoadBalancer

54 Menambahkan Rate Limiting dan Throttling
