GraphQL vs REST: um duelo que deveria ter começado ontem
\n\nSituação familiar: você está escrevendo um novo projeto em JavaScript (ou Node.js), e de repente surge a pergunta: o que usar para a comunicação entre frontend e backend? O clássico REST ou o moderno GraphQL? Os debates sobre esse assunto não param, e cada desenvolvedor tem sua opinião "de ferro".
\n\nVamos ser honestos: REST é aquele velho amigo de confiança que nunca decepciona. GraphQL é o novato ousado que promete resolver todos os seus problemas. Mas como escolher? Vou mostrar não apenas tabelas de comparação secas, mas exemplos reais de combate em JavaScript. Você verá como o código se parece, onde surgem as armadilhas e, o mais importante, quando usar cada um.
\n\nA propósito, se você desenvolve em Python (e este site é sobre Python, não se esqueça), os princípios de escolha entre essas tecnologias são muito semelhantes. Mas hoje estamos falando de JavaScript — a linguagem que domina tanto no cliente quanto no servidor.
\n\nGuia rápido: REST e GraphQL em 60 segundos
\n\nREST (Representational State Transfer)
\nÉ um estilo arquitetural onde cada recurso (usuário, postagem, comentário) tem sua própria URL. Você faz uma requisição GET para /api/users/1 — obtém o usuário. Quer as postagens dele? Vá para /api/users/1/posts. Tudo simples, previsível, mas... às vezes muito verboso.
GraphQL
\nÉ uma linguagem de consulta e ambiente de execução. Você tem um único endpoint (geralmente /graphql) e decide quais dados deseja obter. Sem over-fetching (quando chegam 50 campos, mas você precisa de 3) e sem under-fetching (quando precisa fazer 5 requisições para montar uma página).
Comparação prática: escrevendo código em JavaScript
\n\nVamos imaginar uma tarefa típica: exibir na página o perfil de um usuário com suas três últimas postagens. Vamos comparar ambas as abordagens.
\n\nExemplo de API REST com Express (Node.js)
\n\n// Servidor REST com Express\nconst express = require('express');\nconst app = express();\n\napp.get('/api/users/:id', (req, res) => {\n // Retorna TODOS os dados do usuário\n const user = users.find(u => u.id === req.params.id);\n res.json(user); // { id, name, email, phone, address, ... }\n});\n\napp.get('/api/users/:id/posts', (req, res) => {\n // Retorna TODAS as postagens do usuário\n const posts = posts.filter(p => p.userId === req.params.id);\n res.json(posts); // [{ id, title, body, createdAt, ... }]\n});\n\n// Código do cliente (frontend com fetch)\nasync function loadProfile(userId) {\n // Primeira requisição — obtém o usuário (vem muita coisa desnecessária)\n const userResponse = await fetch(`/api/users/${userId}`);\n const user = await userResponse.json();\n \n // Segunda requisição — obtém as postagens (novamente dados extras)\n const postsResponse = await fetch(`/api/users/${userId}/posts`);\n const allPosts = await postsResponse.json();\n \n // Pega apenas as 3 últimas postagens\n const latestPosts = allPosts.slice(0, 3);\n \n return { user, posts: latestPosts };\n}\n\nO problema é óbvio: recebemos muitos dados desnecessários (over-fetching). Para que precisamos de email, phone, address, se estamos mostrando apenas o nome e o avatar? E podem haver 100 postagens, mas precisamos de apenas 3.
\n\nExemplo de GraphQL com Apollo Server (Node.js)
\n\n// Esquema GraphQL\nconst typeDefs = `\n type User {\n id: ID!\n name: String\n avatar: String\n posts(limit: Int): [Post]\n }\n\n type Post {\n id: ID!\n title: String\n body: String\n }\n\n type Query {\n user(id: ID!): User\n }\n`;\n\n// Resolvers (lógica de obtenção de dados)\nconst resolvers = {\n Query: {\n user: (parent, { id }) => users.find(u => u.id === id),\n },\n User: {\n posts: (parent, { limit }) => {\n let result = posts.filter(p => p.userId === parent.id);\n if (limit) result = result.slice(0, limit);\n