Skip to content
Server Plugin

Ktor 서버의 콘텐츠 협상 및 직렬화

필수 의존성: io.ktor:ktor-server-content-negotiation

코드 예시: json-kotlinx

네이티브 서버
Ktor는 Kotlin/Native를 지원하며 추가 런타임 또는 가상 머신 없이 서버를 실행할 수 있습니다.
지원: ✅

ContentNegotiation 플러그인은 두 가지 주요 목적을 수행합니다:

  • 클라이언트와 서버 간의 미디어 타입 협상. 이를 위해 AcceptContent-Type 헤더를 사용합니다.
  • 특정 형식으로 콘텐츠를 직렬화/역직렬화. Ktor는 기본적으로 다음 형식을 지원합니다: JSON, XML, CBOR, ProtoBuf.

클라이언트 측에서는 Ktor가 콘텐츠 직렬화/역직렬화를 위한 ContentNegotiation 플러그인을 제공합니다.

의존성 추가

ContentNegotiation

ContentNegotiation을(를) 사용하려면 빌드 스크립트에 ktor-server-content-negotiation 아티팩트를 포함해야 합니다:

Kotlin
Groovy
XML

특정 형식의 직렬 변환기(serializer)는 추가 아티팩트를 필요로 합니다. 예를 들어, kotlinx.serialization은 JSON을 위해 ktor-serialization-kotlinx-json 의존성이 필요합니다.

직렬화

kotlinx.serialization 변환기(converter)를 사용하기 전에, Setup 섹션에 설명된 대로 Kotlin serialization 플러그인을 추가해야 합니다.

JSON

JSON 데이터를 직렬화/역직렬화하려면 다음 라이브러리 중 하나를 선택할 수 있습니다: kotlinx.serialization, Gson 또는 Jackson.

빌드 스크립트에 ktor-serialization-kotlinx-json 아티팩트를 추가합니다:

Kotlin
Groovy
XML

빌드 스크립트에 ktor-serialization-gson 아티팩트를 추가합니다:

Kotlin
Groovy
XML

빌드 스크립트에 ktor-serialization-jackson 아티팩트를 추가합니다:

Kotlin
Groovy
XML

XML

XML을 직렬화/역직렬화하려면 빌드 스크립트에 ktor-serialization-kotlinx-xml을 추가합니다:

Kotlin
Groovy
XML

XML 직렬화는 jsNode 타겟에서 지원되지 않습니다.

CBOR

CBOR을 직렬화/역직렬화하려면 빌드 스크립트에 ktor-serialization-kotlinx-cbor을 추가합니다:

Kotlin
Groovy
XML

ProtoBuf

ProtoBuf를 직렬화/역직렬화하려면 빌드 스크립트에 ktor-serialization-kotlinx-protobuf을 추가합니다:

Kotlin
Groovy
XML

ContentNegotiation 설치

ContentNegotiation 플러그인을 애플리케이션에 설치하려면, 지정된

모듈
모듈을 사용하면 라우트를 그룹화하여 애플리케이션 구조를 만들 수 있습니다.
에서 install 함수에 전달하세요. 아래 코드 스니펫은 ContentNegotiation을(를) 설치하는 방법을 보여줍니다...

  • ... embeddedServer 함수 호출 내부.
  • ... Application 클래스의 확장 함수인 명시적으로 정의된 module 내부.
kotlin
kotlin

직렬 변환기 구성

Ktor는 기본적으로 다음 형식을 지원합니다: JSON, XML, CBOR. 또한 사용자 정의 직렬 변환기(serializer)를 구현할 수 있습니다.

JSON 직렬 변환기

애플리케이션에 JSON 직렬 변환기(serializer)를 등록하려면 json 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*

install(ContentNegotiation) {
    json()
}

