GraphQL: alternativa k RESTu a její výhody

GraphQL: Alternativa RESTu a její výhody

Co je GraphQL a proč vznikl

GraphQL je dotazovací jazyk pro API a runtime pro zpracování těchto dotazů pomocí dat z vašich zdrojů. Vznikl jako odpověď na limity tradičního přístupu REST, zejména na problémy over-fetchingu (přenášíme více dat, než klient potřebuje) a under-fetchingu (musíme volat více endpointů, abychom sestavili požadovaný tvar dat). GraphQL dává klientovi možnost deklarativně specifikovat přesný tvar výsledku, a tím zjednodušuje vývoj front-endu, optimalizuje přenosy a urychluje iterace.

Jádro GraphQL: schéma, typy a resolvery

  • Schéma definuje kontrakt mezi klientem a serverem. Popisuje typy, pole, vztahy a operace Query, Mutation a Subscription.
  • Typy: skalární (Int, Float, String, Boolean, ID), Object, Interface, Union, Enum, Input a List. Vše je striktně typované a introspektivní.
  • Resolver je funkce, která naplní dané pole daty. Resolver může číst z DB, volat služby REST/GRPC, cache či jiné zdroje. Skládáním resolverů vzniká datový graf.

Operace: Query, Mutation, Subscription

  • Query: čisté čtecí operace bez vedlejších efektů. Klient přesně určí strukturu, včetně vnořených vazeb a argumentů.
  • Mutation: operace měnící data (vytvoření, aktualizace, smazání). Vrací stav po změně (např. nově vytvořený objekt), což usnadňuje synchronizaci UI.
  • Subscription: stream událostí v reálném čase (typicky přes WebSocket). Užitečné pro notifikace, dashboardy a kolaborativní scénáře.

Transport a protokol

GraphQL není vázán na konkrétní transport, nejběžnější je však HTTP s metodou POST (lze použít i GET pro dotazy, které lze ukládat do cache). Subscription obvykle používají WebSocket. V praxi se uplatňují konvence jako GraphQL-over-HTTP (hlavičky, stavové kódy) a operationName pro více operací v jednom dokumentu.

Výhody oproti REST

  • Přesné dotazy: klient dostane jen to, co chce (méně dat, méně požadavků).
  • Jedno API endpointu: místo mnoha REST endpointů se obvykle používá /graphql. Snižuje to režii spojenou se správou verzí a dokumentací.
  • Silné typování + introspekce: nástroje mohou generovat typy a klientská SDK, což zlepšuje DX (developer experience).
  • Evoluce bez verzí: rozšiřováním schématu o nová pole se vyhneme verzování URL; odstraňování polí se řeší jejich označením jako zastaralých.
  • Kompozice dat: agregace dat z více zdrojů v jednom dotazu bez orchestrací na klientovi.

Kdy REST stále dává smysl

  • Jednoduché CRUD služby s jasně vymezenými zdroji a silnou závislostí na HTTP cache a stavových kódech.
  • Vysoká míra ukládání do cache CDN (GET na konkrétní URL s ETag/Last-Modified), statické API.
  • Integrace se zastaralými systémy, auditem a bezpečnostními kontrolami vázanými na rozhraní REST.

Modelování schématu a doménový návrh

Dobré schéma je zrcadlem domény, nikoli databázového modelu. Doporučení:

  • Doménové typy namísto generických objektů „DTO“.
  • Typy Input pro mutace (jasně určují, co lze měnit).
  • Rozhraní (Interface) a unie (Union) pro polymorfismus a variantní struktury.
  • Označení jako zastaralé pro řízené odstraňování starých polí a operací.

Stránkování, filtrování a řazení

Dvě hlavní strategie:

  • Offset/limit: snadné, ale náchylné na změny v datech a pomalé při použití vysokých hodnot offsetu.
  • Cursor-based (Relay): stabilnější a výkonnější. Využívá edges, node, cursor, pageInfo.

Filtrování a řazení se modelují jako argumenty polí; složitější dotazy mohou využívat objekty input.

Problém N+1 a DataLoader

Protože resolvery běží pro jednotlivá pole, hrozí velké množství malých dotazů do DB (N+1). Řešení:

  • Dávkování a ukládání do cache na úrovni požadavku (např. DataLoader) pro sloučení několika volání findById do jednoho findByIds.
  • Projekce a spojení na DB vrstvě, případně materializované pohledy.

Cache a výkon v GraphQL

  • HTTP cache je obtížnější
  • Dotazy nejsou vázány na URL – proto se používají Persisted Queries a Automatic Persisted Queries (APQ): klient posílá hash dotazu, který může CDN/API Gateway ukládat do cache.
  • Ukládání odpovědí do cache na úrovni pole či resolveru (krátká TTL, stale-while-revalidate), případně ukládání fragmentů do cache na klientovi.
  • CDN na okraji sítě s pravidly podle operationName a proměnných.

