I/O 상호 운용성
코드 예제: client-io-interop, server-io-interop
Ktor는 기본 I/O 프리미티브를 제공하는 멀티플랫폼 Kotlin 라이브러리인 kotlinx-io를 기반으로 구축된 논블로킹(non-blocking), 비동기 I/O를 지원합니다. 이를 통해 모든 데이터를 메모리에 로드하지 않고도 HTTP 요청 및 응답 본문을 스트리밍하고, 파일을 읽거나 쓰고, 데이터를 점진적으로 처리할 수 있습니다.
다른 I/O 모델을 사용하는 외부 라이브러리나 플랫폼으로 작업하는 경우, 다음과의 상호 운용을 위해 일련의 어댑터들을 사용할 수 있습니다:
RawSource및RawSink와 같은kotlinx-io타입OutputStream과 같은 Java I/O 타입
이 페이지에서는 Ktor의 I/O 프리미티브(ByteReadChannel, ByteWriteChannel)와 이러한 외부 타입 간에 변환하는 방법을 설명합니다.
ByteReadChannel을 RawSource로 변환하기
ByteReadChannel을 RawSource로 변환하려면 .asSource() 확장 함수를 사용합니다:
client.prepareGet("https://httpbin.org/bytes/1024").execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.body()
val source: RawSource = channel.asSource()
val buffered = source.buffered()
val firstByte = buffered.readByte()
println("Read first byte from RawSource: $firstByte")
}ByteWriteChannel을 RawSink로 변환하기
일시 중단 가능한 ByteWriteChannel을 RawSink로 변환하려면 .asSink() 확장 함수를 사용합니다:
get("/sink") {
call.respondBytesWriter {
val sink: RawSink = this.asSink()
sink.buffered().use { buffered ->
buffered.writeString("Hello from kotlinx-io Sink!")
}
}
}이 어댑터로 생성된 RawSink는 데이터를 플러시(flush)할 때 내부적으로 runBlocking을 사용하므로, 플러시 작업이 호출 스레드를 차단(block)할 수 있습니다.
RawSink를 ByteWriteChannel로 변환하기
RawSink를 일시 중단 가능한 ByteWriteChannel로 래핑하려면 .asByteWriteChannel() 확장 함수를 사용합니다:
get("/raw-sink") {
val buffer = Buffer()
val channel = buffer.asByteWriteChannel()
channel.writeByte(42)
channel.writeFully("Hello via RawSink".toByteArray())
channel.flushAndClose()
call.respondBytes(buffer.readByteArray())
}이를 통해 일시 중단 함수에서 싱크(sink)로 비동기 쓰기가 가능해집니다. 반환된 채널은 버퍼링됩니다. 모든 데이터가 기록되었는지 확인하려면 .flush() 또는 .flushAndClose()를 사용하세요.
OutputStream을 ByteWriteChannel로 변환하기
Java OutputStream을 ByteWriteChannel로 변환하려면 .asByteWriteChannel() 확장 함수를 사용합니다:
get("/output-stream") {
val out = ByteArrayOutputStream()
val channel = out.asByteWriteChannel()
channel.writeFully("Hello from OutputStream-backed channel!".toByteArray())
channel.flushAndClose()
call.respondBytes(out.toByteArray())
}ByteWriteChannel에서의 모든 작업은 버퍼링됩니다. 기반이 되는 OutputStream은 ByteWriteChannel에서 .flush()가 호출될 때만 데이터를 수신합니다.
