Сетевой слой мобильного приложения
Запрос уходит, ответ не приходит, timeout — 30 секунд. Пользователь смотрит на спиннер. Сети нет — мобильная карта в метро. Или сеть есть, но сервер вернул 200 с HTML-страницей ошибки вместо JSON — и приложение крашит при JSONDecoder.decode(). Сетевой слой мобильного приложения обязан обрабатывать эти сценарии явно, а не полагаться на то, что «соединение всегда есть».
REST и выбор клиентской библиотеки
Alamofire (iOS) — де-факто стандарт для Swift-проектов. Поверх URLSession добавляет request chaining, response validation, automatic retry, certificate pinning через ServerTrustManager. AF.request() с .validate() возвращает ошибку для любого статус-кода вне 200–299. Без .validate() Alamofire считает 404 и 500 успешными ответами.
AF.request("https://api.example.com/orders")
.validate(statusCode: 200..<300)
.responseDecodable(of: OrdersResponse.self) { response in
switch response.result {
case .success(let orders): // ...
case .failure(let error): // всегда обрабатываем
}
}
С Swift Concurrency — async-версия через serializingDecodable:
let response = try await AF.request(url)
.validate()
.serializingDecodable(OrdersResponse.self).value
Retrofit (Android) — аннотационный HTTP-клиент поверх OkHttp. Интерфейс с аннотациями компилируется в реализацию. @GET, @POST, @Path, @Query, @Body — декларативное описание API. Converters (GsonConverterFactory, MoshiConverterFactory, KotlinxSerializationConverterFactory) десериализуют ответ автоматически.
OkHttp под капотом дает: connection pooling, transparent gzip, HTTP/2 multiplex. HttpLoggingInterceptor — логирование запросов/ответов в debug-сборке. Authenticator — автоматический refresh токена при 401.
Ktor (KMM/Flutter) — мультиплатформенный HTTP-клиент. На iOS работает через Darwin engine (URLSession), на Android — через OkHttp. Единый код для обеих платформ при KMM-архитектуре.
GraphQL: когда REST создаёт проблемы
REST возвращает фиксированную структуру. Экран профиля нужен name, avatar, email — сервер возвращает 40 полей. Экран списка нужен только id и name — тот же эндпоинт, те же 40 полей. Over-fetching.
GraphQL решает это: клиент запрашивает ровно те поля, которые нужны. Это критично для мобайла, где трафик и время парсинга — реальные ограничения.
Apollo iOS и Apollo Kotlin — клиенты для GraphQL. Кодогенерация по схеме: schema.graphql + query-файлы → типизированные Swift/Kotlin-классы. Нет строковых запросов, нет ручного парсинга — всё типобезопасно на этапе компиляции.
Subscriptions через WebSocket встроены в Apollo — real-time обновления данных без polling.
Практическое ограничение: GraphQL сложнее кешировать на уровне HTTP (один POST-эндпоинт). Apollo использует нормализованный in-memory кеш с InMemoryNormalizedCache — запросы с пересекающимися данными обновляют кеш без дублирования.
WebSocket: real-time без polling
Polling (setInterval каждые 5 секунд) — это трата батареи и трафика. WebSocket — постоянное двунаправленное соединение.
iOS: URLSessionWebSocketTask (нативный, iOS 13+). Отправка через send(.string(message)), получение через receive() в async loop.
Android: OkHttp WebSocket — newWebSocket() возвращает WebSocket, WebSocketListener обрабатывает события: onOpen, onMessage, onClosing, onFailure.
Обязательная обработка reconnect: мобильная сеть нестабильна. При onFailure — экспоненциальный backoff: 1с → 2с → 4с → 8с → максимум 60с. Без reconnect-логики приложение теряет соединение в метро и не восстанавливает его.
Socket.IO — надстройка над WebSocket с автоматическим reconnect, room/namespace, fallback на long-polling. Удобен, если бэкенд уже использует Socket.IO. Для новых проектов предпочтительнее нативный WebSocket — меньше зависимостей.
gRPC: для высоконагруженных сервисов
gRPC с protobuf — бинарная сериализация против JSON: меньше размер, быстрее парсинг. Для мобайла это ощутимо на слабых устройствах и медленной сети.
grpc-swift для iOS, grpc-kotlin для Android. Protobuf-схема компилируется в типизированные классы на обеих платформах. Streaming (server-side, client-side, bidirectional) — нативная возможность gRPC, не надстройка.
Практический порог применения: gRPC оправдан при высокой частоте запросов (trading, IoT, внутренние микросервисы) или когда latency критична. Для обычного CRUD-API REST проще в дебаге и мониторинге.
Offline-режим и кеширование
Мобильное приложение обязано работать без сети — хотя бы в read-only режиме. Пользователь теряет соединение, видит ранее загруженные данные, а не экран ошибки.
iOS: URLCache для HTTP-кеширования (уважает Cache-Control заголовки). Core Data или SwiftData для структурированных данных. NWPathMonitor — отслеживание доступности сети.
Android: OkHttp Cache + CacheControl в запросах. Room для локального хранилища. ConnectivityManager.NetworkCallback — мониторинг состояния сети.
Паттерн offline-first: при открытии экрана сначала показываем данные из кеша, параллельно делаем сетевой запрос, обновляем UI при получении ответа. Пользователь видит контент немедленно, а не спиннер.
Certificate Pinning
Корпоративный proxy может перехватить HTTPS-соединение через подмену сертификата. Certificate pinning предотвращает это: приложение принимает только конкретный сертификат или публичный ключ.
Alamofire: ServerTrustManager с PinnedCertificatesTrustEvaluator. OkHttp: CertificatePinner с SHA-256 хешем публичного ключа.
Операционная сложность: при ротации сертификата на сервере все старые версии приложения перестанут работать. Решение — pinning на публичный ключ CA, а не на leaf-сертификат, или поддержка нескольких пинов одновременно с grace period.
Сроки
Реализация сетевого слоя с REST, retry, кешированием и offline-режимом — 1–2 недели. Добавление GraphQL или WebSocket — ещё 1–2 недели в зависимости от сложности. gRPC с protobuf — 2–3 недели включая генерацию кода и интеграцию. Стоимость рассчитывается индивидуально после анализа требований к API и offline-поведению.







