WebSocket vs Socket.IO (안드로이드 예제 포함)

오리·2025년 1월 24일

Socket.io 사용?

  • Socket.IO 서버는 기본적으로 /socket.io/라는 경로에서 WebSocket 및 폴백 통신(HTTP Long Polling 등)을 처리
  • 클라이언트와 서버 간의 초기 연결(Handshake)을 수행하는 데 이 경로 사용
  • wss://helloWorld.com/socket.io 같은 URL을 사용
  • Socket.IO 서버는 기본적으로 /socket.io를 통해 클라이언트 요청을 처리하며, 이는 초기 Handshake 및 데이터 통신의 필수 경로로 설정되어 있음

⇒ URL 경로에 /socket.io가 포함되어 있는 것은 Socket.IO 서버에서 제공하는 기본 엔드포인트 패턴

접속해보기

클라이언트에서 Socket.IO 라이브러리로 접속

try {
    val socket = IO.socket("wss://helloWorld.com")
    socket.connect()
    socket.on(Socket.EVENT_CONNECT) {
        println("Connected!")
    }
    socket.on("custom_event") { args ->
        println("Received event: ${args[0]}")
    }
} catch (e: Exception) {
    println("Error: ${e.message}")
}

HTTP 요청으로 확인

  • Socket.IO는 클라이언트와 초기 Handshake를 수행할 때 HTTP 요청을 보냄
    • GET <https://helloWorld.com/socket.io/?EIO=4&transport=polling>
  • 응답이 JSON 형태로 오면 Socket.IO 서버
{
  "sid": "abc123",
  "upgrades": ["websocket"],
  "pingInterval": 25000,
  "pingTimeout": 60000
}

일반 WebSocket 클라이언트로 연결?

  • 시도시 초기 Handshake 단계에서 실패할 수 있음
  • Socket.IO는 WebSocket 외에 다른 프로토콜(HTTP Polling 등)을 혼합적으로 사용하기 때문

⇒ 즉, 서버가 Socket.IO 기반이라면, 반드시 Socket.IO 클라이언트를 사용하는 것이 올바른 방법!

단순 WebSocket과 Socket.IO

Socket.IO 비교 표

기능WebSocketSocket.IO
연결 방식WebSocket 전용WebSocket + 폴백(HTTP 등)
연결 끊김 처리수동 구현 필요자동 재연결 제공
이벤트 기반 통신미지원지원 (커스텀 이벤트 정의)
멀티플렉싱 (룸/네임스페이스)미지원지원

Socket.IO를 사용하면 좋은 상황

  1. 리얼타임 데이터가 필요한 애플리케이션 (채팅, 실시간 알림 시스템, 멀티플레이어 게임..)
  2. 다양한 네트워크 환경에서 안정적으로 연결을 유지해야 할 때
  3. 다양한 클라이언트 환경(모바일, 데스크톱, 브라우저)을 지원해야 할 때
  4. 복잡한 이벤트 기반 통신 로직이 필요한 경우

사용 예제

Kotlin

class WebSocketHandler(private val serverUrl: String) {
    private lateinit var mSocket: Socket

    fun connect(onMessage: (String) -> Unit) {
        try {
            // Socket.IO 옵션 설정
            val options = IO.Options().apply {
                reconnection = true
                reconnectionAttempts = 5
                reconnectionDelay = 2000
            }

            mSocket = IO.socket(serverUrl, options)

            // 연결 성공 이벤트
            mSocket.on(Socket.EVENT_CONNECT) {
                Timber.d("Connected to $serverUrl")
                mSocket.emit("===emitReceive", "OK")
            }

            // 연결 실패 이벤트
            mSocket.on(Socket.EVENT_CONNECT_ERROR) { args ->
                Timber.e("Connection Error: ${args.joinToString(", ")}")
            }

            // 연결 끊김 이벤트
            mSocket.on(Socket.EVENT_DISCONNECT) {
                Timber.w("Disconnected from $serverUrl")
            }

            // 서버에서 메시지 수신 처리
            mSocket.on("connected") { args ->
                onMessage(args.joinToString(", "))
            }

            mSocket.connect()
        } catch (e: Exception) {
            Timber.e("Exception during WebSocket connection: ${e.message}")
        }
    }

    fun disconnect() {
        if (::mSocket.isInitialized && mSocket.connected()) {
            mSocket.disconnect()
            Timber.d("Disconnected from $serverUrl")
        }
    }
}

0개의 댓글