API на Kotlin: REST, GraphQL и gRPC — от REST до микросервисов

Онлайн-тренажер Python для начинающих

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

Начать курс

Kotlin и API: три кита современной разработки

Вы когда-нибудь задумывались, почему одни приложения летают, а другие тормозят даже на флагманах? Секрет часто кроется не в железе, а в том, как они общаются с сервером. Если вы пишете на Kotlin — будь то бэкенд на Ktor или Android-приложение — рано или поздно вы уткнётесь в выбор: REST, GraphQL или gRPC?

На PythonLib мы любим разбираться в технологиях до винтика. Сегодня разложим по полочкам три подхода к работе с API на Kotlin. Никакой воды: только код, сравнение и реальные кейсы. Поехали!

REST API на Kotlin: классика, которая не стареет

REST — это как чёрный костюм: уместен везде, прост и понятен. В Kotlin для REST есть два главных игрока: Ktor (для серверной части) и Retrofit (для клиентской).

Сервер на Ktor: пишем API за 5 минут

Ktor — это фреймворк от JetBrains, созданный специально для Kotlin. Он асинхронный, лёгкий и не навязывает лишних зависимостей.

// build.gradle.kts
implementation("io.ktor:ktor-server-netty:2.3.7")
implementation("io.ktor:ktor-server-content-negotiation:2.3.7")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")

А теперь сам сервер:

import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.server.response.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import kotlinx.serialization.Serializable

@Serializable
data class User(val id: Int, val name: String, val email: String)

fun main() {
    embeddedServer(Netty, port = 8080) {
        install(ContentNegotiation) {
            json()
        }
        routing {
            get("/api/users") {
                val users = listOf(
                    User(1, "Анна", "anna@example.com"),
                    User(2, "Борис", "boris@example.com")
                )
                call.respond(users)
            }
            get("/api/users/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                if (id != null) {
                    call.respond(User(id, "Тест", "test@example.com"))
                } else {
                    call.respondText("Неверный ID", status = io.ktor.http.HttpStatusCode.BadRequest)
                }
            }
        }
    }.start(wait = true)
}

Этот код — полноценный REST API на Kotlin с двумя эндпоинтами. Ktor сам сериализует данные в JSON благодаря kotlinx.serialization.

Клиент на Retrofit: подключаемся к любому API

Retrofit — это стандарт де-факто для Android-разработки. С Kotlin он работает идеально благодаря корутинам.

// build.gradle.kts
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")

Объявляем интерфейс:

interface ApiService {
    @GET("users")
    suspend fun getUsers(): List<User>

    @GET("users/{id}")
    suspend fun getUser(@Path("id") userId: Int): User

    @POST("users")
    suspend fun createUser(@Body user: User): User
}

Создаём клиент и делаем запрос:

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val service = retrofit.create(ApiService::class.java)

// В корутине
GlobalScope.launch {
    val users = service.getUsers()
    println(users)
}

Плюсы REST: простота, кэширование через HTTP, огромное комьюнити.
Минусы: over-fetching и under-fetching данных — часто получаете больше или меньше, чем нужно.

GraphQL на Kotlin: запрашивай только то, что нужно

GraphQL решает главную боль REST — вы сами решаете, какие поля получить. На Kotlin для этого есть библиотеки graphql-kotlin (от Expedia) и KGraphQL.

Сервер с KGraphQL

KGraphQL — самый простой способ добавить GraphQL в ваш Kotlin-проект.

// build.gradle.kts
implementation("com.apurebase:kgraphql:0.18.0")
implementation("com.apurebase:kgraphql-ktor:0.18.0")

Определяем схему и запускаем:

import com.apurebase.kgraphql.GraphQL
import com.apurebase.kgraphql.schema.dsl.SchemaBuilder

data class Book(val id: Int, val title: String, val author: String, val year: Int)

val schema = GraphQL.schema {
    query("books") {
        resolver { ->
            listOf(
                Book(1, "Kotlin в действии", "Дмитрий Жемеров", 2017),
                Book(2, "Чистый код", "Роберт Мартин", 2008)
            )
        }
    }
    query("book") {
        resolver { id: Int ->
            Book(id, "Kotlin в действии", "Дмитрий Жемеров", 2017)
        }
    }
}

// Подключаем к Ktor
fun Application.graphQLModule() {
    install(KGraphQL) {
        schema(schema)
    }
}

Теперь клиент может запросить только нужные поля:

query {
    books {
        title
        author
    }
}

Это даёт гибкость, которой нет в REST. Представьте: мобильное приложение запрашивает только title и author, а веб-версия — ещё и year. Один эндпоинт, два разных ответа.

Клиент GraphQL на Kotlin

Для клиента используем Apollo GraphQL — самую популярную библиотеку:

// build.gradle.kts
implementation("com.apollographql.apollo3:apollo-runtime:3.8.2")
val apolloClient = ApolloClient.Builder()
    .serverUrl("https://api.example.com/graphql")
    .build()

// Запрос
val response = apolloClient.query(BooksQuery()).execute()
val books = response.data?.books
println(books)

Плюсы GraphQL: точные запросы, один эндпоинт, само-документирование (через Introspection).
Минусы: сложность кэширования, нет HTTP-кэша, сложнее мониторинг.

gRPC на Kotlin: скорость и строгость протокола

gRPC — это не просто API, это религия производительности. Он использует HTTP/2, Protobuf и строгую типизацию. Идеален для микросервисов и high-load систем.

Блоги

Рекомендаций по книгам