Подписывайтесь:

Блог AST-SoftPro

Проектирование API: REST vs GraphQL vs gRPC для бизнес-задач

05.07.2026 12 мин чтения
Проектирование API: REST vs GraphQL vs gRPC для бизнес-задач

Проектирование API: REST vs GraphQL vs gRPC для бизнес-задач

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

REST: стандарт для бизнес-приложений

REST (Representational State Transfer) — самый распространённый подход к проектированию API. Он использует HTTP-методы (GET, POST, PUT, DELETE) и URL для обозначения ресурсов.

Преимущества REST:

  • Простота. Любой разработчик понимает, что GET /users/123 возвращает пользователя с ID 123.

  • Кэширование. HTTP-кэширование работает из коробки — браузеры, CDN, прокси-серверы понимают REST.

  • Инструменты. Postman, Swagger, Insomnia — все инструменты заточены под REST.

  • Отладка. Можно открыть URL в браузере и увидеть результат.

Пример REST API на FastAPI:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional

app = FastAPI(title="Shop REST API")

class ProductCreate(BaseModel):
    name: str
    price: int
    description: Optional[str] = None

class ProductResponse(BaseModel):
    id: int
    name: str
    price: int
    description: Optional[str] = None

# В памяти для примера
products_db: dict[int, ProductResponse] = {}

@app.get("/products", response_model=List[ProductResponse])
def list_products():
    return list(products_db.values())

@app.get("/products/{product_id}", response_model=ProductResponse)
def get_product(product_id: int):
    if product_id not in products_db:
        raise HTTPException(404, "Product not found")
    return products_db[product_id]

@app.post("/products", response_model=ProductResponse, status_code=201)
def create_product(product: ProductCreate):
    pid = len(products_db) + 1
    p = ProductResponse(id=pid, **product.dict())
    products_db[pid] = p
    return p

@app.put("/products/{product_id}", response_model=ProductResponse)
def update_product(product_id: int, product: ProductCreate):
    if product_id not in products_db:
        raise HTTPException(404, "Product not found")
    p = ProductResponse(id=product_id, **product.dict())
    products_db[product_id] = p
    return p

@app.delete("/products/{product_id}", status_code=204)
def delete_product(product_id: int):
    if product_id not in products_db:
        raise HTTPException(404, "Product not found")
    del products_db[product_id]
    return None

Когда REST подходит:

  • Публичные API, доступные из браузера

  • CRUD-приложения (каталоги, дашборды, админки)

  • Интеграции с внешними сервисами

  • Когда важно кэширование на CDN

GraphQL: гибкость для сложных интерфейсов

GraphQL — это запросный язык и runtime, который позволяет клиенту запрашивать именно те данные, которые ему нужны. Вместо множества REST-эндпоинтов — один эндпоинт с гибкими запросами.

Преимущества GraphQL:

  • Точные запросы. Клиент получает только нужные поля — нет избыточной или недостаточной выборки данных.

  • Один запрос вместо многих. Вместо 5 HTTP-запросов для получения данных — один GraphQL-запрос.

  • Схема как документация. Типы, поля и мутации описаны в схеме, которая генерирует документацию.

  • Гибкость клиента. Фронтенд может запрашивать новые поля без изменения бэкенда.

Пример GraphQL на Python (Strawberry):

import strawberry
from typing import List, Optional

@strawberry.type
class Product:
    id: int
    name: str
    price: int
    description: Optional[str] = None

@strawberry.type
class Query:
    @strawberry.field
    def products(self) -> List[Product]:
        return [Product(id=1, name="Laptop", price=99999)]

    @strawberry.field
    def product(self, id: int) -> Optional[Product]:
        return Product(id=id, name="Phone", price=49999)

@strawberry.type
class Mutation:
    @strawberry.mutation
    def create_product(
        self,
        name: str,
        price: int,
        description: Optional[str] = None,
    ) -> Product:
        return Product(id=2, name=name, price=price, description=description)

schema = strawberry.Schema(query=Query, mutation=Mutation)

Запрос клиента:

query {
  products {
    id
    name
    price
  }
}

Ответ:

{
  "data": {
    "products": [
      {"id": 1, "name": "Laptop", "price": 99999}
    ]
  }
}

Когда GraphQL подходит:

  • Сложные дашборды с множеством связанных сущностей

  • Мобильные приложения (экономия трафика)

  • Когда фронтенд и бэкенд разрабатываются разными командами

  • Когда клиенты имеют разные потребности в данных

Ограничения GraphQL:

  • Нет кэширования из коробки. HTTP-кэширование не работает, нужно кэшировать на уровне resolvers.

  • Сложность отладки. Нельзя открыть URL в браузере.

  • N+1 проблема. Без DataLoader каждый запрос может генерировать отдельный запрос к базе данных.

  • Не подходит для файлов. Загрузка файлов через GraphQL — это обходные пути.

gRPC: скорость для внутренней коммуникации

gRPC — это RPC-фреймворк от Google, который использует HTTP/2 и Protocol Buffers для сериализации. Он предназначен для высокопроизводительной коммуникации между сервисами.

