GraphQL vs REST: Guida Completa al Confronto tra Architetture API

Intermedio
API e Servizi Web API REST e GraphQL

Scopri le differenze fondamentali tra GraphQL e REST, i vantaggi di ciascuna architettura e i criteri per scegliere la soluzione migliore per il tuo progetto web.

Pubblicato
Tag
Web Development Performance API backend nodejs GraphQL REST

Introduzione

Nel panorama moderno dello sviluppo web, la comunicazione tra client e server è il cuore pulsante di ogni applicazione. Per anni, l'architettura REST (Representational State Transfer) è stata lo standard de facto, definendo il modo in cui i dati vengono scambiati sul web. Tuttavia, con l'aumento della complessità delle interfacce utente (UI) e la necessità di ottimizzare le prestazioni su dispositivi mobili, è emerso GraphQL, un linguaggio di query e un runtime creato da Facebook.

Scegliere tra GraphQL e REST non significa decidere quale sia "migliore" in assoluto, ma capire quale paradigma si adatta meglio alle esigenze specifiche di un progetto. In questo articolo analizzeremo nel dettaglio le differenze strutturali, i pro e i contro di entrambi e fornireemo linee guida concrete per l'implementazione.

Cos'è REST: Lo Standard Basato sulle Risorse

REST non è un protocollo, ma uno stile architetturale. Si basa sul concetto di "risorsa", ogni risorsa è identificata da un URL univoco (Endpoint) e viene manipolata attraverso i metodi standard del protocollo HTTP: GET, POST, PUT, DELETE.

Il funzionamento di REST

In un'API REST, se desideri ottenere le informazioni di un utente e i suoi post correlati, dovresti tipicamente effettuare due o più chiamate separate:

  1. GET /users/1 per ottenere i dati dell'utente.
  2. GET /users/1/posts per ottenere l'elenco dei post di quell'utente.

Questo approccio è intuitivo e sfrutta appieno le funzionalità native di HTTP, come il caching dei browser e i codici di stato (200 OK, 404 Not Found, 500 Internal Server Error).

Esempio di implementazione REST (Node.js/Express)

Ecco come appare un semplice server REST che gestisce una risorsa "Libri".

const express = require('express');
const app = express();
const books = [
  { id: 1, title: 'Clean Code', author: 'Robert C. Martin' },
  { id: 2, title: 'The Pragmatic Programmer', author: 'Andrew Hunt' }
];

// Endpoint per ottenere tutti i libri
app.get('/api/books', (req, res) => {
  res.json(books);
});

// Endpoint per ottenere un singolo libro per ID
app.get('/api/books/:id', (req, res) => {
  const book = books.find(b => b.id === parseInt(req.params.id));
  if (!book) return res.status(404).send('Libro non trovato');
  res.json(book);
});

app.listen(3000, () => console.log('Server REST in ascolto sulla porta 3000'));

In questo esempio, ogni operazione è legata a un URL specifico. Se in futuro volessimo aggiungere l'autore di ogni libro in un endpoint separato, dovremmo creare un nuovo percorso /api/authors/:id.

Cos'è GraphQL: La Flessibilità della Query

GraphQL ribalta il concetto di REST. Invece di avere molteplici endpoint per diverse risorse, GraphQL espone un unico endpoint (solitamente /graphql). Il client non chiede al server "dammi questa risorsa", ma dice "dammi esattamente questi campi di queste risorse".

Il concetto di Schema e Resolver

GraphQL si basa su un sistema di tipizzazione forte. Lo sviluppatore definisce uno Schema che descrive tutti i dati disponibili e le relazioni tra loro. I Resolver sono le funzioni lato server che si occupano di recuperare i dati effettivi dal database o da altre API.

Esempio di implementazione GraphQL (Apollo Server)

Vediamo come implementare lo stesso esempio dei libri utilizzando GraphQL.

const { ApolloServer, gql } = require('apollo-server');

// Definizione dello Schema (SDL)
const typeDefs = gql`
  type Book {
    id: ID!
    title: String!
    author: String!
  }

  type Query {
    books: [Book]
    book(id: ID!): Book
  }
`;

// Dati di esempio
const books = [
  { id: 1, title: 'Clean Code', author: 'Robert C. Martin' },
  { id: 2, title: 'The Pragmatic Programmer', author: 'Andrew Hunt' }
];

