GraphQL — что это такое, язык запросов и применение в мобильных проектах

Автор: IT Sectr Опубликовано: 2026-03-06 Время чтения: 9 мин

GraphQL — это язык запросов к API и среда выполнения для выполнения этих запросов, разработанная Facebook в 2012 году и открытая в 2015. В отличие от REST, где сервер определяет структуру ответа, GraphQL позволяет клиенту точно указать, какие данные ему нужны, полностью устраняя проблемы overfetching и underfetching. По данным State of JavaScript Survey (2025), GraphQL используют 35% опрошенных разработчиков, а среди крупных компаний его внедрили GitHub, Shopify, Airbnb и The New York Times. GraphQL поддерживает три типа операций: query (чтение), mutation (запись) и subscription (real-time обновления через WebSocket).

Главное

  • GraphQL — язык запросов, где клиент указывает структуру ответа
  • Решает проблемы overfetching (лишние данные) и underfetching (недостаток данных)
  • Поддерживает query, mutation и subscription для разных типов операций
  • Использует единую endpoint (обычно /graphql) вместо множества URL как в REST
  • Основан на системе типов со строгой схемой: все возможные данные описаны заранее

Что такое GraphQL?

GraphQL — это спецификация и среда выполнения для API, которая предоставляет клиенту полный контроль над получаемыми данными. Разработанная инженерами Facebook для решения проблем мобильного приложения News Feed, спецификация была опубликована как открытый стандарт в 2015 году. С 2018 года GraphQL находится под управлением GraphQL Foundation при поддержке Linux Foundation и таких компаний, как Apollo, AWS, GitHub, SAP и другие.

В отличие от REST, где каждый эндпоинт возвращает фиксированную структуру данных, GraphQL использует единый эндпоинт, принимающий строку запроса. Клиент описывает в запросе, какие поля ему нужны, и сервер возвращает ровно их. Например, запрос { user(id: "1") { name email } } вернёт только name и email пользователя, без лишних полей вроде address, phone или createdAt, которые пришлось бы получать в REST.

GraphQL не привязан к какой-либо конкретной базе данных или языку. Спецификация определяет только формат запросов и ответов. Существуют реализации серверов на Node.js (graphql-js, Apollo Server), Kotlin (graphql-kotlin, Netflix DGS Framework), Python (Graphene, Strawberry), Ruby (graphql-ruby) и других языках. Клиентские библиотеки доступны для всех основных платформ, включая Apollo Client для iOS, Android и веба.

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

Архитектура GraphQL состоит из трёх ключевых компонентов: схема (Schema), резолверы (Resolvers) и движок выполнения (GraphQL Engine). Схема определяет, какие типы данных доступны, какие запросы можно выполнять и какие аргументы они принимают. Резолверы — это функции на сервере, которые возвращают данные для каждого поля схемы. Движок выполнения получает входящий запрос, валидирует его по схеме, вызывает соответствующие резолверы и собирает ответ.

Процесс обработки запроса выглядит так:

  • Клиент отправляет POST-запрос на /graphql с JSON-телом { "query": "..." }
  • Сервер парсит запрос, строит AST (Abstract Syntax Tree) и валидирует его по схеме
  • Движок проходит по AST, вызывая резолверы для каждого поля, собирая данные
  • Ответ возвращается в формате JSON, строго соответствующий структуре запроса

Ключевое преимущество архитектуры GraphQL — разрешение на уровне полей. В REST разработчик либо получает все поля ресурса (возможно, с лишними), либо прибегает к расширениям вроде ?fields=name,email. В GraphQL такая фильтрация встроена в язык: каждый запрос явно специфицирует, какие поля нужны, и сервер возвращает ровно их. Это особенно важно для мобильных приложений, где объём передаваемых данных напрямую влияет на скорость загрузки и расход трафика.

Query, Mutation и Subscription

GraphQL определяет три типа операций, каждый из которых соответствует определённому сценарию взаимодействия. Query — для чтения данных, аналогичен GET в REST. Mutation — для изменения данных (создание, обновление, удаление), аналогичен POST/PUT/DELETE. Subscription — для real-time обновлений через WebSocket, что не имеет прямой аналогии в классическом REST (требует дополнительных решений вроде WebSocket или Server-Sent Events).

Базовый синтаксис запросов интуитивно понятен:

js
// Простой query с аргументом
query {
    user(id: "42") {
        name
        email
        avatarUrl
    }
}

// Mutation с возвратом изменённых данных
mutation {
    updateProfile(name: "Иван") {
        id
        name
        updatedAt
    }
}

// Subscription — слушает real-time обновления
subscription {
    newMessage(chatId: "chat_1") {
        id
        text
        sender { name }
    }
}

Query выполняется параллельно — все поля на одном уровне загружаются одновременно. Это позволяет загрузить связанные данные (пользователя и его посты) одним запросом без множества round-trip. Mutation выполняется последовательно — мутации в одном запросе выполняются одна за другой в порядке объявления. Subscription устанавливает постоянное соединение через WebSocket, по которому сервер отправляет данные при наступлении события.

