PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    GraphQL vs REST: что выбрать для API в 2026 году

    GraphQL vs REST: что выбрать для API в 2026 году

    Аватар автора GraphQL vs REST: что выбрать для API в 2026 году

    Антон Ларичев

    Иконка календаря11 июля 2026
    graphqlrestapibackendnodejsjavascriptmiddleИконка уровня middle
    Картинка поста GraphQL vs REST: что выбрать для API в 2026 году

    Введение

    Выбор между GraphQL и REST — один из первых архитектурных вопросов при проектировании нового API. В 2026 году оба подхода живы, активно используются и имеют свои ниши. Проблема в том, что многие команды выбирают «модный» вариант вместо подходящего, и потом расплачиваются за это техдолгом.

    В этой статье мы разберём реальные отличия, покажем код на Node.js и поможем принять осознанное решение.

    Как работает REST

    REST (Representational State Transfer) строится вокруг ресурсов и стандартных HTTP-методов. Каждый ресурс имеет свой URL, а действия над ним выражаются через GET, POST, PUT, PATCH, DELETE.

    // Получить пользователя и его посты — два отдельных запроса
    GET /users/42
    GET /users/42/posts
    
    // Ответ от /users/42
    {
      "id": 42,
      "name": "Иван Петров",
      "email": "ivan@example.com",
      "role": "admin",
      "createdAt": "2024-01-15"
    }
    

    Это просто, предсказуемо и отлично кешируется на уровне HTTP. Большинство CDN и прокси понимают REST из коробки.

    Как работает GraphQL

    GraphQL — это язык запросов, где клиент сам описывает форму нужных данных. Все запросы идут на один эндпоинт, обычно POST /graphql.

    // Один запрос — точно нужные поля
    query GetUserWithPosts {
      user(id: 42) {
        name
        email
        posts(limit: 5) {
          title
          publishedAt
        }
      }
    }
    
    // Ответ содержит только то, что запросили
    {
      "data": {
        "user": {
          "name": "Иван Петров",
          "email": "ivan@example.com",
          "posts": [
            { "title": "Мой первый пост", "publishedAt": "2025-03-01" }
          ]
        }
      }
    }
    

    Схема как контракт

    Главная сила GraphQL — типизированная схема. Она служит живой документацией и позволяет генерировать типы для фронтенда.

    type User {
      id: ID!
      name: String!
      email: String!
      posts(limit: Int): [Post!]!
    }
    
    type Post {
      id: ID!
      title: String!
      publishedAt: String
      author: User!
    }
    
    type Query {
      user(id: ID!): User
      posts: [Post!]!
    }
    

    Серверная реализация

    Сравним минимальную реализацию на Node.js. REST через Express:

    const express = require('express');
    const app = express();
    
    // Каждый ресурс — отдельный маршрут
    app.get('/users/:id', async (req, res) => {
      const user = await db.users.findById(req.params.id);
      if (!user) return res.status(404).json({ error: 'Не найден' });
      res.json(user);
    });
    
    app.get('/users/:id/posts', async (req, res) => {
      const posts = await db.posts.findByUserId(req.params.id);
      res.json(posts);
    });
    

    Тот же функционал через Apollo Server (GraphQL):

    const { ApolloServer, gql } = require('@apollo/server');
    
    const typeDefs = gql`
      type User {
        id: ID!
        name: String!
        posts: [Post!]!
      }
      type Post {
        id: ID!
        title: String!
      }
      type Query {
        user(id: ID!): User
      }
    `;
    
    const resolvers = {
      Query: {
        // Резолвер вызывается только если поле запрошено
        user: (_, { id }) => db.users.findById(id),
      },
      User: {
        posts: (user) => db.posts.findByUserId(user.id),
      },
    };
    
    const server = new ApolloServer({ typeDefs, resolvers });
    

    Проблема N+1 в GraphQL

    Классическая ловушка — когда запрос списка пользователей с постами порождает N дополнительных запросов к БД. Решается через DataLoader:

    const DataLoader = require('dataloader');
    
    // Группируем запросы в один батч
    const postsLoader = new DataLoader(async (userIds) => {
      const posts = await db.posts.findByUserIds(userIds);
      // Возвращаем посты в том же порядке, что userIds
      return userIds.map(id => posts.filter(p => p.userId === id));
    });
    
    const resolvers = {
      User: {
        // Теперь 100 пользователей = 1 запрос к БД, а не 100
        posts: (user) => postsLoader.load(user.id),
      },
    };
    

    Когда выбирать REST

    REST — правильный выбор в следующих случаях:

    • Публичное API — REST легче документировать через OpenAPI/Swagger, клиентам не нужно учить GraphQL
    • Файлы и бинарные данные — загрузка файлов через multipart в REST прямолинейна
    • Агрессивное кеширование — HTTP-кеш, CDN и браузерное кеширование работают из коробки
    • Простые CRUD-операции — если у вас интернет-магазин с типовыми операциями, GraphQL добавит сложности без выгоды
    • Команда без опыта с GraphQL — кривая обучения GraphQL реальна

    Когда выбирать GraphQL

    GraphQL побеждает в таких сценариях:

    • Несколько клиентов с разными нуждами — мобильное приложение, веб и SmartTV хотят разный набор полей
    • Быстро меняющийся фронтенд — бэкенд не нужно трогать при изменении UI
    • Сложные связанные данные — социальные сети, графы знаний, CMS
    • Developer Experience в приоритете — GraphQL Playground и типогенерация ускоряют разработку

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

    1. GraphQL поверх REST вместо прямого доступа к данным

    Оборачивать REST-эндпоинты в GraphQL-резолверы — антипаттерн. Теряются все преимущества обоих подходов, зато добавляется latency и сложность.

    2. Игнорирование кеширования в GraphQL

    POST-запросы не кешируются браузером. Для GraphQL нужно настраивать кеш на уровне клиента (Apollo Client, urql) и использовать Persisted Queries для CDN-кеширования.

    3. Открытые мутации без авторизации на уровне полей

    // Плохо: проверяем авторизацию только на уровне резолвера верхнего уровня
    const resolvers = {
      Mutation: {
        updateUser: (_, args, ctx) => {
          if (!ctx.user) throw new Error('Не авторизован');
          // Но любой авторизованный может менять любого пользователя!
          return db.users.update(args.id, args.input);
        },
      },
    };
    
    // Правильно: проверяем владельца ресурса
    updateUser: (_, { id, input }, ctx) => {
      if (!ctx.user || ctx.user.id !== id) {
        throw new Error('Доступ запрещён');
      }
      return db.users.update(id, input);
    },
    

    4. Глубокая вложенность без ограничений

    Злоумышленник может отправить запрос с глубиной вложенности 100 уровней и положить сервер. Всегда ограничивайте глубину и сложность запросов через graphql-depth-limit или встроенные механизмы.

    5. REST без версионирования

    Ломанье обратной совместимости в REST без версии /v2/ — частая причина инцидентов. GraphQL решает это через deprecation полей, но REST требует явного планирования.

    Заключение

    В 2026 году нет универсального победителя. REST остаётся стандартом для публичных API, простых сервисов и там, где важно HTTP-кеширование. GraphQL выигрывает при сложных данных, множестве клиентов и высоких требованиях к DX.

    Прагматичный выбор: начните с REST. Если через месяц работы обнаружите, что пишете десятки эндпоинтов под разные экраны мобильного приложения или тонете в over-fetching — переходите на GraphQL. Не оптимизируйте архитектуру заранее.

    Иконка глаза2

    Комментарии

    0

    Постройте личный план изучения Next.js 15 - с нуля, React TypeScript, Hooks, SSR и CSS Grid до уровня Middle — бесплатно!

    Next.js 15 - с нуля, React TypeScript, Hooks, SSR и CSS Grid — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Vue 3 и Pinia

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Nuxt

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста WebSocket: что это и как работает в реальных проектах
    Иконка аватараАнтон
    Иконка календаря24 июня 2026
    websocketjavascriptnodejs+ 3juniorИконка уровня junior

    WebSocket: что это и как работает в реальных проектах

    WebSocket — протокол двусторонней связи в реальном времени. Разбираем, как устроено соединение изнутри, и пишем чат на Node.js с нуля.

    Иконка чипа0
    Иконка глаза194
    Иконка комментариев0
    Картинка поста Clean Architecture: чистая архитектура для веб-разработки
    Иконка аватараАнтон
    Иконка календаря02 июля 2026
    архитектураclean architecturetypescript+ 3middleИконка уровня middle

    Clean Architecture: чистая архитектура для веб-разработки

    Clean Architecture разделяет код на независимые слои: бизнес-логика не зависит от фреймворков, БД и внешних сервисов. Разбираем на примерах TypeScript.

    Иконка чипа0
    Иконка глаза185
    Иконка комментариев0
    Картинка поста Async/await в JavaScript: полное руководство 2024
    Иконка аватараАнтон
    Иконка календаря28 июня 2026
    javascriptasyncawait+ 2middleИконка уровня middle

    Async/await в JavaScript: полное руководство 2024

    Async/await в JavaScript — полное руководство с примерами: от основ промисов до параллельного выполнения и обработки ошибок.

    Иконка чипа0
    Иконка глаза142
    Иконка комментариев0
    Иконка чипа0