Преимущества gRPC:

  • Производительность. Protocol Buffers быстрее JSON в 3-5 раз, а HTTP/2 поддерживает мультиплексирование.

  • Строгая типизация. Схема (.proto-файл) генерирует код на всех языках. Ошибки типов обнаруживаются на этапе компиляции.

  • Стримминг. Поддержка серверного, клиентского и двунаправленного стримминга.

  • Обнаружение сервисов. Встроенная поддержка метаданных и таймаутов.

Пример gRPC на Python:

Сначала определение сервиса (proto-файл):

syntax = "proto3";

package shop;

service ProductService {
  rpc GetProduct (ProductRequest) returns (Product);
  rpc ListProducts (ListRequest) returns (ProductList);
  rpc CreateProduct (Product) returns (Product);
}

message ProductRequest {
  int32 id = 1;
}

message ListRequest {
  int32 page = 1;
  int32 page_size = 2;
}

message Product {
  int32 id = 1;
  string name = 2;
  int32 price = 3;
  string description = 4;
}

message ProductList {
  repeated Product products = 1;
  int32 total = 2;
}

Реализация на Python:

from shop_pb2 import ProductRequest, Product, ProductList
from shop_pb2_grpc import ProductServiceServicer, add_ProductServiceServicer_to_server
import grpc

class ProductServiceImpl(ProductServiceServicer):
    def GetProduct(self, request, context):
        # Логика получения продукта
        return Product(id=request.id, name="Laptop", price=99999)

    def ListProducts(self, request, context):
        return ProductList(
            products=[Product(id=1, name="Laptop", price=99999)],
            total=1,
        )

def serve():
    server = grpc.server()
    add_ProductServiceServicer_to_server(ProductServiceImpl(), server)
    server.add_insecure_port("[::]:50051")
    server.start()
    server.wait_for_termination()

if __name__ == "__main__":
    serve()

Когда gRPC подходит:

  • Коммуникация между микросервисами

  • Высоконагруженные системы (тысячи RPS)

  • Когда важна строгая типизация

  • Стриминг данных (мониторинг в реальном времени, чаты)

  • Мультиязычные проекты (генерация кода на Go, Java, Python)

Ограничения gRPC:

  • Не подходит для публичных API. Нет CORS, нет кэширования, нет браузера.

  • Сложнее отладка. Нельзя открыть в браузере, нужны специальные инструменты.

  • Дополнительная настройка. Нужен proto-файл, генерация кода, gRPC-сервер.

Сравнение подходов

Критерий REST GraphQL gRPC
Скорость разработки Высокая Средняя Средняя
Производительность Средняя Средняя Высокая
Кэширование HTTP из коробки Нет (нужен Redis) Нет
Браузерная поддержка Да Да (через HTTP) Нет
Строгая типизация Нет (OpenAPI) Да (схема) Да (.proto)
Стриминг WebSockets Subscriptions Да (из коробки)
Мультиязычность Да (JSON) Да (JSON) Да (генерация)
Подходит для публичного API Да Да Нет
Подходит для микросервисов Да Нет Да

Гибридный подход: когда использовать всё

На практике редко используется один подход. Типичная архитектура:

[Frontend] ──REST/GraphQL──> [API Gateway] ──gRPC──> [Orders Service]
                                    │                  │
                                    ├──────────────────┼──gRPC──> [Products Service]
                                    │                  │
                                    └──────────────────┴──gRPC──> [Users Service]
  • REST — для публичного API и простых CRUD-операций

  • GraphQL — для дашборда с сложными запросами

  • gRPC — для внутренней коммуникации между микросервисами

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

  1. REST для всего. Использование REST для внутренней коммуникации между микросервисами — избыточно. gRPC быстрее и типобезопаснее.

  2. GraphQL для файлов. Загрузка файлов через GraphQL — антипаттерн. Используйте REST для файловых операций.

  3. gRPC для фронтенда. gRPC не работает в браузере без обходных путей (gRPC-Web). Для фронтенда — REST или GraphQL.

  4. Отсутствие версионирования REST. API без версионирования (/api/v1/...) создаёт проблемы при изменении контракта.

  5. Отсутствие схемы GraphQL. GraphQL без строгой схемы — это просто JSON-эндпоинт. Схема — главное преимущество.

Заключение

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

Главное правило: не выбирайте один подход для всего. Используйте каждый там, где он лучше всего подходит.

Ключевые моменты:

  1. REST — стандарт для публичных API и CRUD-приложений. Прост, кэшируется, отлаживается в браузере.

  2. GraphQL — для сложных дашбордов и мобильных приложений. Один запрос вместо многих, точные данные.

  3. gRPC — для внутренней коммуникации микросервисов. Быстрый, типобезопасный, со стримингом.

  4. Гибридный подход (REST + GraphQL + gRPC) — обычная практика в реальных проектах.

  5. Не используйте gRPC для фронтенда и GraphQL для файлов — это антипаттерны.

AI-Помощник