Операции могут принимать переменные для отделения данных от запроса, директивы (@include, @skip) для условного включения полей и фрагменты для повторного использования наборов полей. Эти возможности делают GraphQL-запросы гибкими и переиспользуемыми, что особенно важно в крупных проектах с множеством экранов и компонентов.

Схема и система типов GraphQL

В основе GraphQL лежит система типов, описывающая все возможные данные и операции API. Схема (Schema) — это описание типов, которые может возвращать сервер, и запросов, которые принимает. Схема пишется на языке Schema Definition Language (SDL) и служит контрактом между клиентом и сервером. Клиент может получить схему через интроспекцию — специальный запрос __schema, который возвращает полное описание API.

Пример схемы для блога:

js
// SDL — Schema Definition Language
type User {
    id: ID!
    name: String!
    email: String
    posts: [Post!]!
}

type Post {
    id: ID!
    title: String!
    content: String
    author: User!
}

type Query {
    user(id: ID!): User
    posts(page: Int): [Post!]!
}

Восклицательный знак (!) означает non-null поле — оно гарантированно будет присутствовать в ответе. Квадратные скобки [ ] обозначают список. GraphQL поддерживает скалярные типы (Int, Float, String, Boolean, ID), объектные типы, enum, union, interface и input-типы (для аргументов мутаций). Строгая типизация само-документирует API и позволяет клиентским инструментам генерировать код: TypeScript-типы, Kotlin-дата-классы, Swift-структуры.

Интроспекция — уникальная возможность GraphQL, отсутствующая в REST. Клиент может отправить запрос к схеме и получить полное описание всех типов, полей, аргументов и директив. Это лежит в основе инструментов вроде GraphiQL и Apollo Studio, которые автоматически генерируют документацию и автодополнение для разработчиков. Интроспекция также позволяет писать автоматические тесты, проверяющие соответствие схемы ожидаемой структуре.

Сравнение GraphQL с REST

Выбор между GraphQL и REST — один из ключевых архитектурных вопросов при проектировании API. Оба подхода имеют свои сильные и слабые стороны, и выбор зависит от конкретных требований проекта. REST выигрывает в простоте и универсальности, GraphQL — в гибкости и эффективности запросов. Рассмотрим сравнительную таблицу.

КритерийRESTGraphQL
Структура ответаФиксированная, сервернаяГибкая, клиентская
OverfetchingЧасто — сервер возвращает все поляНет — клиент запрашивает только нужные
Количество запросовМножественные round-tripsОдин запрос на все данные
КэшированиеНативное HTTP-кэшированиеТребует ручной настройки
ТипизацияНе встроена (зависит от формата)Строгая, через SDL-схему
Инструментыcurl, Postman, SwaggerGraphiQL, Apollo Studio, Introspection
Загрузка файловНативно через multipartТребует дополнительных протоколов
ПроизводительностьПредсказуемая, проще оптимизироватьЗависит от сложности вложенных запросов

Основной недостаток GraphQL — сложность кэширования. В REST HTTP-кэширование работает на уровне URL: один запрос к /api/users/42 возвращает всегда одинаковую структуру, и ответ можно кэшировать по URL. В GraphQL все запросы идут на один эндпоинт, структура ответа зависит от тела запроса. Для решения этой проблемы Apollo Client использует нормализованный кэш на стороне клиента, который разбивает ответы на отдельные сущности по id и автоматически обновляет их при получении новых данных.

Ещё один важный аспект — N+1 проблема. При запросе вложенных данных (например, посты пользователя и комментарии к каждому посту) GraphQL может выполнить отдельный SQL-запрос для каждого элемента списка. Решается с помощью DataLoader — утилиты для батчинга и кэширования запросов к базам данных, которая группирует отдельные запросы в один пакетный. В REST эта проблема менее выражена, так как разработчик контролирует структуру ответа на сервере.

Примеры GraphQL запросов

Рассмотрим практические примеры использования GraphQL в мобильном приложении на Kotlin с Apollo Client. Примеры демонстрируют типичные сценарии: загрузка данных для экрана профиля (query), создание нового поста (mutation) и подписка на новые комментарии (subscription). Каждый пример включает как GraphQL-запрос, так и код на клиентской стороне.

Query: загрузка профиля с постами

Один запрос GraphQL загружает пользователя, его последние посты и общее количество подписчиков. В REST для этого потребовалось бы минимум 2-3 запроса: /users/42, /users/42/posts, /users/42/stats. GraphQL объединяет их в один round-trip, сокращая время загрузки экрана на медленных соединениях.

kotlin
// GraphQL запрос (в .graphql файле)
query ProfileScreen($userId: ID!) {
    user(id: $userId) {
        name
        bio
        avatarUrl
        posts(limit: 10) {
            id
            title
            createdAt
        }
        followersCount
        followingCount
    }
}

