GraphQL কী? API এবং ডেটা ফেচিং-এর জন্য পরিষ্কার গাইড
জানুন GraphQL কী, কোয়েরি, মিউটেশন এবং স্কিমা কীভাবে কাজ করে, কখন REST-এর বদলে এটি ব্যবহার করবেন—প্রায়োগিক সুবিধা, অসুবিধা ও উদাহরণ সহ।

GraphQL কী (এবং কী নয়)
GraphQL হচ্ছে একটি কোয়েরি ল্যাংগুয়েজ এবং API-এর জন্য রনটাইম। সরলভাবে: এটা এমন একটি উপায় যার মাধ্যমে একটি অ্যাপ (ওয়েব, মোবাইল বা অন্য কোনো সার্ভিস) পরিষ্কার, গঠনভিত্তিক রিকোয়েস্ট ব্যবহার করে এক API-কে ডেটা চাইতে পারে—আর সার্ভার সেই রিকোয়েস্টের সাথে মেলে এমন রেসপন্স ফেরত দেয়।
সমস্যাগুলো যা এটি সমাধান করে
অনেক API ক্লায়েন্টকে নির্দিষ্ট এন্ডপয়েন্ট যা দেয় সেটাই গ্রহণ করতে বাধ্য করে। এতে প্রায়ই দুটি সমস্যা দেখা দেয়:
- ওভার‑ফেচিং: এমন ফিল্ড ডাউনলোড করা যা আপনি ব্যবহার করছেন না।
- আন্ডার‑ফেচিং: একটি স্ক্রিন সাজাতে একাধিক রিকুয়েস্ট করতে হয়।
GraphQL-এ, ক্লায়েন্ট ঠিকমাত্রা ফিল্ডই চাইতে পারে—না বেশি, না কম। এটি বিশেষভাবে উপকারী যখন বিভিন্ন স্ক্রিন বা অ্যাপ একই মূল ডেটার বিভিন্ন "কাট" চায়।
GraphQL কোথায় অবস্থান করে
GraphQL সাধারণত ক্লায়েন্ট অ্যাপ ও আপনার ডেটা সোর্সগুলোর মাঝখানে থাকে। ওই ডেটা সোর্সগুলো হতে পারে:
- ডাটাবেস
- বিদ্যমান REST সার্ভিস
- তৃতীয়‑পার্টি API
- মাইক্রোসার্ভিস
GraphQL সার্ভার একটি কোয়েরি গ্রহণ করে, প্রতিটি অনুরোধকৃত ফিল্ড কোথা থেকে আনা হবে তা নির্ধারণ করে, এবং পরে চূড়ান্ত JSON রেসপন্স সাজায়।
একটি দ্রুত মানসিক মডেল
GraphQL-কে ভাবুন কাস্টম‑আকৃতির রেসপন্স অর্ডার করার মতো:
- ক্লায়েন্ট চাহিদার আকৃতি বর্ণনা করে।
- সার্ভার সেই সঠিক আকৃতির ডেটা ফেরত দেয় (সম্ভব হলে)।
GraphQL কী নয়
কিছু ভুল ধারণা পরিষ্কার করে বলা দরকার:
- এটি কোনো ডাটাবেস নয় (এটি আপনার ডেটা সংরক্ষণ করে না)।
- এটি স্বয়ংক্রিয়ভাবে দ্রুত নয় (অপ্রয়োজনীয় ডেটা ট্রান্সফার কমাতে পারে, কিন্তু সার্ভারের কাজ এখনও প্রভাব ফেলে)।
- এটি "REST 2.0" নয় (এটি ভিন্ন শক্তি এবং ট্রেড‑অফ সহ একটি বিকল্প API পদ্ধতি)।
যদি আপনি সেই মূল সংজ্ঞা—কোয়েরি ল্যাংগুয়েজ + API-এর জন্য রনটাইম—মনে রাখেন, তাহলে বাকি বিষয়গুলো বোঝা সহজ হবে।
কেন GraphQL তৈরি করা হয়েছিল
GraphQL তৈরি হয়েছিল একটি প্রায়োগিক প্রোডাক্ট সমস্যার সমাধানে: টিমগুলো UI স্ক্রিনের জন্য API-কে মানিয়ে নিতে অনেকটা সময় নষ্ট করছিল।
পারম্পরিক এন্ডপয়েন্ট‑ভিত্তিক API প্রায়ই বাধ্য করে যে হয় আপনি অপ্রয়োজনীয় ডেটা ছাড়বেন অথবা যে ডেটাগুলো লাগবে তা পেতে একাধিক কল করতে হবে। প্রোডাক্ট বাড়ার সাথে সাথে এই ঘর্ষণ ধীর পেজ, জটিল ক্লায়েন্ট কোড এবং ফ্রন্টএন্ড‑ব্যাকএন্ড সমন্বয়ের কষ্টে পরিণত হয়।
যে যন্ত্রণাগুলো GraphQL লক্ষ্য করে
ওভার‑ফেচিং ঘটে যখন একটি এন্ডপয়েন্ট "সম্পূর্ণ" অবজেক্ট কী দেয়, যদিও একটি স্ক্রিনে শুধু কয়েকটি ফিল্ডই দরকার। উদাহরণ: মোবাইল প্রোফাইল ভিউতে শুধুমাত্র নাম ও অবতার লাগে, কিন্তু API ঠিকানাগুলো, প্রেফারেন্স, অডিট ফিল্ড ইত্যাদি ফেরত দেয়—এটি ব্যান্ডউইথ নষ্ট করে এবং ইউজার এক্সপেরিয়েন্সকে ক্ষতিগ্রস্ত করতে পারে।
আন্ডার‑ফেচিং এর বিপরীত: কোনো একক এন্ডপয়েন্টে প্রয়োজনীয় সবকিছু না থাকলে ক্লায়েন্টকে একাধিক রিকুয়েস্ট করে রেজাল্টগুলো জোড়া লাগাতে হয়। এতে লেটেন্সি বাড়ে এবং আংশিক ব্যর্থতার সম্ভাবনা বেড়ে যায়।
ক্রমাগত ভার্সন বাম্প ছাড়াই API বিবর্তন
অনেক REST‑স্টাইল API পরিবর্তনের জবাবে নতুন এন্ডপয়েন্ট যোগ করে বা ভার্সনিং (v1, v2, v3) করে। ভার্সনিং প্রয়োজনীয় হলেও এতে দীর্ঘমেয়াদি রক্ষণাবেক্ষণের কাজ বাড়ে: পুরোনো ক্লায়েন্টরা পুরোনো ভার্সন ব্যবহার করে যায়, আর নতুন ফিচার অন্য জায়গায় জমা হয়।
GraphQL-এর পদ্ধতি হলো স্কিমা বাড়ানো—নতুন ফিল্ড ও টাইপ যোগ করা—এভাবে বিদ্যমান ফিল্ডগুলো স্থিতিশীল রেখে। এতে অনেক সময় নতুন UI প্রয়োজনের জন্য আলাদা ভার্সন তৈরি করার চাপে কম পড়ে।
এক API, বহু ক্লায়েন্ট
আধুনিক প্রোডাক্ট সাধারণত একাই কনজিউমার রাখে না। ওয়েব, iOS, Android এবং পার্টনার ইন্টেগ্রেশন প্রতিটি ভিন্ন ডেটা আকৃতি চায়।
GraphQL যাতে করে প্রত্যেক ক্লায়েন্টই ঠিক প্রয়োজনীয় ফিল্ড চাইতে পারে—ব্যাকএন্ডকে প্রতিটি স্ক্রিন বা ডিভাইসের জন্য আলাদা এন্ডপয়েন্ট তৈরি করতে বাধ্য না করেই—এমনভাবে ডিজাইন করা হয়েছে।
GraphQL স্কিমা: API চুক্তি
একটি GraphQL API এর সংজ্ঞা তার স্কিমা দ্বারা নির্ধারিত। এটিকে সার্ভার ও সকল ক্লায়েন্টের মধ্যে থাকা চুক্তি হিসেবে ভাবুন: এটি বলে কোন ডেটা আছে, কীভাবে সেটা সংযুক্ত, আর কী চাওয়া বা বদলানো যাবে। ক্লায়েন্টগুলি এন্ডপয়েন্ট অনুমান করে না—তারা স্কিমা পড়ে নির্দিষ্ট ফিল্ড অনুরোধ করে।
স্কিমার বুনিয়াদি: টাইপ, ফিল্ড, সম্পর্ক
স্কিমা টাইপ (যেমন User বা Post) এবং ফিল্ড (যেমন name বা title) দিয়ে গঠিত। ফিল্ডগুলো অন্য টাইপের কাছে নির্দেশ করতে পারে—এভাবেই GraphQL সম্পর্ক মডেল করে।
নিচে Schema Definition Language (SDL)-তে একটি সহজ উদাহরণ আছে:
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String
author: User!
comments: [Comment!]!
}
type Comment {
id: ID!
text: String!
author: User!
post: Post!
}
শক্তিশালী টাইপিং = এক্সিকিউশনের আগে ভ্যালিডেশন
স্কিমা স্ট্রংলি টাইপড হওয়ায়, GraphQL একটি রিকুয়েস্ট চালানোর আগে তা ভ্যালিডেট করতে পারে। যদি ক্লায়েন্ট এমন কোনো ফিল্ড চায় যা নেই (উদাহরণ: Post.publishDate যখন স্কিমায় নেই), সার্ভার স্পষ্ট ত্রুটি দিয়ে রিকুয়েস্ট বাতিল বা আংশিকভাবে পূরণ করতে পারে—অনিশ্চিত "হয়তো কাজ করে" আচরণ ছাড়াই।
সময়ের সঙ্গে নিরাপদে বিবর্তন
স্কিমা বাড়ানোর জন্য ডিজাইন করা—সাধারণত নতুন ফিল্ড যোগ করলে বিদ্যমান ক্লায়েন্ট ভাঙে না, কারণ ক্লায়েন্ট শুধু যা চেয়েছে তাই পায়। ফিল্ড সরানো বা পরিবর্তন করা সংবেদনশীল, তাই টিমগুলো প্রায়ই প্রথমে ফিল্ড ডিপ্রিকেট করে ক্লায়েন্টগুলো ধীরে ধীরে মাইগ্রেট করে।
কোয়েরি: ঠিক যা দরকার তাই চাওয়া
একটি GraphQL API সাধারণত একটি এন্ডপয়েন্ট (উদাহরণ: /graphql) দিয়ে প্রকাশ করা হয়। বিভিন্ন রিসোর্সের জন্য অনেক URL (যেমন /users, /users/123, /users/123/posts) থাকার বদলে আপনি এক স্থানে একটি কোয়েরি পাঠিয়ে ঠিক কোন ডেটা চান তা বর্ণনা করেন।
ফিল্ড নির্বাচন (নেস্টেড ডেটাসহ)
কোয়েরি হলো মূলত একটি "শপিং লিস্ট" ফিল্ডগুলোর। আপনি সহজ ফিল্ড (যেমন id, name) এবং নেস্টেড ডেটা (যেমন ইউজারের সাম্প্রতিক পোস্ট) একই অনুরোধে চাইতে পারেন—বিনা অপ্রয়োজনীয় ফিল্ড ডাউনলোড করে।
নিচে একটি ছোট উদাহরণ আছে:
query GetUserWithPosts {
user(id: "123") {
id
name
posts(limit: 2) {
id
title
}
}
}
প্রত্যাশিত রেসপন্স আকৃতি
GraphQL রেসপন্সগুলো প্রেডিক্টেবল: আপনি যে JSON পাবেন তা আপনার কোয়েরির স্ট্রাকচারকে অনুকরণ করে। এটা ফ্রন্টএন্ডে কাজ করা সহজ করে, কারণ আপনাকে আর অনুমান করতে হয় না ডেটা কোথায় থাকবে।
সরলীকৃত রেসপন্সের আউটলাইন এরকম হতে পারে:
{
"data": {
"user": {
"id": "123",
"name": "Sam",
"posts": [
{ "id": "p1", "title": "Hello GraphQL" },
{ "id": "p2", "title": "Queries in Practice" }
]
}
}
}
আপনি যদি কোন ফিল্ড ন চান তা রেসপন্সে থাকবে না। আপনি যদি চান, আপনি নির্দিষ্ট স্থানে তা পাবেন—ফ্রন্টএন্ডের জন্য GraphQL কোয়েরিগুলোকে প্রতিটি স্ক্রিন বা ফিচারের প্রয়োজন অনুযায়ী ডেটা আনার পরিষ্কার উপায় বানায়।
মিউটেশন: ডেটা নিরাপদে লেখা
কোয়েরি পড়ার জন্য; মিউটেশন হল GraphQL API-তে কিভাবে আপনি ডেটা পরিবর্তন করেন—রেকর্ড তৈরি, আপডেট বা ডিলিট।
সাধারণ মিউটেশন ফ্লো
বহু মিউটেশন একই প্যাটার্ন অনুসরণ করে:
- ইনপুট: ক্লায়েন্ট একটি স্ট্রাকচার্ড ইনপুট (প্রায়শই একটি
inputঅবজেক্ট) পাঠায়, যেমন কোন ফিল্ড আপডেট হবে। - ভ্যালিডেশন ও অথরাইজেশন: সার্ভার চেক করে যেমন আবশ্যক ফিল্ড, ডেটা ফরম্যাট, ইউনিকনেস, এবং ব্যবহারকারীর অনুমতি।
- রাইট: সার্ভার ডাটাবেস পরিবর্তন করে (বা অন্য সার্ভিস কল করে)।
- পেলোড/রিটার্ন টাইপ: সার্ভার একটি প্রত্যাশিত রেজাল্ট আকার রিটার্ন করে যাতে UI আপডেট করতে পারে।
কেন মিউটেশন ডেটা রিটার্ন করে
GraphQL মিউটেশন সাধারণত উদ্দেশ্যপ্রণোদিতভাবে ডেটা রিটার্ন করে, কেবল "success: true" নয়। আপডেট হওয়া অবজেক্ট (বা কমপক্ষে তার id ও গুরুত্বপূর্ণ ফিল্ড) রিটার্ন করলে UI:
- অতিরিক্ত রাউন্ড‑ট্রিপ ছাড়া স্ক্রিন দ্রুত আপডেট করতে পারে
- কেশ নিরাপদে রিফ্রেশ করতে পারে (উদাহরণ: Apollo Client)
- ক্ষেত্রভিত্তিক ত্রুটি প্রসঙ্গভিত্তিকভাবে দেখাতে পারে
একটি সাধারণ ডিজাইন হলো এমন একটি "পেলোড" টাইপ যা আপডেট হওয়া এনটিটি এবং যেকোনো এরর দুটোই অন্তর্ভুক্ত করে।
একটি বেসিক মিউটেশন উদাহরণ
mutation UpdateEmail($input: UpdateUserEmailInput!) {
updateUserEmail(input: $input) {
user {
id
email
}
errors {
field
message
}
}
}
UI‑চালিত API-এর জন্য একটি ভাল নিয়ম: পরবর্তী রাষ্ট্র রেন্ডার করার জন্য যা দরকার তা রিটার্ন করুন (উদাহরণ: আপডেট হওয়া user এবং কোনো errors)। এতে ক্লায়েন্ট সরল থাকে, কি পরিবর্তিত হয়েছে অনুমান করতে হয় না, এবং ব্যর্থতাগুলো সুন্দরভাবে হ্যান্ডল করা সহজ হয়।
রেজলভার: GraphQL কিভাবে ফলাফল তৈরি করে
একটি GraphQL স্কিমা বর্ণনা করে কি চাওয়া যেতে পারে। রেজলভারগুলো বর্ণনা করে তথ্য কিভাবে আসবে। একটি রেজলভার হলো আপনার স্কিমার নির্দিষ্ট ফিল্ডে সংযুক্ত একটি ফাংশন। ক্লায়েন্ট যখন ঐ ফিল্ড অনুরোধ করে, GraphQL ঐ রেজলভারকে কল করে মান আনতে বা গণনা করতে।
রেজলভারগুলো "ফিল্ড-লেভেল" ফাংশন
GraphQL একটি কোয়েরি চালানোর সময় অনুরোধকৃত আকৃতি ধরে হাঁটে। প্রতিটি ফিল্ডের জন্য, এটি মিলযুক্ত রেজলভার খুঁজে পায় এবং চালায়। কিছু রেজলভার সোজাসুজি একটি অবজেক্টের প্রোপার্টি রিটার্ন করে; অন্যরা ডাটাবেস কল করে, অন্য সার্ভিসকে কল করে, বা একাধিক সোর্স সংযুক্ত করে।
উদাহরণস্বরূপ, যদি আপনার স্কিমায় User.posts থাকে, তখন posts রেজলভারটি userId দ্বারা posts টেবিল কোয়েরি করতে পারে, বা আলাদা Posts সার্ভিস কল করতে পারে।
স্কিমা ফিল্ডগুলোকে ডেটা সোর্সের সাথে ম্যাপ করা
রেজলভারগুলো স্কিমা এবং আপনার বাস্তব সিস্টেমগুলোর মাঝের গ্লু:
- ডাটাবেস: SQL/NoSQL কুয়েরি, স্টোরড প্রসিডিউর, ORM কল
- সার্ভিস: REST/gRPC কল, ইনটারনাল মাইক্রোসার্ভিস, থার্ড‑পার্টি API
- কম্পিউটেড ফিল্ড: টোটাল, ফরম্যাটিং, ডেরাইভড ভ্যালু
এই ম্যাপিংটি নমনীয়: আপনি ব্যাকএন্ড ইমপ্লিমেন্টেশন পরিবর্তন করতে পারবেন ক্লায়েন্ট কোয়েরি আকৃতি অপরিবর্তিত থাকলেই।
পারফরম্যান্স: ধীর রেজলভার চেইন এড়ানো (N+1)
রেজলভারগুলো প্রতি ফিল্ড ও তালিকার প্রতিটি আইটেমে চালানো হতে পারে, তাই অসাবধানতায় অনেক ছোট কল ট্রিগার হতে পারে (উদাহরণ: 100 ইউজারের পোস্ট 100টি আলাদা কোয়েরি দিয়ে ফেচ করা)। এই "N+1" প্যাটার্ন রেসপন্সকে ধীর করে দিতে পারে।
সাধারণ সমাধান: বাচিং ও ক্যাশিং (উদাহরণ: আইডি সংগ্রহ করে একবারে ফেচ করা) এবং কোন নেস্টেড ফিল্ডে ক্লায়েন্টকে উৎসাহিত করবেন সেগুলো সম্পর্কে সচেতন হওয়া।
অথরাইজেশন ও ভ্যালিডেশন কোথায় হয়
অথরাইজেশন সাধারণত রেজলভারগুলিতে (বা শেয়ার্ড মিডলওয়্যারে) প্রয়োগ করা হয় কারণ রেজলভাররা জানে কে চাচ্ছে (কন্টেক্সটের মাধ্যমে) এবং কি ডেটা অ্যাক্সেস করছে। ভ্যালিডেশন সাধারণত দুই স্তরে হয়: GraphQL টাইপ/আকৃতি ভ্যালিডেশন স্বয়ংক্রিয়ভাবে করে, যখন রেজলভার ব্যবসায়িক নিয়ম (যেমন "শুধু অ্যাডমিনরা এই ফিল্ড সেট করতে পারবে") Enforce করে।
ত্রুটি ও আংশিক ফলাফল
GraphQL-এ নতুনদের জন্য একটি বিস্ময় হলো যে একটি রিকুয়েস্ট "সাফল্য" হতে পারে এবং তবুও ত্রুটি থাকতে পারে। তার কারণ GraphQL ফিল্ড-ওরিয়েন্টেড: কিছু ফিল্ড রেজলভ করা যায় এবং কিছু করা যায় না—তাই আপনি আংশিক ডেটা পেতে পারেন।
ত্রুটিগুলো কেমন দেখায়
একটি সাধারণ GraphQL রেসপন্সে data এবং একটি errors অ্যারে দুটোই থাকতে পারে:
{
"data": {
"user": {
"id": "123",
"email": null
}
},
"errors": [
{
"message": "Not authorized to read email",
"path": ["user", "email"],
"extensions": { "code": "FORBIDDEN" }
}
]
}
এটা দরকারী: ক্লায়েন্টের কাছে যা আছে তা রেন্ডার করার সুযোগ থাকে (উদাহরণ: ইউজার প্রোফাইল) এবং মিসিং ফিল্ডটি হ্যান্ডল করা যায়।
ফিল্ড-লেভেল ত্রুটি বনাম রিকুয়েস্ট-লেভেল ব্যর্থতা
- ফিল্ড-লেভেল ত্রুটি এক্সিকিউশনের সময় ঘটে (একটি রেজলভার থ্রো করে, পারমিশন চেক ব্যর্থ হয়, ডাউনস্ট্রীম সার্ভিস টাইমআউট)। অন্য ফিল্ডগুলো তখনও রেজলভ হতে পারে।
- রিকুয়েস্ট-লেভেল ব্যর্থতা এক্সিকিউশনকে বাধা দেয় (অবৈধ JSON, ম্যালফর্মড কোয়েরি, স্কিমা ভ্যালিডেশন ত্রুটি)। এই ক্ষেত্রে
dataপ্রায়ইnullহয়।
ইউজার‑ফ্রেন্ডলি মেসেজ দেয়া
এন্ড‑ইউজারের জন্য ত্রুটি মেসেজ লিখুন, ডিবাগিংয়ের জন্য নয়। স্ট্যাক ট্রেস, ডাটাবেস নাম বা অভ্যন্তরীণ আইডি এক্সপোজ করা এড়ান। ভালো প্যাটার্ন:
- একটি ছোট, নিরাপদ
message - একটি স্থির মেশিন‑রিডেবল
extensions.code - ঐচ্ছিক মেটাডেটা যা নিরাপদ (উদাহরণ:
retryable: true)
সার্ভার‑সাইডে বিস্তারিত লগ করুন রিকুয়েস্ট আইডির সঙ্গে যাতে অভ্যন্তরীণ তথ্য প্রকাশ না হয়।
ক্লায়েন্টগুলোর মধ্যে সামঞ্জস্যপূর্ণ হ্যান্ডলিং টিপস
নেটিভ ও ওয়েব অ্যাপগুলোর জন্য ছোট একটি ত্রুটি “চুক্তি” নির্ধারণ করুন: সাধারণ extensions.code মান (যেমন UNAUTHENTICATED, FORBIDDEN, BAD_USER_INPUT), কখন টোস্ট দেখানো হবে বনাম কখন ইনলাইন ফিল্ড ত্রুটি দেখাবেন, এবং আংশিক ডেটা কিভাবে হ্যান্ডল করবেন। এখানে সামঞ্জস্য থাকলে প্রতিটি ক্লায়েন্ট নিজে নিজে নিয়ম আবিষ্কার করবে না।
সাবস্ক্রিপশন: রিয়েল‑টাইম আপডেট
সাবস্ক্রিপশন হলো GraphQL‑এর উপায় ক্লায়েন্টদের ডেটা পরিবর্তিত হলে তা পুশ করে দেওয়ার, বারবার ক্লায়েন্টকে জিজ্ঞেস করার বদলে। এগুলো সাধারণত একটি স্থায়ী সংযোগ (সবচেয়ে সাধারণত WebSockets) করে দেওয়া হয়, যাতে সার্ভার কোনো ইভেন্ট ঘটলেই সাবস্ক্রাইবারদের পে-লোড পাঠাতে পারে।
সাবস্ক্রিপশন কি এবং কীভাবে কাজ করে
একটি সাবস্ক্রিপশন অনেকটা কোয়েরির মতো দেখায়, কিন্তু ফলাফল একক রেসপন্স নয়। এটি একটি রেসাল্ট স্ট্রিম—প্রতিটি আপডেট একটি ইভেন্ট উপস্থাপন করে।
অন্তর্ভুক্ত পদ্ধতিতে, ক্লায়েন্ট একটি টপিক সাবস্ক্রাইব করে (উদাহরণ: চ্যাট অ্যাপে messageAdded)। সার্ভার যখন ইভেন্ট প্রকাশ করে, কানেক্টেড সাবস্ক্রাইবাররা সাবস্ক্রিপশন‑এর সিলেকশন সেট অনুযায়ী পে‑লোড পায়।
সাধারণ ইউজ‑কেস
সাবস্ক্রিপশনগুলো তখন ভাল যখন ব্যবহারকারীরা তাত্ক্ষণিক পরিবর্তন আশা করে:
- চ্যাট মেসেজ রুমে রিফ্রেশ ছাড়াই আসা
- নোটিফিকেশন (মেনশন, অর্ডার স্টেটাস, অ্যালার্ট)
- লাইভ ড্যাশবোর্ড (সিস্টেম হেলথ, লজিস্টিক্স, ট্রেডিং, খেলার স্কোর)
সাবস্ক্রিপশন বনাম পোলিং
পোলিং-এ ক্লায়েন্ট প্রতি N সেকেন্ডে জিজ্ঞেস করে "কিছু নতুন আছে?"। এটা সহজ, কিন্তু যখন কিছুই পরিবর্তিত না হয় তখন অনুরোধ নষ্ট হয় এবং এখনও দেরি মনে হতে পারে।
সাবস্ক্রিপশন-এ সার্ভারই মুহূর্তেই আপডেট পাঠায়। এতে অনাবশ্যক ট্রাফিক কমে এবং অনুভূত গতি বাড়ে—কিন্তু সংযোগ খোলা রাখার ও রিয়েল‑টাইম ইনফ্রা পরিচালনার খরচ থাকে।
কখন সাবস্ক্রিপশন অপ্রয়োজনীয় জটিলতা
সাবস্ক্রিপশন সবসময় প্রয়োজনীয় নয়। যদি আপডেট কম ঘটে, সময়নিষ্ঠ না হয়, বা সহজে ব্যাচ করা যায়, তবে পোলিং বা ইউজার একশন পরে রি‑ফেচ করা যথেষ্ট। সাবস্ক্রিপশন অপারেশনাল ওভারহেড বাড়ায়: সংযোগ স্কেলিং, দীর্ঘজীবী সেশনের অথ, রিট্রাই ও মনিটরিং। নিয়ম: রিয়েল‑টাইম হলে ব্যবহার করুন—শুধু সুখের জন্য নয়।
সুবিধা, অসুবিধা ও ব্যবহারিক ট্রেড‑অফ
GraphQL প্রায়ই বলা হয় "ক্লায়েন্টকে ক্ষমতা দেয়", কিন্তু সেই ক্ষমতার দাম আছে। আগে থেকে ট্রেড‑অফগুলো জানা থাকলে সিদ্ধান্ত নেওয়া সহজ হয়—কখন GraphQL ভাল ফিট এবং কখন অতিরিক্ত জটিলতা।
GraphQL কোথায় উজ্জ্বল
বড় জয় হলো ফ্লেক্সিবল ডেটা ফেচিং: ক্লায়েন্ট ঠিক যে ফিল্ডগুলো চায় তা অনুরোধ করে, যা ওভার‑ফেচিং কমাতে পারে এবং UI পরিবর্তন দ্রুত করতে সাহায্য করে।
আরেকটি বড় সুবিধা হলো স্কিমা দ্বারা প্রদত্ত শক্তিশালী চুক্তি। স্কিমা টাইপ ও উপলব্ধ অপারেশনের একক সোর্স অফ ট্রুথ হয়ে ওঠে, যা সহযোগিতা ও টুলিং উন্নত করে।
টিমগুলো প্রায়ই দেখতে পায় ক্লায়েন্ট প্রোডাক্টিভিটি বাড়ে কারণ ফ্রন্ট‑এন্ড ডেভেলপাররা নতুন এন্ডপয়েন্টের জন্য অপেক্ষা না করেই ইটারেট করতে পারে, এবং Apollo Client মত টুল টাইপ জেনারেট করে ডেটা ফেচিং সহজ করে।
সাধারণ অসুবিধাগুলো পরিকল্পনা করতে হবে
GraphQL‑এ ক্যাশিং জটিল হতে পারে। REST‑এ ক্যাশিং প্রায়ই "প্রতি URL" ভিত্তিক। GraphQL‑এ অনেক কোয়েরি একই এন্ডপয়েন্ট শেয়ার করে, তাই ক্যাশিং কোয়েরি আকৃতি, নরমালাইজড ক্যাশ এবং সাবধানে সার্ভার/ক্লায়েন্ট কনফিগারেশনের ওপর নির্ভর করে।
সার্ভার সাইডে পারফরম্যান্স পিটফলস আছে। একটি ছোট কোয়েরিও অনেক ব্যাকএন্ড কল ট্রিগার করতে পারে যদি রেজলভারগুলো ঠিকমতো ডিজাইন না করা হয় (বাচিং, N+1 এড়ানো, ব্যয়বহুল ফিল্ড নিয়ন্ত্রণ দরকার)।
একটি শেখার বাঁকও আছে: স্কিমা, রেজলভার ও ক্লায়েন্ট প্যাটার্নগুলো ঐসব টিমের জন্য অপরিচিত হতে পারে যারা এন্ডপয়েন্ট‑ভিত্তিক API-এ অভ্যস্ত।
সিকিউরিটি ও অপারেশন
কারণ ক্লায়েন্ট অনেক কিছু চাইতে পারে, GraphQL API-তে কোয়েরি ডেপ্থ ও কমপ্লেক্সিটি লিমিট প্রয়োগ করা উচিত যাতে অপব্যবহার বা দুর্ঘটনাজনিত "অতিবড়" অনুরোধ প্রতিরোধ করা যায়।
অথেন্টিকেশন ও অথরাইজেশন per‑field স্তরে প্রয়োগ করা উচিত, শুধুই রুট‑লেভেলে নয়, কারণ বিভিন্ন ফিল্ডে ভিন্ন এক্সেস নিয়ম থাকতে পারে।
অপারেশনালি, GraphQL‑কে বোঝা যায় এমন লগিং, ট্রেসিং ও মনিটরিং-এ বিনিয়োগ করুন: অপারেশন নাম, ভ্যারিয়েবল (সাবধানে), রেজলভার টাইমিং এবং এরর রেট ট্র্যাক করুন যাতে ধীর কোয়েরি ও রিগ্রেশন দ্রুত ধরে ফেলতে পারেন।
GraphQL বনাম REST: তারা কিভাবে আলাদা
GraphQL এবং REST উভয়ই অ্যাপগুলোকে সার্ভারের সাথে কথা বলাতে সাহায্য করে, কিন্তু তারা সেই কথোপকথনকে ভিন্নভাবে গঠন করে।
REST সাধারণত কিভাবে কাজ করে
REST হলো রিসোর্স‑ভিত্তিক। আপনি বিভিন্ন এন্ডপয়েন্ট (URL) কল করে ডেটা নেন—/users/123 বা /orders?userId=123 এর মতো। প্রতিটি এন্ডপয়েন্ট সার্ভার দ্বারা নির্ধারিত একটি নির্দিষ্ট ডেটা আকার ফেরত দেয়।
REST এছাড়াও HTTP সেমান্টিক্স ব্যবহার করে: GET/POST/PUT/DELETE, স্ট্যাটাস কোড, ও ক্যাশিং নিয়ম। সহজ CRUD বা ব্রাউজার/প্রক্সি ক্যাশের সাথে কাজ করার সময় REST আরো স্বাভাবিক মনে হতে পারে।
GraphQL কিভাবে কাজ করে
GraphQL হলো স্কিমা‑ভিত্তিক। বহু এন্ডপয়েন্টের বদলে সাধারণত একটি এন্ডপয়েন্ট থাকে, এবং ক্লায়েন্ট একটি কোয়েরি পাঠায় যে ঠিক কোন ফিল্ডগুলো চায়। সার্ভার ঐ রিকুয়েস্টকে স্কিমার বিরুদ্ধে ভ্যালিডেট করে এবং কোয়েরির সাথে মেলে এমন রেসপন্স দেয়।
এই "ক্লায়েন্ট‑চালিত সেলেকশন" কারণেই GraphQL ওভার‑ফেচিং ও আন্ডার‑ফেচিং কমাতে পারে, বিশেষ করে এমন UI স্ক্রিনগুলোর জন্য যেগুলো একাধিক সম্পর্কিত মডেল থেকে ডেটা চায়।
কখন REST সহজ হতে পারে
REST সাধারণত ভাল ফিট যখন:
- আপনি ফাইল ডাউনলোড/আপলোড করছেন (স্ট্রিমিং, কনটেন্ট‑টাইপ, রেঞ্জ রিকুয়েস্ট)।
- আপনার API প্রধানত সরল CRUD এবং প্রেডিক্টেবল পে‑লোড।
- আপনি ব্রাউজার/এজ ক্যাশিং-এর উপর বেশ নির্ভরশীল।
হাইব্রিড পদ্ধতি সাধারণ
অনেক টিম দুটোই মিশিয়ে ব্যবহার করে:
- UI‑ফোকাসড ডেটা ফেচিং জন্য GraphQL ব্যবহার করা
- নির্দিষ্ট সার্ভিসের জন্য REST রাখা (যেমন auth callbacks, webhooks, ফাইল হ্যান্ডলিং, বা ইনটার্নাল মাইক্রোসার্ভিস)
প্রায়োগিক প্রশ্নটি হলো “কোনটা ভালো নয়—কোনটা এই ব্যবহার‑কেসে কম জটিলতার সাথে মানায়?”
কিভাবে একটি GraphQL API ডিজাইন করবেন (শुरুকারীদের চেকলিস্ট)
GraphQL API ডিজাইন করা সহজ হয় যখন আপনি এটিকে স্ক্রীন তৈরি করা লোকদের জন্য একটি প্রোডাক্ট হিসেবে বিবেচনা করেন, আপনার ডাটাবেসের প্রতিফলন হিসেবে নয়। ছোট করে শুরু করুন, বাস্তব ইউজ‑কেস দিয়ে ভ্যালিডেট করুন, এবং চাহিদা বাড়লে ধীরেই বাড়ান।
1) UI স্ক্রিন থেকে শুরু করুন (টেবিল নয়)
আপনার মূল স্ক্রিনগুলো তালিকাভুক্ত করুন (উদাহরণ: "Product list", "Product details", "Checkout")। প্রতিটি স্ক্রিনের জন্য ঠিক কোন ফিল্ড দরকার এবং কি ইন্টার্যাকশন হবে তা লিখে নিন।
এতে আপনি "গড কোয়েরি" এড়াতে পারবেন, ওভার‑ফেচিং কমবে, এবং যতখানে ফিল্টারিং, সোর্টিং ও পেজিনেশন দরকার তা স্পষ্ট হবে।
2) ডোমেইন টাইপ মডেল করুন, তারপর অপারেশন ধীরগতিতে যোগ করুন
প্রথমে আপনার কোর টাইপগুলো সংজ্ঞায়িত করুন (উদাহরণ: User, Product, Order) এবং তাদের সম্পর্ক। তারপর যোগ করুন:
- কিছু সংখ্যক কোয়েরি যা বাস্তব স্ক্রিন মেলে
- কিছু সংখ্যক মিউটেশন যা বাস্তব ব্যবহারকারীর ক্রিয়া মেলে ("addToCart", "placeOrder")
বিজনেস‑ল্যাঙ্গুয়েজ নাম ব্যবহার করুন ডাটাবেস নামের বদলে। “placeOrder” ইচ্ছা প্রকাশ করে “createOrderRecord”-এর তুলনায়।
3) নামকরণ ও পেজিনেশন বুনিয়াদি
নামকরণ একরকম রাখুন: একক আইটেমের জন্য singular (product), সংগ্রহের জন্য plural (products)। পেজিনেশনের জন্য সাধারণত একটি পছন্দ করুন:
- কার্সার‑ভিত্তিক: পরিবর্তনশীল তালিকার জন্য ও "infinite scroll"-এর ক্ষেত্রে ভালো (স্থির)
- অফসেট‑ভিত্তিক: সহজ, কিন্তু ডেটা বদলালে আইটেম স্কিপ বা ডুপ্লিকেট হতে পারে
প্রাথমিকভাবে সিদ্ধান্ত নিন কারণ তা আপনার API‑র রেসপন্স কাঠামো গঠন করে।
4) তৈরি করার সময় ডকুমেন্ট করুন
GraphQL স্কিমা সরাসরি বর্ণনা সমর্থন করে—ফিল্ড, আর্গুমেন্ট এবং এজ‑কেসগুলোর জন্য এগুলো ব্যবহার করুন। পরে ডকুমেন্টে কয়েকটি কপি‑পেস্ট করা উদাহরণ (পেজিনেশন ও সাধারণ এরর সিনারিও সহ) যোগ করুন। ভালোভাবে বর্ণিত স্কিমা ইন্ট্রোসপেকশন ও API‑এক্সপ্লোরারকে অনেক বেশি কাজে লাগায়।
শুরু করা: টুল, টেস্টিং ও পরবর্তী ধাপ
GraphQL শুরু করা মানে কয়েকটি ভালো সমর্থিত টুল পছন্দ করা এবং একটি বিশ্বস্ত ওয়ার্কফ্লো সেটআপ করা। আপনাকে সবকিছু একসাথে গ্রহণ করতে হবে না—একটি কোয়েরি পুরো পথে কাজ করলেই শুরু করুন, তারপর বাড়ান।
সার্ভার ফ্রেমওয়ার্ক বেছে নিন
স্ট্যাক ও কতটা "ব্যাটারি ইনক্লুডেড" চান তার ওপর ভিত্তি করে সার্ভার বেছে নিন:
- Apollo Server: বড় ইকোসিস্টেম ও চমৎকার ডকুমেন্টেশনের সাথে জনপ্রিয় পছন্দ।
- GraphQL Yoga: হালকা, আধুনিক ডিফল্ট এবং ভালো ডেভ এক্সপিরিয়েন্স।
- NestJS: আপনি যদি আগেই Nest ব্যবহার করে থাকেন এবং GraphQL এর সাথে DI ও মডিউল প্যাটার্ন চান তাহলে উপযুক্ত।
একটি ব্যবহারিক প্রথম ধাপ: একটি ছোট স্কিমা (কয়েকটি টাইপ + একটি কোয়েরি) সংজ্ঞায়িত করুন, রেজলভার ইমপ্লিমেন্ট করুন, এবং একটি বাস্তব ডেটা সোর্সের সাথে কানেক্ট করুন (এমনকি যদি সেটা ইন-মেমোরি স্টাবই কেন না)।
যদি আপনি আইডিয়া থেকে ওয়ার্কিং API পর্যন্ত দ্রুত যেতে চান, Koder.ai মত প্ল্যাটফর্ম দ্রুত স্ক্যাফোল্ড করে সাহায্য করতে পারে—React ফ্রন্টএন্ড, Go + PostgreSQL ব্যাকএন্ড সহ এবং চ্যাটের মাধ্যমে স্কিমা/রেজলভার ইটারেট করার সুবিধা; তারপর কোড এক্সপোর্ট করে নেওয়া যায় যখন আপনি ইমপ্লিমেন্টেশন নিজের দায়িত্ব নিতে চান।
ক্লায়েন্ট পদ্ধতি বেছে নিন
ফ্রন্টএন্ডে আপনার পছন্দ সাধারণত এই বিষয়ে নির্ভর করে যে আপনি কি ধার্মিক কনভেনশন চান কিংবা নমনীয়তা:
- Apollo Client: ব্যাপকভাবে ব্যবহৃত, শক্তিশালী ক্যাশিং ও ডেভটুলস।
- Relay: কঠোর প্যাটার্ন, বড় অ্যাপগুলোর জন্য কনসিস্টেন্সি দেয়।
- urql: ছোট, কম্পোজেবল, কন্ট্রোল পছন্দ করা দলের জন্য ভালো।
REST থেকে মাইগ্রেট করলে প্রথমে একটি স্ক্রিন বা ফিচারের জন্য GraphQL ব্যবহার করে শুরু করুন, বাকিটা REST রাখুন যতক্ষণ না নতুন পদ্ধতি প্রমাণ করে নিজের দক্ষতা।
টেস্টিং: স্কিমা + রেজলভার + ইন্টিগ্রেশন
আপনার স্কিমাকে API চুক্তি হিসেবে বিবেচনা করুন। উপকারী টেস্টিং স্তরসমূহ:
- স্কিমা ভ্যালিডেশন (CI-তে স্কিমা বিল্ড করুন; অবৈধ টাইপে ফেইল করে দিন)
- রেজলভার ইউনিট টেস্ট (ডেটা সোর্স মক করে এজ কেস ও অথরাইজেশন চেক যাচাই করুন)
- ইন্টিগ্রেশন টেস্ট (বাস্তব GraphQL অপারেশনগুলো টেস্ট সার্ভার ও টেস্ট ডাটাবেসের বিরুদ্ধে চালান)
পরবর্তী ধাপ
আপনার বোঝাপড়া বাড়াতে অব্যাহত রাখুন:
- /blog/graphql-vs-rest
- /blog/graphql-schema-design
সাধারণ প্রশ্ন
সরল ভাষায় GraphQL কি?
GraphQL হচ্ছে একটি কোয়েরি ল্যাংগুয়েজ এবং রনটাইম ফর এপিআই। ক্লায়েন্টরা একটি কোয়েরি পাঠায় যেখানে তারা ঠিক কোন ফিল্ডগুলো চায় তা বলে, আর সার্ভার এমন একটি JSON রেসপন্স দেয় যা সেই কাঠামোই অনুকরণ করে।
এটিকে সবচেয়ে সহজভাবে ভাবা যায় ক্লায়েন্ট ও এক বা একাধিক ডেটা সোর্সের (ডাটাবেস, REST সার্ভিস, থার্ড-পার্টি API, মাইক্রোসার্ভিস) মধ্যে একটি পরত হিসেবে।
নির্দিষ্ট REST এন্ডপয়েন্টগুলোর তুলনায় GraphQL কোন সমস্যা সমাধান করে?
GraphQL মূলত নিম্নোক্ত সমস্যা সমাধান করে:
- ওভার‑ফেচিং: একটি স্ক্রিনের জন্য প্রয়োজনের তুলনায় বেশি ফিল্ড ফেরৎ পাওয়া।
- আন্ডার‑ফেচিং: একটি ভিউ তৈরি করতে একাধিক রিকুয়েস্ট করতে হয়।
ক্লায়েন্ট যখন নির্দিষ্ট ফিল্ড (এবং নেস্টেড ফিল্ড) অনুরোধ করে, তখন GraphQL অপ্রয়োজনীয় ডেটা ট্রান্সফার কমাতে এবং ক্লায়েন্ট কোড সরল করতে সাহায্য করে।
GraphQL কি নয়?
GraphQL নয়:
- একটি ডাটাবেস (এটি আপনার ডেটা সংরক্ষণ করে না)।
- স্বয়ংক্রিয়ভাবে দ্রুত (এটি অপ্রয়োজনীয় ট্রান্সফার কমাতে পারে, কিন্তু সার্ভারের কাজ এখনও প্রাসঙ্গিক)।
- “REST 2.0” (এটি ভিন্ন সুবিধা ও ট্রেডঅফ সহ একটি বিকল্প API ধারা)।
এটাকে একটি স্টোরেজ বা পারফরম্যান্স ম্যাজিক না বলে, একটি API চুক্তি ও এক্সিকিউশন ইঞ্জিন হিসেবে দেখুন।
কেন GraphQL প্রায়ই একটি একক এন্ডপয়েন্ট ব্যবহার করে?
অনেক GraphQL API একটি একক এন্ডপয়েন্ট (সাধারণত /graphql) দিয়ে প্রকাশ করে। বিভিন্ন URL-এর বদলে আপনি ওই একটি এন্ডপয়েন্টে ভিন্ন অপারেশন (কোয়েরি/মিউটেশন) পাঠান।
প্রায়োগিক দিক: ক্যাশিং ও অবজারভেবিলিটি সাধারণত অপারেশন নাম + ভ্যারিয়েবল অনুসারে নির্ধারিত হয়, URL দ্বারা নয়।
GraphQL স্কিমা কি, এবং কেন তা গুরুত্বপূর্ণ?
স্কিমা হচ্ছে API কনট্রাক্ট। এটি নির্ধারণ করে:
- টাইপগুলো (যেমন
User,Post) - ঐ টাইপগুলোর ফিল্ড (যেমন
User.name) - সম্পর্ক (যেমন
User.posts)
কারণ এটি স্ট্রংলি টাইপড, সার্ভার কোয়েরি এক্সিকিউট করার আগে ভ্যালিডেশন করে এবং স্পষ্ট ত্রুটি দিতে পারে যখন কোনো ফিল্ড উপস্থিত নেই।
GraphQL কোয়েরিগুলো কীভাবে কাজ করে?
GraphQL কোয়েরিগুলো হলো রিড অপারেশন। আপনি যে ফিল্ডগুলো চান সেগুলো নির্দিষ্ট করেন, আর রেসপন্স JSON সেই কোয়েরির স্ট্রাকচারের সাথে মেলে।
টিপস:
- ডিবাগিং ও মনিটরিংয়ের জন্য অপারেশনগুলো নাম দিন (যেমন
query GetUserWithPosts)। - ফলাফল কনফিগার করতে আর্গুমেন্ট ব্যবহার করুন (যেমন
posts(limit: 2))।
GraphQL মিউটেশনগুলো কিভাবে কাজ করে, এবং কেন তারা ডেটা ফেরত দেয়?
মিউটেশন হচ্ছে লেখার (write) অপারেশন—create/update/delete। সাধারণ প্যাটার্ন:
- ক্লায়েন্ট একটি
inputঅবজেক্ট পাঠায় - সার্ভার ভ্যালিডেশন ও অথরাইজেশন করে
- ডাটাবেসে লিখে বা অন্য সার্ভিস কল করে
- একটি পেয়লোড রিটার্ন করে যাতে আপডেট হওয়া ডেটা এবং কোনো এরর থাকে
ক্লায়েন্টের দ্রুত UI আপডেট, কেশ সামঞ্জস্য ও ফাইলে ত্রুটি হ্যান্ডলিং সহজ করার জন্য মিউটেশন সাধারণত ডেটা রিটার্ন করে (শুধু success: true নয়)।
রেজলভারগুলো কী এবং অথরাইজেশন ও বিজনেস রুল সাধারণত কোথায় থাকে?
রেজলভারগুলো হলো ফিল্ড-লেভেল ফাংশন যা বলে GraphQL কীভাবে প্রতিটি ফিল্ডের মান আনবে বা কম্পিউট করবে।
প্রায়ই রেজলভারগুলো:
- ডাটাবেস কোয়েরি চালায়
- অন্য ইন্টার্নাল সার্ভিস কল করে
- থার্ড-পার্টি API থেকে ফেচ করে
- derived/ক্যালকুলেটেড ভ্যালু রিটার্ন করে
অথরাইজেশন সাধারণত রেজলভার বা শেয়ার্ড মিডলওয়্যারে কার্যকর করা হয় কারণ রেজলভাররা জানে কে কী চাচ্ছে।
N+1 কিঞ্চিৎ পারফরম্যান্স সমস্যাগুলো কীভাবে এড়ানো যায়?
সহজভাবে N+1 প্যাটার্ন তৈরি করা সহজ (উদাহরণ: 100 ইউজারের জন্য প্রতিটি ইউজারের পোস্ট আলাদা আলাদা লোড করা)।
সাধারণ সমাধানগুলো:
- বাচিং (IDগুলো একসঙ্গে নিয়ে একবারে ফেচ করা)
- ক্যাশিং (প্রতি রিকুয়েস্ট বা শেয়ার্ড ক্যাশ)
- ব্যয়বহুল নেস্টেড ফিল্ডগুলোর ব্যবহার সীমাবদ্ধ করা
রেজলভার টাইমিং মেপুন এবং একই রিকুয়েস্টে বারবার ডাউনস্ট্রীম কল হচ্ছে কিনা মনিটর করুন।
কেন একটি GraphQL রেসপন্সে একসাথে data ও errors থাকতে পারে?
GraphQL একটি রেসপন্সে পাশাপাশি data এবং errors থাকতে পারে—কারণ কিছু ফিল্ড সফলভাবে রেজলভ হয় এবং কিছুতে ত্রুটি আসে (উদাহরণ: অনুমতি নেই, টাইমআউট)।
ভাল অনুশীলন:
- ব্যবহারকারীর জন্য নিরাপদ, সংক্ষিপ্ত
messageদিন - স্থির
extensions.codeব্যবহার করুন (যেমনFORBIDDEN,BAD_USER_INPUT) - সার্ভার-সাইডে বিস্তারিত লগ/রিকোয়েস্ট আইডি রেখে তদন্ত করুন
ক্লায়েন্টরা সিদ্ধান্ত নেবে কখন আংশিক ডেটা রেন্ডার করবে এবং কখন পুরো অপারেশনকে ব্যর্থ বলে মনে করবে।