REST или GraphQL: какой подход к API выбрать?
REST и GraphQL решают одну и ту же базовую задачу — позволяют клиенту запрашивать данные у сервера по HTTP, — но с разными компромиссами, и выбор между ними часто воспринимают куда идеологичнее, чем следовало бы. Ни один из них не лучше сам по себе. Каждый просто лучше подходит для определённых типов продуктов и команд.
Как работает REST и в чём его сильные стороны
REST строит API вокруг ресурсов — URL для пользователя, URL для заказа, URL для списка товаров — и стандартных HTTP-методов (GET, POST, PUT, DELETE) для работы с ними. Этот подход так давно стал стандартом для веб-API, что инструменты, механизмы кэширования и опыт команд вокруг него давно сложились. Любой HTTP-кэш, CDN и браузер уже умеют кэшировать GET-запрос по URL — это реальное практическое преимущество, которое REST получает даром.
Неудобства у REST начинаются, когда клиенту нужны данные сразу из нескольких ресурсов. Экрану мобильного приложения, которому нужны профиль пользователя, его последние пять заказов и позиции каждого заказа, может понадобиться три-четыре отдельных REST-вызова или специальный объединённый эндпоинт, созданный только для этого экрана. А его потом придётся поддерживать наряду со всеми остальными эндпоинтами под конкретные экраны по мере роста продукта.
Как работает GraphQL и в чём его сильные стороны
GraphQL переворачивает эту модель: не сервер решает, данные какой структуры возвращает каждый эндпоинт, а клиент отправляет запрос с описанием именно тех полей, которые ему нужны, — возможно, сразу из нескольких связанных ресурсов, — и получает ровно это, не больше и не меньше. Гибкость в рамках одного запроса — главное преимущество GraphQL, и оно действительно ценно для продуктов с множеством разных экранов или клиентских приложений (веб, iOS, Android), каждому из которых нужен немного свой срез одних и тех же данных: одна гибкая схема может обслуживать их все без разрастания числа специальных эндпоинтов.
Но и компромиссы здесь вполне реальны. Кэширование сложнее, потому что GraphQL API — это обычно один POST-эндпоинт, а не множество кэшируемых GET-адресов, поэтому нужны специальные механизмы кэширования (сохранённые запросы, нормализованные клиентские кэши вроде Apollo или Relay) вместо стандартного HTTP-кэширования. Сложностью запросов нужно активно управлять на стороне сервера: технически клиент может запросить глубоко вложенные, ресурсоёмкие данные, чего примитивный REST-эндпоинт изначально бы просто не позволил. А порог входа для команды, которая только знакомится с GraphQL, — проектирование схемы, резолверы, клиентские инструменты — выше, чем у REST.
Как принять решение на практике
- Выбирайте REST, если модель данных проще, типов клиентов немного, вы хотите опираться на стандартное HTTP-кэширование и инструменты или ваша команда уже хорошо знает REST, а продукт не требует большего.
- Выбирайте GraphQL, если один бэкенд обслуживает несколько очень разных клиентских приложений, модель данных действительно реляционная и клиентам часто нужно проходить по этим связям в одном запросе или если избыточная и недостаточная выборка данных в REST стала реальной, регулярной проблемой, а не гипотетической.
- Ни тот, ни другой не обязывает делать выбор «всё или ничего» для всей системы: многие реальные продукты используют REST для простых CRUD-сервисов и GraphQL как агрегирующий слой перед ними для клиентских запросов — или наоборот.
Что важнее выбора подхода к API
Что бы вы ни выбрали, удобство работы с API в долгосрочной перспективе определяют одни и те же вещи независимо от подхода: понятные и единообразные названия, корректная обработка ошибок вместо кода 200 на всё подряд, продуманная пагинация и документация, которая действительно поддерживается в актуальном состоянии. Хорошо спроектированный REST API всегда лучше плохо спроектированного GraphQL — и наоборот. Формат значит гораздо меньше, чем дисциплина, которая за ним стоит.
Выбор архитектуры API под реальные особенности продукта, а не просто более модного варианта, — часть нашей работы по разработке ПО и веб-разработке в Burncode для каждого бэкенда, который мы создаём. Ошибку здесь дорого исправлять, когда от API уже зависит десяток клиентов.