또한 json 메서드를 사용하면 JsonBuilder에서 제공하는 직렬화 설정을 조정할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin

    install(ContentNegotiation) {
        json(Json {
            prettyPrint = true
            isLenient = true
        })

애플리케이션에 Gson 직렬 변환기(serializer)를 등록하려면 gson 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.gson.*

install(ContentNegotiation) {
    gson()
}

또한 gson 메서드를 사용하면 GsonBuilder에서 제공하는 직렬화 설정을 조정할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin
install(ContentNegotiation) {
    gson {
        registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
        setDateFormat(DateFormat.LONG, DateFormat.SHORT)
        setPrettyPrinting()
    }

애플리케이션에 Jackson 직렬 변환기(serializer)를 등록하려면 jackson 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.jackson.*

install(ContentNegotiation) {
    jackson()
}

또한 jackson 메서드를 사용하면 ObjectMapper에서 제공하는 직렬화 설정을 조정할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin
install(ContentNegotiation) {
    jackson {
        configure(SerializationFeature.INDENT_OUTPUT, true)
        setDefaultPrettyPrinter(DefaultPrettyPrinter().apply {
            indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
            indentObjectsWith(DefaultIndenter("  ", "
"))
        })
        registerModule(JavaTimeModule())  // support java.time.* types
    }
}

XML 직렬 변환기

애플리케이션에 XML 직렬 변환기(serializer)를 등록하려면 xml 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.xml.*

install(ContentNegotiation) {
    xml()
}

또한 xml 메서드를 사용하면 XML 직렬화 설정에 접근할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.xml.*
import nl.adaptivity.xmlutil.*
import nl.adaptivity.xmlutil.serialization.*

install(ContentNegotiation) {
    xml(format = XML {
        xmlDeclMode = XmlDeclMode.Charset
    })
}

CBOR 직렬 변환기

애플리케이션에 CBOR 직렬 변환기(serializer)를 등록하려면 cbor 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.cbor.*

install(ContentNegotiation) {
    cbor()
}

또한 cbor 메서드를 사용하면 CborBuilder에서 제공하는 CBOR 직렬화 설정에 접근할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.cbor.*
import kotlinx.serialization.cbor.*

install(ContentNegotiation) {
    cbor(Cbor {
        ignoreUnknownKeys = true
    })
}

ProtoBuf 직렬 변환기

애플리케이션에 ProtoBuf 직렬 변환기(serializer)를 등록하려면 protobuf 메서드를 호출하세요:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*

install(ContentNegotiation) {
    protobuf()
}

또한 protobuf 메서드를 사용하면 ProtoBufBuilder에서 제공하는 ProtoBuf 직렬화 설정에 접근할 수 있습니다. 예를 들면 다음과 같습니다:

kotlin
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*
import kotlinx.serialization.protobuf.*

install(ContentNegotiation) {
    protobuf(ProtoBuf {
        encodeDefaults = true
    })
}

사용자 정의 직렬 변환기

지정된 Content-Type에 대한 사용자 정의 직렬 변환기(serializer)를 등록하려면 register 메서드를 호출해야 합니다. 아래 예시에서는 application/jsonapplication/xml 데이터를 역직렬화하기 위해 두 개의 사용자 정의 직렬 변환기가 등록됩니다:

kotlin
install(ContentNegotiation) {
    register(ContentType.Application.Json, CustomJsonConverter())
    register(ContentType.Application.Xml, CustomXmlConverter())
}

데이터 수신 및 전송

데이터 클래스 생성

수신된 데이터를 객체로 역직렬화하려면 데이터 클래스를 생성해야 합니다. 예를 들면 다음과 같습니다:

kotlin
@Serializable

kotlinx.serialization을 사용하는 경우, 이 클래스에 @Serializable 어노테이션이 있는지 확인하세요:

kotlin
import kotlinx.serialization.*
import io.ktor.server.util.getValue

@Serializable

다음 타입의 직렬화/역직렬화는 kotlinx.serialization 라이브러리에서 지원됩니다:

데이터 수신

요청에 대한 콘텐츠를 수신하고 변환하려면 데이터 클래스를 매개변수로 받는 receive 메서드를 호출하세요:

kotlin

        post("/customer") {
            val customer = call.receive<Customer>()
            customerStorage.add(customer)
            call.respondText("Customer stored correctly", status = HttpStatusCode.Created)

요청의 Content-Type은 요청 처리를 위한 직렬 변환기를 선택하는 데 사용됩니다. 아래 예시는 JSON 또는 XML 데이터를 포함하며 서버 측에서 Customer 객체로 변환되는 샘플 HTTP 클라이언트 요청을 보여줍니다:

HTTP
POST http://0.0.0.0:8080/customer
Content-Type: application/json

{
  "id": 3,
  "firstName": "Jet",
  "lastName": "Brains"
}
HTTP
POST http://0.0.0.0:8080/customer
Content-Type: application/xml

<Customer id="3" firstName="Jet" lastName="Brains"/>

전체 예시는 다음에서 찾을 수 있습니다: json-kotlinx.

데이터 전송

응답에 데이터 객체를 전달하려면 respond 메서드를 사용할 수 있습니다:

kotlin
routing {
    get("/customer/{id}") {
        val id: Int by call.parameters
        val customer: Customer = customerStorage.find { it.id == id }!!
        call.respond(customer)

이 경우 Ktor는 Accept 헤더를 사용하여 필요한 직렬 변환기를 선택합니다. 전체 예시는 다음에서 찾을 수 있습니다: json-kotlinx.

사용자 정의 직렬 변환기 구현

Ktor에서는 데이터를 직렬화/역직렬화하기 위해 자신만의 직렬 변환기를 작성할 수 있습니다. 이를 위해서는 ContentConverter 인터페이스를 구현해야 합니다:

kotlin
interface ContentConverter {
    suspend fun serialize(contentType: ContentType, charset: Charset, typeInfo: TypeInfo, value: Any): OutgoingContent?
    suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any?
}

구현 예시로 GsonConverter 클래스를 살펴보세요.