GraphQL

GraphQL

Co je GraphQL a proč vznikl

GraphQL je dotazovací a manipulační jazyk pro API a zároveň runtime pro provádění dotazů nad datovým grafem. Vznikl ve Facebooku (2012, otevřen v roce 2015) jako reakce na limity RESTu u složitých klientských aplikací: příliš mnoho „koleček“ mezi klientem a serverem, overfetching (stahujeme více dat než potřebujeme) a underfetching (nutnost vícero volání pro sestavení jedné obrazovky). GraphQL umožňuje klientovi přesně deklarovat, která pole potřebuje, v jednom požadavku napříč více zdroji, nad jednotným schématem typů.

Základní stavební prvky: schéma, typy a resolver

  • Schéma (SDL – Schema Definition Language) definuje typy, pole a jejich vztahy. Je to kontrakt mezi klientem a serverem.
  • Kořenové typy: Query (čtení), Mutation (změny) a Subscription (stream událostí).
  • Resolver je funkce, která pro dané pole vrací data. Řeší napojení na DB, služby, cache apod.

Ukázka schématu (SDL) a základních dotazů

type User { id: ID! name: String! email: String! posts(first: Int, after: String): PostConnection! } type Post { id: ID! title: String! body: String! author: User! createdAt: String! } type PostEdge { node: Post! cursor: String! } type PageInfo { endCursor: String, hasNextPage: Boolean! } type PostConnection { edges: [PostEdge!]! pageInfo: PageInfo! } type Query { me: User post(id: ID!): Post users(limit: Int = 10): [User!]! } type Mutation { createPost(title: String!, body: String!): Post! } type Subscription { postCreated: Post! }

# Dotaz s přesnými poli query { me { id name posts(first: 10) { edges { node { id title } } pageInfo { hasNextPage } } } }

# Mutace s návratovou strukturou mutation { createPost(title: "GraphQL", body: "Hello") { id title author { name } } }

GraphQL vs. REST: srovnání paradigmat

  • Granularita: REST vrací pevně dané reprezentace; GraphQL vrací přesně to, co si klient nadefinuje.
  • Navigace: REST používá URL a zdroje; GraphQL naviguje grafem přes pole a vztahy.
  • Verzování: REST často verzování v URL (/v1, /v2), GraphQL preferuje evoluci schématu (deprecations, non-breaking changes).
  • Chyby: REST = stavové kódy HTTP; GraphQL = pole errors v JSON odpovědi + (typicky) 200 OK na transportní vrstvě.

Silná typová kontrola a introspekce

Schéma je silně typované. Klienti využijí introspekci ke zjištění dostupných typů, polí a argumentů; díky tomu vznikají nástroje jako GraphiQL, GraphQL Playground, generátory SDK (TypeScript/Kotlin/Swift) a validace dotazů v CI.

Architektura serveru: resolvery, kontext, datové zdroje

  • Resolvery: mapují pole na implementaci (DB dotaz, volání REST/gRPC, cache). Každé pole může mít svůj resolver.
  • Kontext: požadavkový kontejner (uživatel, tokeny, loaders, trace ID).
  • DataSources: opakovaně použitelné konektory s vestavěným cachováním a retry (např. Apollo DataSource).

Výkonnost: N+1 problém a jeho mitigace

Vnořené resolvery mohou vést k N+1 dotazům (např. pro 100 příspěvků 100 dotazů na autora). Zmírnění:

  • Batching a caching přes DataLoader (seskupí dotazy by ID do jedné DB operace).
  • Projection/select optimalizace: načítat pouze požadovaná pole.
  • Joins/CTE na DB vrstvě nebo předpočítané pohledy.

Stránkování a filtrování: offset vs. cursory

GraphQL nenařizuje konkrétní paging, ale v praxi se prosadil cursor-based model (Relay specifikace: edges, node, pageInfo). Je stabilnější vůči vkládání/mazání řádků než offset/limit a snižuje riziko ztráty/duplicit.

Subscriptions a realtime

Subscription umožňuje streamovat události klientovi (WebSocket, SSE, MQTT). Typické scénáře: chat, notifikace, live metriky. Server drží kanál a publikuje payload dle schématu; škálování vyžaduje broker (Redis, Kafka) a sticky sessions či pub/sub vrstvu.

Směrování a federace schémat

  • Schema Stitching: spojování více schémat na gateway.
  • Apollo Federation: deklarativní federace s @key, @provides, @requires a subgraph službami; gateway resolvuje referenční entity napříč doménami.
  • Remote joins a grafové routery: směrují části dotazu do mikroservis, agregují odpovědi.

Bezpečnost: autorizace, limity a ochrana proti zneužití

  • Autentizace v kontextu (JWT, mTLS, OAuth 2.0).
  • Autorizace na úrovni polí (directive @auth), policy enforcement ve resolveru nebo gateway.
  • Depth/complexity limit: omezení hloubky, počtu uzlů a šířky dotazu, aby se zabránilo drahým dotazům.
  • Persisted queries: klient posílá hash předem zaregistrovaného dotazu ⇒ kratší payload, nižší riziko injekce.
  • Rate limiting, throttling, cost analysis per pole (váhy dle nákladnosti).

