OkHttp - WebSocket

HEETAE HEO·2023년 2월 22일
0
post-thumbnail

이번 글에서는 Android 앱에서 WebSocket 통신을 구현하는 방법에 대해서 작성해보려고 합니다.

WebSocket이란?

WebSocket은 웹 브라우저와 서버 간에 양방향 실시간 통신을 가능하게 하는 프로토콜입니다. 일반적인 Http 요청과 달리, WebSocket은 연결이 지속적으로 유지되어 서버와 클라이언트 간에 즉시 메시지를 전달할 수 있습니다. 이는 실시간 채팅, 게임, 주식 시세 애플리케이션 등에 사용되는 기술입니다.

우선 Android에서 WebSocket 통신을 하려고 한다면 OkHttp 라이브러리를 사용해야합니다. OkHttp 라이브러리를 사용하면 쉽게 웹소켓 통신을 구현할 수 있기 때문입니다.

간단 WebSocket 사용 설명

  1. 의존성 주입
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
}
  1. WebSocket 생성

WebSocket 연결을 시작하려면 OkHttpClient를 생성하고, 웹소켓 서버 URL을 사용하여 Request를 생성한 다음, WebSocketListener를 사용하여 웹소켓 이벤트를 처리합니다.

val request = Request.Builder()
    .url("wss://your-websocket-server-url")
    .build()

val listener = object : WebSocketListener() {
    override fun onOpen(webSocket: WebSocket, response: Response) {
        // 웹소켓 연결이 성공적으로 열림
    }
}

val client = OkHttpClient()
val websocket = client.newWebSocket(request, listener)
  1. WebSocket 메시지 전송 및 수신

WebSocket을 사용하여 메시지를 보내려면 send() 메서드를 사용하며, 메시지를 받으려면 WebSocketListener의 onMessage() 메서드를 재정의합니다.

// 메시지 전송
websocket.send("send Message")

// 메시지 수신 처리
override fun onMessage(webSocket: WebSocket, text: String) {
    // 웹소켓으로부터 문자열 메시지를 받음
}
  1. 연결 종료 및 재연결 처리

웹소켓 연결을 종료하려면 Close() 메서드를 호출하고, 정상적인 종료 코드와 종료 메시지를 전달할 수 있습니다.

// 웹소켓 연결을 종료
websocket.close(1000, "Goodbye, WebSocket!")

만약 WebSocketListener에서 연결 종료 이벤트를 처리하려면 onClosing() 또는 onClosed() 메서드를 재정의합니다.

val listener = object : WebSocketListener() {
    // ...
    override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
        // 연결이 종료되기 전에 호출됩니다.
        println("WebSocket is closing. Code: $code, Reason: $reason")
    }

    override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
        // 연결이 완전히 종료된 후에 호출됩니다.
        println("WebSocket closed. Code: $code, Reason: $reason")
    }
    // ...
}

재연결을 구현하려면, 연결이 종료되거나 실패할 때 새로운 연결을 생성하는 로직을 추가합니다. 예를 들어 onFailure() 또는 onClosed() 메서드에서 새로운 연결을 생성할 수 있습니다.

심화 WebSocket 사용 설명

OkHttp의 WebSocket 통신을 조금 더 효율적으로 사용하기 위한 방법을 작성해보려고 합니다.

1. 재사용 가능한 OkHttpClient 인스턴스 사용

OkHttpClient 인스턴스를 애플리케이션 전체에서 공유하는 싱글턴으로 사용하면, 연결 풀링 및 스레드 풀 관리 등의 이점을 얻을 수 있습니다.

// 코드 예시

object OkHttpClientSingleton {
    val instance: OkHttpClient = OkHttpClient.Builder()
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()
}

그리고 웹소켓 연결을 생성할 때 싱글턴을 사용하는 것입니다.

val client = OkHttpClientSingleton.instance

// Hilt를 사용한다면

@Module
@IntallIn(SingletonComponent::class)
object NetworkModule {
	
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient = 
    	OkHttpClient.Builder()
        	.readTimeOut(30, TimeUnit.SECONDS)
            .writeTimeOut(30, TimeUnit.SECONDS)
            .build()
}

Repository.kt

class NetWorkingRepository @Inject constructor(
	private val okHttpClient: OkHttpClient
) {
	// 클라이언트 사용 
}

2. 메시지 압축 사용

웹소켓에서 메시지 압축을 사용하면, 통신 효율을 높일 수 있습니다. OkHttp에서는 메시지 압축을 지원하기 때문에, 이를 활용하려면 OkHttpClient.Builder에서 다음과 같이 Interceptor를 넣어주면 됩니다.

val client = OkHttpClient.Builder()
    .addInterceptor(WebSocketCompressionInterceptor())
    .build()

3. 웹소켓 연결 유지

웹 소켓 연결이 끊기지 않도록 주기적으로 핑(ping) 메시지를 보내는 것이 좋습니다.

val client = OkHttpClient.Builder()
    .pingInterval(30, TimeUnit.SECONDS)
    .build()

4. 백그라운드에서의 연결 관리

애플리케이션이 백그라운드로 이동할 때, 웹소켓 연결을 닫거나 연결 상태를 관리하는 로직을 구현하세요. 이렇게 하면, 불필요한 연결이 존재하지 않으며, 자원을 효율적으로 사용할 수 있습니다.

5. 적절한 로깅 사용

OkHttp의 로깅 인터셉터를 사용하여 웹소켓 연결 및 메시지에 대한 디버깅 정보를 얻을 수 있습니다. 하지만, 로그 레벨을 적절히 설정하여 불필요한 로그가 기록되지 않도록 주의하세요.

마치며

다음과 같은 방식등을 통해 WebSocket 통신을 수행할 수 있습니다. 꼭 OkHttp3 라이브러리를 사용해야한 하는 것은 아닙니다. Scarlet 라이브러리를 사용하면 웹소켓 연결 관리 및 재연결 전략, 스레드 관리 등을 자동화하여 관리해주기 때문에 좀 더 효율적으로 웹소켓을 사용할 수 있습니다. 추후에 기회가 된다면 Scarlet 라이브러리에 대한 글을 작성해보도록 하겠습니다.

profile
Android 개발 잘하고 싶어요!!!

0개의 댓글