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 (актуализации в реално време чрез WebSocket).
Основни точки
GraphQL — е спецификация и среда за изпълнение за API, която предоставя на клиента пълен контрол върху получаваните данни. Разработена от инженери на Facebook за решаване на проблемите на мобилното приложение News Feed, спецификацията беше публикувана като отворен стандарт през 2015 г. От 2018 г. GraphQL се управлява от GraphQL Foundation с подкрепата на Linux Foundation и компании като Apollo, AWS, GitHub, SAP и други.
За разлика от REST, където всеки endpoint връща фиксирана структура от данни, GraphQL използва единен endpoint, който приема низ за заявка. Клиентът описва в заявката кои полета са му необходими и сървърът връща точно тях. Например заявката { 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 се състои от три ключови компонента: схема (Schema), резолвери (Resolvers) и двигател за изпълнение (GraphQL Engine). Схемата определя какви типове данни са налични, какви заявки могат да се изпълняват и какви аргументи приемат. Резолверите са функции на сървъра, които връщат данни за всяко поле от схемата. Двигателят за изпълнение получава входящата заявка, валидира я спрямо схемата, извиква съответните резолвери и съставя отговора.
Процесът на обработка на заявка изглежда така:
Ключовото предимство на архитектурата GraphQL е разрешаване на ниво поле. В REST разработчикът или получава всички полета на ресурса (евентуално с излишък), или прибягва до разширения като ?fields=name,email. В GraphQL такова филтриране е вградено в езика: всяка заявка изрично посочва кои полета са необходими и сървърът връща точно тях. Това е особено важно за мобилни приложения, където обемът на предаваните данни пряко влияе върху скоростта на зареждане и потреблението на трафик.
GraphQL дефинира три типа операции, всеки от които отговаря на определен сценарий на взаимодействие. Query — за четене на данни, аналогично на GET в REST. Mutation — за промяна на данни (създаване, актуализиране, изтриване), аналогично на POST/PUT/DELETE. Subscription — за актуализации в реално време чрез WebSocket, което няма пряк аналог в класическия REST (изисква допълнителни решения като WebSocket или Server-Sent Events).
Основният синтаксис на заявките е интуитивен:
// Проста заявка с аргумент
query {
user(id: "42") {
name
email
avatarUrl
}
}
// Mutation с връщане на променени данни
mutation {
updateProfile(name: "Иван") {
id
name
updatedAt
}
}
// Subscription — слуша актуализации в реално време
subscription {
newMessage(chatId: "chat_1") {
id
text
sender { name }
}
}
Query се изпълнява паралелно — всички полета на едно и също ниво се зареждат едновременно. Това позволява зареждане на свързани данни (потребител и неговите публикации) с една заявка без множество round-trip-ове. Mutation се изпълнява последователно — мутациите в една заявка се изпълняват една след друга по реда на деклариране. Subscription установява постоянна връзка чрез WebSocket, по която сървърът изпраща данни при настъпване на събитие.
Операциите могат да приемат променливи за отделяне на данните от заявката, директиви (@include, @skip) за условно включване на полета и фрагменти за повторно използване на набори от полета. Тези възможности правят GraphQL заявките гъвкави и многократно използваеми, което е особено важно в големи проекти с множество екрани и компоненти.
В основата на GraphQL стои система от типове, която описва всички възможни данни и операции на API. Схемата (Schema) е описание на типовете, които сървърът може да върне, и на заявките, които приема. Схемата се пише на езика Schema Definition Language (SDL) и служи като договор между клиента и сървъра. Клиентът може да получи схемата чрез интроспекция — специална заявка __schema, която връща пълно описание на API.
Пример за схема за блог:
// 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 е един от ключовите архитектурни въпроси при проектирането на API. И двата подхода имат своите силни и слаби страни и изборът зависи от конкретните изисквания на проекта. REST печели в простота и универсалност, GraphQL — в гъвкавост и ефективност на заявките. Нека разгледаме сравнителната таблица.
| Критерий | REST | GraphQL |
|---|---|---|
| Структура на отговора | Фиксирана, сървърна | Гъвкава, клиентска |
| Overfetching | Често — сървърът връща всички полета | Не — клиентът изисква само необходимите |
| Брой заявки | Множество round-trip-ове | Една заявка за всички данни |
| Кеширане | Вродено HTTP кеширане | Изисква ръчна конфигурация |
| Типизиране | Не е вградено (зависи от формата) | Строго, чрез SDL схема |
| Инструменти | curl, Postman, Swagger | GraphiQL, Apollo Studio, Introspection |
| Качване на файлове | Вродено чрез multipart | Изисква допълнителни протоколи |
| Производителност | Предвидима, по-лесна за оптимизиране | Зависи от сложността на вложените заявки |
Основният недостатък на GraphQL е трудността на кеширането. В REST HTTP кеширането работи на ниво URL: една заявка към /api/users/42 винаги връща една и съща структура и отговорът може да бъде кеширан по URL. В GraphQL всички заявки отиват към един endpoint, структурата на отговора зависи от тялото на заявката. За решаване на този проблем Apollo Client използва нормализиран кеш от страна на клиента, който разделя отговорите на отделни единици по id и автоматично ги актуализира при получаване на нови данни.
Друг важен аспект е проблемът N+1. При заявка на вложени данни (например публикации на потребител и коментари към всяка публикация) GraphQL може да изпълни отделна SQL заявка за всеки елемент от списъка. Решава се с DataLoader — помощна програма за групиране и кеширане на заявки към бази данни, която обединява отделните заявки в една групова. В REST този проблем е по-слабо изразен, тъй като разработчикът контролира структурата на отговора на сървъра.
Нека разгледаме практически примери за използване на GraphQL в мобилно приложение на Kotlin с Apollo Client. Примерите демонстрират типични сценарии: зареждане на данни за екрана на профила (query), създаване на нова публикация (mutation) и абонамент за нови коментари (subscription). Всеки пример включва както GraphQL заявката, така и кода от страна на клиента.
Една GraphQL заявка зарежда потребителя, последните му публикации и общия брой последователи. В REST биха били необходими поне 2-3 заявки: /users/42, /users/42/posts, /users/42/stats. GraphQL ги обединява в един round-trip, съкращавайки времето за зареждане на екрана при бавни връзки.
// 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
Мутацията не само създава ресурса, но и връща актуалните му данни за актуализиране на UI. Полето __typename се използва от Apollo Client за нормализиране на кеша — клиентът автоматично актуализира записа Post в кеша при успешен отговор на мутацията.
// 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 файлове на етапа на компилация. Ако сървърът промени схемата, проектът няма да се компилира, докато заявките не бъдат актуализирани. Това предотвратява грешки по време на изпълнение, характерни за REST, където промяната в структурата на отговора може да остане незабелязана по време на разработката.
Екосистемата на 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, а предлага алтернативен подход. REST е по-подходящ за прости CRUD API, кеширане чрез HTTP и публични API с предвидимо натоварване. GraphQL е оптимален за сложни интерфейси с множество свързани данни.
Миграцията е възможна постепенно: GraphQL може да работи като междинен слой (gateway) пред съществуващи REST услуги. Много компании добавят GraphQL до REST, без да изключват стария API. Пълната замяна изисква пренаписване на резолверите.
N+1 възниква, когато за всеки елемент от списъка се изпълнява отделна заявка към базата данни. Решава се с DataLoader — библиотека, която групира отделните заявки в една и кешира резултатите в рамките на една HTTP заявка.
Спецификацията на GraphQL не дефинира директно качване на файлове. На практика се използват: base64 кодиране (просто, но неефективно за големи файлове), multipart заявки по протокола graphql-multipart-request-spec или отделен REST endpoint за файлове.
Сигурността на GraphQL изисква допълнителни мерки: ограничаване на дълбочината на влагане, лимит на сложност на заявката, rate limiting на ниво операции. Публичната интроспекция на схемата може да разкрие структурата на данните — в продукционна среда се препоръчва да бъде изключена.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също