// Вызов на клиенте (Apollo Client + Kotlin)
val response = apolloClient
    .query(ProfileScreenQuery(userId = "42"))
    .execute()
binding.nameText.text = response.data?.user?.name

Mutation: создание нового поста

Мутация не только создаёт ресурс, но и возвращает его актуальные данные для обновления UI. Поле __typename используется Apollo Client для нормализации кэша — клиент автоматически обновит запись Post в кэше при успешном ответе мутации.

kotlin
// GraphQL мутация
mutation CreatePost($input: CreatePostInput!) {
    createPost(input: $input) {
        id
        title
        createdAt
        author {
            id
            name
        }
    }
}

// Вызов мутации с input-типом
val input = CreatePostInput(
    title = "Новый пост о GraphQL",
    content = "GraphQL упрощает работу с API..."
)
val result = apolloClient
    .mutation(CreatePostMutation(input))
    .execute()

Важное преимущество GraphQL перед REST в контексте мобильной разработки — автоматическая генерация кода. Apollo Client для Kotlin (Apollo GraphQL) генерирует типобезопасные классы из .graphql файлов на этапе сборки. Если сервер изменит схему, проект не соберётся до обновления запросов. Это предотвращает runtime-ошибки, характерные для REST, где изменение структуры ответа может остаться незамеченным при разработке.

Экосистема: Apollo, Relay и инструменты

Экосистема GraphQL включает несколько ключевых библиотек и инструментов, которые упрощают разработку и эксплуатацию. Apollo Client — самая популярная клиентская библиотека, поддерживающая React, iOS, Android и Kotlin Multiplatform. Relay от Facebook — альтернатива для React-приложений с уникальным подходом к управлению данными и кэшированием. Выбор между Apollo и Relay зависит от платформы и требований к производительности.

На серверной стороне лидируют Apollo Server (Node.js), Netflix DGS Framework (Kotlin/Java) и graphql-ruby. Для разработки схемы и тестирования запросов используется GraphiQL — интерактивная IDE, встроенная в браузер. Apollo Studio предоставляет метрики производительности, трассировку запросов и управление схемой для продакшн-среды. Отдельно стоит упомянуть GraphQL Code Generator — инструмент, генерирующий TypeScript, Kotlin, Swift и Dart типы из SDL-схемы.

Для мобильной разработки особый интерес представляет Apollo Kotlin (Apollo GraphQL) — библиотека, полностью написанная на Kotlin с поддержкой корутин, Flow и Multiplatform. Она позволяет использовать единые GraphQL-запросы для Android и iOS в Kotlin Multiplatform проектах. Apollo Kotlin нормализует кэш, поддерживает ошибки на уровне полей (partial errors) и автоматически генерирует модели данных из .graphql файлов. Это делает GraphQL предпочтительным выбором для крупных мобильных проектов, где важны скорость разработки и типобезопасность.

Часто задаваемые вопросы

GraphQL заменяет REST?

GraphQL не заменяет REST, а предлагает альтернативный подход. REST лучше подходит для простых CRUD-API, кэширования через HTTP и публичных API с предсказуемой нагрузкой. GraphQL оптимален для сложных интерфейсов с множеством связанных данных.

Сложно ли мигрировать с REST на GraphQL?

Миграция возможна постепенно: GraphQL может работать как прослойка (gateway) перед существующими REST-сервисами. Многие компании добавляют GraphQL рядом с REST, не отключая старый API. Полная замена требует переписывания резолверов.

Что такое N+1 проблема в GraphQL?

N+1 возникает, когда для каждого элемента списка выполняется отдельный запрос к базе данных. Решается с помощью DataLoader — библиотеки, которая батчит отдельные запросы в один и кэширует результаты в рамках одного HTTP-запроса.

Как GraphQL работает с загрузкой файлов?

Спецификация GraphQL не определяет загрузку файлов напрямую. На практике используются: base64-кодирование (просто, но неэффективно для больших файлов), multipart-запросы по протоколу graphql-multipart-request-spec или отдельный REST-эндпоинт для файлов.

Безопасен ли GraphQL?

Безопасность GraphQL требует дополнительных мер: ограничение глубины вложенности, лимит сложности запроса, rate limiting на уровне операций. Публичная интроспекция схемы может раскрыть структуру данных — в продакшне её рекомендуется отключать.

Итоги

  • GraphQL — язык запросов, где клиент управляет структурой ответа, устраняя overfetching и underfetching
  • Три типа операций: query (чтение), mutation (запись), subscription (real-time)
  • Использует единый эндпоинт и строгую систему типов — SDL-схему
  • В отличие от REST, решает проблему множественных round-trips — все данные за один запрос
  • Требует DataLoader для предотвращения N+1 проблемы и ручной настройки кэширования
  • Основные клиенты: Apollo Client (Android, iOS, Web) и Relay (React)
  • Лучше всего подходит для сложных интерфейсов с множеством связанных сущностей и мобильных приложений

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также