서버에서 클라이언트로 실시간 이벤트를 전달하는 단방향 통신 기술
https://github.com/square/okhttp/tree/master/okhttp-sse
Github에 따르면 아직 실험적으로 SSE를 제공하고 있기 때문에 정식 서비스에 이용하기는 어려울 것 같습니다
(캡스톤 디자인과 같은 단기성 프로젝트에는 유용할 것 같습니다)
implementation("com.squareup.okhttp3:okhttp-sse:$version")
implementation("com.launchdarkly:okhttp-eventsource:$version")
(이 포스트를 작성할 때는 okhttp-sse는 4.12.0, eventsource는 4.1.1 버전을 사용하였습니다)
// ServerClient
val okHttpClient = OkhttpClient().newBuilder().build()
// SSEClient
private val client = ServerClient.okHttpClient
fun startSse(eventSourceListener: EventSourceListener) {
val request = Request.Builder().url("$SSE-Address").build()
val factory = createFactory(client)
val eventSource = factory.newEventSource(request, eventSourceListener)
}
// viewModel
val eventSourceListener = object: EventSourceListener() {
override fun onOpen(eventSource: EventSource, response: Response) {
super.onOpen(eventSource, response)
}
override fun onEvent(
eventSource: EventSource,
id: String?,
type: String?,
data: String
) {
val jsonObject = JsonParser.parseString(data).asJsonObject
val dataObject = Gson().fromJson(jsonObject, DataObject::class.java)
super.onEvent(eventSource, id, type, data)
}
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
super.onFailure(eventSource, t, response)
}
override fun onClosed(eventSource: EventSource) {
sseClient.startSse(this)
super.onClosed(eventSource)
}
}
sseClient.startSse()
// Spring SSE Emitter
SseEmitter emitter = new SseEmitter();
emitter.send(event().id("1").name("update").data(myObject));
위의 Spring의 SSE-Emitter는 id, name, data를 설정할 수 있는데 OkHttp-SSE에서는 이를 onEvent에서 각각 id, type, data로 받게되며 모두 String(String?) 타입으로 주어집니다.
data는 JsonParser와 Gson Converter로 원하는 Object(Model)로 변환 가능합니다.
SSE에서 여러 Model의 데이터를 수신하는 경우에는 id or type으로 판별하면 될 것 같습니다.
마지막으로 Spring 서버에서 30초마다 Reconnect를 하게 되었을 때 연결이 끊기게(onClosed) 됩니다.
이 때 sseClient.startSse(this)를 해주어 연결이 종료되었을 때 client에서 sse를 다시 시작해주는 방식을 사용하였습니다.
만약 Auto-Reconnect가 있다면 알려주시면 감사하겠습니다