안드로이드/개발관련(Kotlin)

안드로이드에서 Nodejs와 socket.io를 사용해 소켓 통신하기

닉네임못짓는사람 2023. 2. 27. 20:07
반응형

이번 글에서는 안드로이드에서 Nodejs서버와 socket.io를 사용해 다른 클라이언트와

소켓 통신을 하는 법에 대해서 알아보자.

 

가장 먼저 해야 할 일은 gradle파일에 의존성을 추가해주는 것이다.

dependencies{
    implementation('io.socket:socket.io-client:1.0.0') {
        exclude group: 'org.json', module: 'json'
    }
}

 

 

의존성을 추가해줫으면 sync now를 눌러서 적용해준 뒤, Manifest로 이동하자.

서버와 통신하려면 INTERNET퍼미션이 추가하고, Nodejs로 테스트용 서버를 구동시킬 시

주소가 http가 되는데, 안드로이드에서는 http로 된 주소로의 접속을 기본적으로 막아두고 있기 때문에 이를 허용해주어야 한다.

<uses-permission android:name="android.permission.INTERNET" />
<application
	android:usesCleartextTraffic="true"
</application>

이렇게 사전 준비가 끝낫다면, 본격적으로 소켓 통신을 하기 위해 MainAcitivity로 이동해주자.

    lateinit var mSocket: Socket

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        try {
            mSocket = IO.socket("http://192.168.XXX.XXX:8080")
            mSocket.connect()
            Log.d("Connected", "OK")
        } catch (e: URISyntaxException) {
            Log.d("ERR", e.toString())
        }
        mSocket.on(Socket.EVENT_CONNECT, onConnect)
    }
    val onConnect = Emitter.Listener {
        mSocket.emit("emitReceive", "OK")
    }

소켓 통신을 위해서 먼저 Socket객체를 만들어주어야 한다.

mSocket이라는 이름의 변수를 하나 생성한 뒤, IO.socket을 사용해 객체를 생성해준다.

이때, argument로 IP주소와 포트번호를 전달해주어야 하는데, 같은 네트워크 안에서 실행할 경우 사설IP를,

외부 네트워크에서 실행하려는 경우 공인IP를 입력해주어야 한다.

 

또한 외부 네트워크에서 공인IP로 접속하려는 경우 포트 포워딩, 방화벽 해제 등 해주어야 할 작업이 많다.

이 글에서는 서버PC와 같은 네트워크에 있는 핸드폰(와이파이)를 사용해서 테스트해 볼 예정이기 때문에

사설 IP인 192.168.XXX.XXX를 입력해주도록 하자.

 

Socket객체를 생성했으면, connect를 사용해서 서버와 연결해주면 된다.

이제 잠시 Nodejs서버 쪽으로 넘어가도록 하자.

 

 

NodeJs서버로 소켓 통신을 하려면 socket.io모듈을 추가시켜주어야 한다.

npm install -s socket.io

명령 프롬프트에서 npm을 사용해 모듈을 추가시켜주도록 하자.

var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);

io.on('connection', (socket) => {
  console.log("user connect");

  socket.on('connectReceive', (data) => {
  	console.log(data)
  });

  socket.on('disconnect', function() {
  console.log('user disconnected');
  });
});

server.listen(8080, function(){
  console.log("server on 8080");
});

'모듈을 추가했으면 서버 코드를 작성해주는데, 연결 확인만 하기 위해서 최대한 간결하게 작성했다.

기본적으로 socket.io에서 사용되는 명령어는 두 가지라고 할 수 있다.

Method Description
.on 메세지를 받았을 때 동작 수행.
.emit 메세지를 전송하는 동작 수행

.on과 .emit이 있는데, on의 경우 메세지가 전송되기를 기다리는 리스너로, 메세지가 전송되면 정해진 동작을 수행한다.

emit의 경우는 반대로 연결된 클라이언트나 서버로 메세지를 전송해주는 역할을 한다.

 

위의 코드에서 io.on이라는 부분은 'connection'이라는 메세지가 오는 것을 기다리고 있다.

connection은 클라이언트가 서버에 연결되었을 때, 자동적으로 보내지는 메세지이다.

소켓 통신을 수행하려면 서버와 연결이 먼저 이루어져야 하기 때문에, 통신 시 수행하는 코드는 기본적으로 이 안에 작성한다.

 

다음으로, 코드를 자세히 보면 io.on과 socket.on이 있는 것을 볼 수 있는데, 여기서 io는 소켓에 연결된 클라이언트 전체를 의미한다.

그리고 socket은 현재 서버에 메세지를 전송한 클라이언트 하나, 즉 자기 자신을 의미한다.

예를 들어 아래와 같은 코드가 있다고 생각해보자.

io.emit('snedMsg', data)
socket.emit('sendMsg', data)

emit은 위에서 말했던 대로 메세지를 전송하는 명령어인데, io.emit의 경우 자신과 연결된 모든 클라이언트들에게 메세지를 전송한다.

반면, socekt.emit의 경우 socket은 자기 자신에게 메세지를 전송한다는 뜻이다.

 

서버 쪽 코드를 작성해봤으니 다시 클라이언트 쪽 코드로 돌아가 보도록 하자.

안드로이드에서도 on과 emit은 기본적으로 동일하게 작동한다.

class MainActivity : AppCompatActivity() {
    lateinit var mSocket: Socket

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        try {
            mSocket = IO.socket("http://192.168.XXX.XXX:8080")
            mSocket.connect()
            Log.d("Connected", "OK")
        } catch (e: URISyntaxException) {
            Log.d("ERR", e.toString())
        }
        mSocket.on(Socket.EVENT_CONNECT, onConnect)
    }
    val onConnect = Emitter.Listener {
        mSocket.emit("connectReceive", "OK")
    }
}

안드로이드에서 on으로 메세지를 받을 경우 Emitter.Listener를 사용해서 동작을 수행해주어야 한다.

위의 코드에서는 Socket.EVENT_CONNECT라는 메세지를 받을 경우 onConnect를 수행하게 되는데,

Socket.EVNET_CONNECT는 서버와 클라이언트와 연결되었을 때, 서버로부터 자동적으로 전송되는 메세지이다.

 

이렇게 서버와 클라이언트 코드를 모두 작성했으면, 서버를 실행시킨 뒤 실제로 잘 작동하는지 확인해보자.

앱을 실행시키면 서버와 연결이 되고, OK라는 메세지가 정상적으로 전송되어 console.log에 찍힌 걸 볼 수 있다.

그리고 어플을 종료하면 서버와 연결이 끊어지게 되어 disconnect가 찍힌 것을 볼 수 있다.

 

필자의 경우 npm을 사용해서 socket.io를 설치했을 때, 정상적으로 동작하질 않아서 2일 동안 해결법을 찾아다녔는데,

socket.io를 2.0.3버전으로 지정해서 설치해주었더니 정상적으로 동작했다.

혹시라도 안 되는 분들은 이 방법을 사용해보시길 바란다.

 

npm을 사용해서 버전을 지정해서 사용하는 방법은 아래와 같다.

npm install -s socket.io@2.0.3

 

retrofit을 사용해 nodejs 서버와 통신하는법!

https://devrunner96.tistory.com/6

반응형