Explicación teórica de GraphQL, paso a paso..
Iniciemos:
1. ¿Qué es GraphQL y de dónde viene?
GraphQL es una lenguaje de consulta (query language) y un sistema de ejecución (runtime) para APIs, creado internamente por Facebook en 2012 y liberado como open-source en 2015. Fue diseñado para resolver los principales problemas que presentaban las APIs REST tradicionales.
2. Problemas que GraphQL intenta resolver
Antes de entender GraphQL, es importante comprender qué limitaciones tenía el enfoque REST clásico:
- Over-fetching: El cliente recibe más datos de los que necesita.
- Under-fetching: Un solo endpoint no es suficiente y el cliente tiene que hacer múltiples peticiones para completar la información.
- Múltiples rondas de ida y vuelta (round-trips) entre cliente y servidor.
- Versionado de APIs constante (v1, v2, v3…) porque cambiar la estructura rompe clientes existentes.
- Falta de flexibilidad: El servidor decide qué datos devuelve, no el cliente.
GraphQL nace con la filosofía opuesta: el cliente decide exactamente qué datos necesita, y los recibe en una sola petición.
3. Los tres pilares fundamentales de GraphQL
- Un único endpoint
- En lugar de tener decenas o cientos de URLs (/users, /users/123/posts, /posts/456/comments…), GraphQL expone un solo punto de entrada (normalmente /graphql).
- Todas las operaciones (lectura y escritura) pasan por ese mismo endpoint.
- Sistema fuertemente tipado
- Todo en GraphQL está definido mediante un esquema (schema) escrito en el lenguaje de definición de esquemas (SDL – Schema Definition Language).
- El esquema describe exactamente qué tipos de datos existen, qué campos tienen, qué relaciones hay entre ellos y qué operaciones se pueden realizar.
- Este esquema actúa como un contrato entre el cliente y el servidor.
- Tres tipos de operaciones principales
- Query: Lectura de datos (equivalente a GET en REST).
- Mutation: Escritura/modificación de datos (equivalente a POST/PUT/PATCH/DELETE).
- Subscription: Conexiones en tiempo real mediante WebSockets para recibir actualizaciones cuando los datos cambian.
4. El esquema (Schema) y los tipos
El esquema es el núcleo de cualquier API GraphQL. Define:
- Tipos de objetos (Object Types): Representan entidades con campos.
- Tipos escalares (String, Int, Float, Boolean, ID) y tipos personalizados.
- Tipos de entrada (Input Types): Usados en mutaciones para recibir datos estructurados.
- Interfaces y Unions: Para modelar relaciones polimórficas.
- Enumeraciones (Enum).
- El tipo especial Query: Punto de entrada obligatorio para operaciones de lectura.
- El tipo especial Mutation: Punto de entrada opcional para operaciones de escritura.
- El tipo especial Subscription: Para suscripciones en tiempo real.
El esquema es introspectivo: cualquier cliente puede preguntarle al servidor “¿qué estructura tienes?” y recibir la respuesta completa (esto permite herramientas como GraphiQL o Apollo Studio).
5. Cómo funciona una petición GraphQL (flujo teórico)
- El cliente envía una operación (query, mutation o subscription) escrita en el lenguaje GraphQL.
- El servidor recibe la operación y la valida contra el esquema (verifica tipos, campos obligatorios, etc.).
- Si es válida, se analiza sintácticamente (parse) y se convierte en un AST (Abstract Syntax Tree).
- Se ejecuta el resolver correspondiente a cada campo solicitado.
- Los resolvers pueden ser síncronos o asíncronos y son los responsables de obtener los datos (bases de datos, microservicios, caché, etc.).
- GraphQL recopila los resultados siguiendo exactamente la estructura solicitada por el cliente.
- Devuelve un único objeto JSON con la forma exacta que pidió el cliente (ni más, ni menos).
6. Resolvers: el corazón de la lógica
- Cada campo de cada tipo en el esquema tiene asociado una función resolver (o usa el resolver por defecto).
- Los resolvers reciben cuatro argumentos principales:
- parent (o root): el objeto padre del que cuelga este campo.
- args: los argumentos que el cliente pasó a ese campo.
- context: objeto compartido entre todos los resolvers (autenticación, loaders, etc.).
- info: información sobre la operación y el AST.
- Los resolvers son los únicos responsables de acceder a bases de datos, servicios externos, etc.
7. Características clave que diferencian GraphQL de REST
- Declarativo: El cliente declara qué quiere, no cómo obtenerlo.
- Jerárquico: La estructura de la respuesta coincide exactamente con la estructura de la consulta.
- Sin over-fetching ni under-fetching (en teoría perfecta).
- Un solo round-trip para consultas complejas.
- Introspección completa del esquema.
- Versionado casi innecesario: añadir campos nuevos no rompe clientes antiguos.
- Control de acceso y profundidad se puede limitar en el servidor (para evitar consultas muy costosas).
8. Conceptos avanzados (teoría)
- Fragments: Reutilización de selecciones de campos.
- Directivas: @include, @skip, @deprecated, y directivas personalizadas.
- DataLoader: Patrón para evitar el problema N+1 en bases de datos.
- Persisted Queries: Enviar solo un hash de la consulta para reducir tamaño y mejorar seguridad.
- Schema Stitching / Federation: Unir varios esquemas GraphQL en uno solo (usado en arquitecturas de microservicios).
9. Resumen conceptual
GraphQL cambia el paradigma de “el servidor decide qué datos devolver” a “el cliente pide exactamente lo que necesita”. Lo logra mediante:
- Un esquema fuertemente tipado que actúa como contrato.
- Un único endpoint.
- Un sistema de ejecución basado en resolvers que construye la respuesta siguiendo la forma de la consulta.
- Tres tipos de operaciones (query, mutation, subscription).
Con esta base teórica ya tienes el marco mental completo para entender cómo y por qué funciona GraphQL, antes de pasar a ejemplos prácticos.