이번 포스트에서는 코틀린 웹 서버에서 웹 소켓과 스트리밍을 구현하는 방법에 대해 알아보겠습니다.
1. 웹 소켓 구현하기
1.1. Gradle 설정
먼저, 프로젝트의 build.gradle
파일에 아래의 의존성을 추가해야 합니다.
dependencies {
implementation 'io.ktor:ktor-websockets:<version>'
}
<version>
을 사용하고자 하는 Ktor 버전으로 바꿔주시면 됩니다.
1.2. 웹 소켓 핸들러 작성
다음으로, 웹 소켓 핸들러를 작성해야 합니다. 새로운 WebSocketHandler
클래스를 생성하고, 아래의 코드를 추가해주세요.
import io.ktor.routing.*
import io.ktor.websocket.*
import io.ktor.http.cio.websocket.*
import kotlinx.coroutines.channels.*
fun Application.module() {
install(WebSockets)
routing {
webSocket("/websocket") {
val incoming = produce<Message> {
try {
for (frame in incoming) {
when (frame) {
is Frame.Text -> {
val message = frame.readText()
send(Message("$connection incoming: $message"))
}
}
}
} finally {
send(Message("$connection closed"))
}
}
outgoing.send(Frame.Text("Connected: $connection"))
for (message in incoming) {
outgoing.send(Frame.Text("Server: $message"))
}
}
}
}
위의 코드는 /websocket
경로로 접근한 클라이언트와의 웹 소켓 통신을 처리합니다. 클라이언트로부터 메시지를 받아서 서버의 콘솔에 출력하고, 서버에서 전달한 메시지를 클라이언트에게 다시 보내는 동작을 합니다.
1.3. 서버 실행
이제, 웹 서버를 실행하고 /websocket
에 접속해서 메시지를 주고받아볼 수 있습니다.
2. 스트리밍 구현하기
2.1. Gradle 설정
스트리밍을 구현하기 위해서는 추가적인 의존성이 필요합니다. build.gradle
파일에 아래의 의존성을 추가해주세요.
dependencies {
implementation 'io.ktor:ktor-server-netty:<version>'
implementation 'io.ktor:ktor-serialization:<version>'
implementation 'io.ktor:ktor-client-cio:<version>'
}
2.2. 스트리밍 핸들러 작성
다음으로, 스트리밍 핸들러를 작성해야 합니다. 새로운 StreamingHandler
클래스를 생성하고, 아래의 코드를 추가해주세요.
import io.ktor.http.cio.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*
import java.util.*
import kotlin.collections.HashMap
import kotlin.coroutines.CoroutineContext
class StreamingHandler(
private val context: CoroutineContext
) : WebSocketHandler {
private val connections = HashMap<WebSocketSession, List<OutputStream>>()
override suspend fun onConnect(session: WebSocketSession) {
super.onConnect(session)
connections[session] = ArrayList()
}
override suspend fun onFrame(session: WebSocketSession, frame: Frame) {
when (frame) {
is Frame.Text -> {
val message = frame.readText()
sessions().send(Frame.Text(message))
}
is Frame.Binary -> {
val outputStreams = connections[session]
outputStreams?.forEach { outputStream ->
withContext(Dispatchers.IO) {
outputStream.write(frame.data.array())
outputStream.flush()
}
}
}
}
}
override suspend fun onClose(session: WebSocketSession, code: CloseReason.Codes, reason: String?) {
super.onClose(session, code, reason)
connections.remove(session)
}
}
위의 코드는 클라이언트로부터 받은 바이너리 데이터를 클라이언트에게 전달하는 스트리밍 핸들러입니다. onFrame
함수에서 클라이언트로부터 받은 데이터를 연결된 모든 OutputStream
에 전달하고 있습니다.
2.3. 서버 실행
스트리밍을 구현한 웹 서버를 실행하고 클라이언트와 연결하여 데이터를 주고받습니다.
마치며
이번에는 코틀린 웹 서버에서 웹 소켓과 스트리밍을 구현하는 방법에 대해 알아보았습니다. 웹 소켓을 사용하면 실시간으로 데이터를 주고받을 수 있고, 스트리밍을 구현하면 바이너리 데이터를 실시간으로 전송할 수 있습니다. 이러한 기능들을 이용하여 다양한 웹 애플리케이션을 구현해보세요.
참고 자료:
- Ktor documentation: https://ktor.io/
- Kotlin official website: https://kotlinlang.org/