Bezpečnost: limity, autorizace, ochrana schématu

  • Omezování počtu požadavků a throttling na vrstvě gateway; omezování hloubky a složitosti (maximální hloubka dotazu, bodové hodnocení polí).
  • Autorizace: kontrola na úrovni polí (field-level, direktivy, middleware), pravidla na úrovni záznamů (record-level) a attribute-based access.
  • Zakázání či omezení introspekce v produkčním prostředí (nebo pouze pro privilegované klienty), ochrana před úniky z introspekce.
  • Ověřování vstupů a seznam povolených dotazů (persisted queries) pro veřejná API.

Chyby a návratové kódy

GraphQL vždy vrací HTTP 200 pro syntakticky platnou odpověď GraphQL; chyby jsou uvedeny v poli errors s položkami path a extensions. Doporučuje se standardizovat error codes v extensions.code a mapovat doménové chyby (např. FORBIDDEN, NOT_FOUND, CONFLICT).

Verzování vs. evoluce schématu

  • „Bez verzování“: přidáváme nová pole, stará označíme @deprecated a po období podpory odstraníme.
  • Zpětně nekompatibilní změny plánujeme s dostatečným předstihem a komunikujeme je; automatické kontroly kompatibility (rozdíly ve schématu v CI).

Federace a modulární monorepo schémat

Ve větších organizacích je praktické rozdělit schéma mezi doménové týmy. Federace umožňuje publikovat dílčí subgraphy a skládat na gateway supergraph (klíče entit, řešení požadavků napříč hranicemi). Alternativou je schema stitching nebo BFF (Backend for Frontend) pro každou aplikaci.

Nástroje a ekosystém

  • Server: Apollo Server, GraphQL Yoga, Mercurius (Fastify), Helix; pro jiné jazyky graphql-java, Sangria (Scala), graphql-go, Strawberry/Graphene (Python).
  • Klient: Apollo Client, Relay, urql; generování typů (GraphQL Code Generator), fragmenty, normalizace cache.
  • Vývoj: GraphiQL/GraphQL Playground, Explorer, lintování a validace schématu, mockování resolverů.

Testování a kvalita

  • Jednotkové testy resolverů a přístupu k datům.
  • Integrační testy s lokálním serverem a předem naplněnými daty.
  • Testování kontraktu proti schématu (registr operací, kontrola změn narušujících kompatibilitu v CI/CD).

Observabilita a monitoring

  • Trasování jednotlivých resolverů (OpenTelemetry) – latence polí, detekce N+1, tepelné mapy nejnákladnějších dotazů.
  • Analytika využití: kdo volá které operace a fragmenty (pomůže s označováním za zastaralé a úklidem).
  • Registr operací a seznam povolených dotazů pro bezpečnost i výkon na CDN.

Integrace s REST a existujícími systémy

GraphQL často funguje jako orchestrace nad REST/GRPC – nenahrazuje všechny systémy, ale sjednocuje přístup k datům. Výhodou je postupná migrace: nejprve obalíme existující endpointy resolverem, později refaktorujeme zdroje.

Osvědčené postupy pro produkční prostředí

  • Správa schématu: vlastnictví domén, proces revizí, automatické kontroly kompatibility.
  • Bezpečnost a limity: omezení hloubky a složitosti, model nákladů dotazů, omezování počtu požadavků, RLS na úrovni DB.
  • Výkon: DataLoader, cache, APQ, jemně odstupňovaná autorizace (nikoli ve smyčkách DB), vhodné indexy.
  • Dokumentace: descriptions ve schématu, generované reference, živá prostředí Playground s ukázkami.

Příklady typických případů použití

  • Komplexní front-endy (mobilní aplikace/SPA), kde jeden dotaz sestaví dashboard z více domén.
  • Produktové katalogy s bohatými vazbami (produkty, varianty, recenze, skladové zásoby, cena).
  • Multi-tenant SaaS se silnou personalizací a řízením přístupů na úrovni polí.

Antivzory a časté chyby

  • „Jedna mega-mutace“: obtížná autorizace a audit; používejte menší, konzistentní mutace.
  • Vystavení databázového modelu: schéma ≠ tabulky; skrývejte technické detaily.
  • Ignorování problému N+1: vždy plánujte použití DataLoaderu a dávkování.
  • Žádné limity dotazů: otevřená brána k DoS – zaveďte kontroly složitosti a hloubky.

GraphQL vs. REST: shrnutí

GraphQL skvěle řeší flexibilitu klienta, agregaci dat a rychlý vývoj kontraktu. REST vyniká v jednoduchosti, HTTP cache a jasném mapování zdrojů. V praxi se přístupy často kombinují: veřejné API s převahou čtení zůstává kompatibilní s REST/HTTP cache, interní BFF/federované API využívá GraphQL.

Závěr

GraphQL není jen „rychlejší REST“, ale jiný model interakce – klient si vyžádá přesná data a server se postará o jejich složení. Díky silnému typování, introspekci, federaci a bohatému ekosystému výrazně zlepšuje produktivitu týmů a uživatelskou zkušenost. Úspěch však závisí na promyšleném schématu, sledování výkonu, bezpečnostních limitech a disciplinované správě změn.