GraphQL: основы и отличия от REST

GraphQL — язык запросов для API и среда выполнения, позволяющая клиенту запрашивать ровно те данные, которые ему нужны, за один запрос.

Зачем нужно

REST-API часто страдает over-fetching (лишние поля) или under-fetching (нужно несколько запросов). GraphQL решает обе проблемы: клиент описывает нужную форму данных в запросе и получает только её. Это особенно важно для мобильных приложений с ограниченным трафиком и сложными иерархическими данными.

Где используется

  • SPA и мобильные приложения с разными потребностями в данных
  • Публичные API (GitHub GraphQL API, Shopify API)
  • BFF (Backend For Frontend) — один endpoint для множества клиентов
  • Системы с взаимосвязанными сущностями (социальные сети, e-commerce)

REST vs GraphQL

Критерий REST GraphQL
Endpoint Один URL — один ресурс Один endpoint для всего
Количество запросов N+1 для связанных данных Один запрос
Данные ответа Фиксированная структура Только запрошенные поля
Версионирование /api/v2/... Deprecation полей в схеме
Документация OpenAPI/Swagger Introspection (встроено)
Кэширование HTTP-кэш (GET) Требует дополнительной настройки

Базовый запрос GraphQL

# REST: три запроса для получения пользователя + посты + комментарии
# GraphQL: один запрос

query GetUserWithPosts {
  user(id: 42) {
    id
    name
    email
    posts(first: 5) {
      title
      publishedAt
      comments {
        text
        author {
          name
        }
      }
    }
  }
}

HTTP-запрос к GraphQL endpoint

// Все GraphQL запросы идут на один endpoint — POST /graphql
const query = `
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

const res = await fetch('/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query,
    variables: { id: '42' },
  }),
});

const { data, errors } = await res.json();
// HTTP статус всегда 200 — даже при ошибках!
if (errors) console.error(errors);
console.log(data.user);

Частые ошибки

  • Ожидают HTTP 4xx/5xx при GraphQL-ошибках — ответ всегда 200, ошибки в поле errors
  • Запрашивают все поля вместо нужных — теряют преимущество точных запросов
  • Не используют переменные, передают значения прямо в строку — уязвимость инъекций
  • Путают Query (чтение) и Mutation (изменение) — GET vs POST аналогия

Связанные темы

Ресурсы