// Resolver per mappare le query ai dati
const resolvers = {
  Query: {
    books: () => books,
    book: (_, { id }) => books.find(b => b.id === id),
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀 Server GraphQL pronto su ${url}`);
});

In questo caso, il client può richiedere solo il titolo del libro senza scaricare l'autore, semplicemente inviando una query come: { books { title } }.

Confronto Tecnico: Overfetching e Underfetching

Uno dei motivi principali per cui GraphQL è nato è risolvere due problemi critici di REST: l'Overfetching e l'Underfetching.

Overfetching

L'overfetching si verifica quando un endpoint REST restituisce più dati di quelli necessari al client. Se per mostrare un elenco di nomi utente chiami /api/users e il server restituisce per ogni utente indirizzo, email, data di nascita e biografia, stai sprecando banda e memoria, specialmente su connessioni mobili lente.

Underfetching

L'underfetching accade quando un singolo endpoint non fornisce abbastanza dati per completare una vista, costringendo il client a effettuare chiamate multiple (il cosiddetto problema delle N+1 query lato client). Per visualizzare un post e i commenti di quell'utente, devi fare: /posts/1 $
ightarrow$ /users/1 $
ightarrow$ /posts/1/comments.

GraphQL risolve entrambi i problemi permettendo al client di specificare esattamente ciò che serve in un'unica richiesta HTTP.

Vantaggi e Svantaggi a Confronto

Vantaggi di REST

  • Caching Nativo: HTTP ha un sistema di caching integrato potentissimo. Le risposte di un endpoint GET possono essere memorizzate da proxy, CDN e browser senza configurazioni complesse.
  • Semplicità di Apprendimento: Quasi ogni sviluppatore conosce REST; non richiede l'apprendimento di un nuovo linguaggio di query.
  • Gestione degli Errori Standard: L'uso dei codici di stato HTTP (401, 403, 404) rende la gestione degli errori univoca e standardizzata.

Svantaggi di REST

  • Rigidità: Ogni modifica ai dati restituiti spesso richiede una nuova versione dell'API (es. /v1/ a /v2/) per non rompere le app client esistenti.
  • Molteplici Round-trip: Maggiore latenza a causa delle chiamate multiple necessarie per assemblare i dati di una pagina complessa.

Vantaggi di GraphQL

  • Efficienza dei Dati: Riduzione drastica del payload scambiato tra client e server.
  • Sviluppo Front-end Rapido: I team front-end possono modificare l'interfaccia e richiedere nuovi campi senza dover chiedere al team back-end di creare nuovi endpoint.
  • Auto-documentazione: Grazie all'Introspezione, strumenti come GraphiQL o Apollo Studio permettono di esplorare l'API in tempo reale senza documentazione manuale (come Swagger).

Svantaggi di GraphQL

  • Caching Complesso: Poiché tutte le richieste vanno a un unico endpoint tramite POST, il caching HTTP standard non funziona. È necessario implementare il caching a livello di client (es. Apollo Cache) o usare soluzioni come Persisted Queries.
  • Rischio di Query Complesse: Un client malintenzionato potrebbe inviare una query profondamente annidata (es. utente $
    ightarrow$ post $
    ightarrow$ commenti $
    ightarrow$ autore $
    ightarrow$ post...) che potrebbe mandare in crash il database (DoS).
  • Learning Curve: Richiede l'installazione di librerie specifiche e la definizione di uno schema rigoroso.

Esempi Pratici: Quando usare cosa?

Scenario A: Blog Semplice o Sito di News

Se stai costruendo un sito dove i contenuti sono statici o cambiano raramente e la struttura è semplice, REST è la scelta ideale. La capacità di cache delle CDN renderà il sito estremamente veloce e l'implementazione sarà rapida.

Scenario B: Dashboard Aziendale Complessa

Immagina un'app di gestione progetti con utenti, task, commenti, file allegati e cronologia. Una singola pagina potrebbe dover mostrare dati da 5 tabelle diverse. In questo caso, GraphQL brilla. Invece di orchestrare 5 chiamate API diverse, il front-end invia una singola query strutturata che recupera tutto il necessario in un unico viaggio di rete.

Scenario C: API Pubblica per Terze Parti

Se stai creando un'API che sarà utilizzata da migliaia di sviluppatori esterni, REST è spesso preferibile per la sua universalità e facilità di integrazione senza l'uso di client specifici. Tuttavia, aziende come GitHub offrono ora entrambe le opzioni per dare massima flessibilità.

Errori Comuni e FAQ

"Posso usare GraphQL per tutto?"

No. Per operazioni molto semplici o per il download di file binari (immagini, PDF), REST (o semplici URL statici) rimane superiore. GraphQL è progettato per i dati, non per lo streaming di file.

"GraphQL sostituisce il database?"

Assolutamente no. GraphQL è uno strato di astrazione. Dietro un resolver GraphQL può esserci un database SQL, un database MongoDB, un'altra API REST o persino un file di testo.

Come prevenire l'abuso delle query in GraphQL?

Per evitare che query troppo profonde saturino il server, è fondamentale implementare il Query Depth Limiting (limitare la profondità dell'annidamento) o il Query Cost Analysis (assegnare un punteggio a ogni campo e rifiutare query che superano un certo costo).

Prossimi Passi

Ora che comprendi le differenze tra REST e GraphQL, il passo successivo è l'experimentazione pratica. Ecco un percorso consigliato:

  1. Per REST: Approfondisci l'uso di HATEOAS (Hypermedia as the Engine of Application State) per rendere le tue API REST veramente mature.
  2. Per GraphQL: Installa apollo-server e prova a creare un piccolo progetto che colleghi due entità diverse (es. Autori e Libri).
  3. Ibridazione: Considera l'uso di un "BFF" (Backend For Frontend), dove un server GraphQL funge da gateway che aggrega dati provenienti da diversi microservizi REST.

Studiare queste due tecnologie ti permetterà di progettare sistemi scalabili, efficienti e manutenibili, indipendentemente dallo stack tecnologico scelto.