Cache a výkon: vrstvy a strategie

  • Client cache: normalizace entit (Apollo Client, Relay); write policies, cache redirects, optimistic UI.
  • Server cache: per-field/per-resolver cache, response caching (u persisted queries), mikrocache (ms–s) na gateway.
  • CDN: těžší kvůli POST a variabilitě dotazů; pomáhá persisted GET + cache key podle hash dotazu a proměnných.

Vývojové workflow: kontrakty, typová generace a CI

  • SDL-first vs. code-first (Nexus, TypeGraphQL). Důležité je, aby byl schématový kontrakt zdrojem pravdy.
  • Generování typů (TypeScript/Swift/Kotlin) z introspection a z dotazů – snižuje runtime chyby.
  • Linting a schema validation v CI (breaking changes detekce, deprecation audit).

Evoluce a správa schématu (schema governance)

  • Non-breaking změny: přidávat pole s defaulty, označovat staré @deprecated.
  • Breaking změny plánovat s migračním oknem a telemetrií (kdo ještě čte stará pole?).
  • Changelog, contract tests pro klíčové klienty, schema registry (Apollo Studio, GraphQL Hive).

Defer/Stream, živé dotazy a file upload

  • @defer a @stream: postupné doručování částí odpovědi (lepší time-to-first-byte u velkých grafů).
  • Live queries: klient udržuje dotaz „živý“ a server posílá změny (alternativa k subscriptions u některých gateway).
  • Nahrávání souborů: multipart request (specifikace graphql-multipart-request-spec), pole Upload a perzistence v objektovém úložišti.

Chyby a jejich modelování

  • GraphQL odpověď má data a errors; částečný úspěch je možný (část polí selže).
  • Pro doménové chyby modelujte výsledkové typy (union Success | Error) nebo polymorfní payload s chybovým polem.
  • Přidávejte extensions pro kódy, trace ID, tipy pro klienta.

Monitorování, tracing a observabilita

  • Tracing per field (Apollo, OpenTelemetry): které resolvery jsou nejdražší? latence, počet volání, cache hit ratio.
  • Field-level metrics, error rates, p95/p99 latence; korelace s backend službami.
  • Query safelisting a audit: které dotazy běží, kdo je volá, s jakými proměnnými.

Integrace s existujícím ekosystémem

  • Backend: Node.js (Apollo Server, Helix), JVM (GraphQL Java), .NET (Hot Chocolate), Go (gqlgen), Python (Strawberry, Graphene).
  • Frontend: Apollo Client, Relay, URQL; generátory SDK (graphql-code-generator).
  • Hybridní přístup: GraphQL gateway před REST/gRPC mikroslužbami, postupná adopce bez přepisování backendu.

Bezpečné a škálovatelné nasazení: osvědčené postupy

  • Zapněte depth/complexity limit, persisted queries a timeouty resolverů.
  • Udržujte idempotentní a deterministické resolvery; používejte retry s jitterem.
  • Pro vertikální škálování navyšte CPU/RAM; pro horizontální použijte gateway + read-through cache a pub/sub pro subscriptions.

Typické antipatterny

  • Jeden mega-dotaz vracející „všechno“ – ztrácí granularitu a kontrolu nad náklady; omezte šířku a hloubku.
  • Resolver per řádek DB bez batchingu – vede k N+1; použijte DataLoader.
  • Absence autorizace na poli – únik citlivých polí i když je UI nezobrazuje.
  • Skryté breaking changes – mazání/renaming bez deprecations a telemetrie.

Praktický mini–design: feed příspěvků

# Schéma type FeedItem { id: ID! title: String! snippet: String! author: User! createdAt: String! } type Query { feed(first: Int, after: String): FeedConnection! }

# Dotaz (klient si volí pole) query Feed($first: Int = 20) { feed(first: $first) { edges { node { id title author { id name } createdAt } cursor } pageInfo { hasNextPage endCursor } } }

# Poznámky k implementaci: 1) resolver feed načítá minimum sloupců; 2) author je batchován dle author_id; 3) přidejte complexity weight pro pole feed.

Check-list pro adopci GraphQL v organizaci

  • Use-case fit: více klientů (web, mobil), složité obrazovky, agregace z více zdrojů, potřeba rychlé iterace.
  • Governance: vlastník schématu, review a deprecations proces, telemetrie dotazů.
  • Bezpečnost: autentizace v kontextu, autorizace na poli, rate/complexity limity, persisted queries.
  • Výkon: DataLoader, caching, federace pro rozdělení domén, CDN pro persisted GET odpovědi.
  • DX: schema registry, automatická generace typů, GraphiQL/Playground, kontraktní testy v CI.

Závěr

GraphQL poskytuje jednotný, silně typovaný kontrakt mezi klienty a backendem a umožňuje přesné, efektivní a evolvující API. Při správném nasazení – s důrazem na governance, bezpečnost, observabilitu a výkon – zjednodušuje vývoj komplexních aplikací, snižuje síťovou režii a urychluje iteraci produktů napříč platformami.

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *