방프리

21.03.27 Nodejs Socket.IO를 이용한 Unity 통신 (연결편) 본문

Server&Network/Node.js

21.03.27 Nodejs Socket.IO를 이용한 Unity 통신 (연결편)

방프리 2021. 3. 27. 20:23

IOCP 등 소켓 통신을 공부하면서 웹 소켓 통신을 사용해보면 어떨까라는 호기심이 생겨 사용해보았다.

마침 회사에서 Nodejs를 사용해서 관련하여 공부할 겸 테스트를 해보기로 하였다.

일단 Nodejs를 세팅한 웹 서버의 정보는 다음과 같다.

운영체제 Ubuntu 18.04
Nodejs Nodejs 14.16.0
Socket.IO 4.0.0

npm의 경우에는 따로 업데이트하지 않고 그대로 사용했다. Socket.IO 버전 관련해서 조사해보니 꽤나 많은 버전업이

있었는데 이 주기가 너무 짧아 사용 전 자기 버전의 가이드 문서를 반드시 한 번 확인해볼 필요가 있다.

SocketIO 주소 : socket.io/

 

Socket.IO

SOCKET.IO 3.0 IS HERE ~/Projects/tweets/index.js const io = require('socket.io')(80); const cfg = require('./config.js

socket.io

Unity 클라이언트에서 SocketIO를 사용하는 방법이라고 검색하다보면 반드시 이 에셋을 보게되는데

현재는 지원이 중단되었다. 물론 에셋 스토어에도 내려가있으니... 사용할 방법이 없다.

다른 방법으로는 C#의 Nuget Package를 이용하여 SocketIO 패키지를 이용하는 방법과 다른 유료에셋을

구매하는 방법밖에 없다. (위의 에셋이 유일하게 무료인 에셋이였다.)

필자는 이 에셋을 사용했다. 리뷰평도 굉장히 좋고 피드백이 굉장히 빠르다. 

외국회사에 문의를 보내면 몇 일을 보고 기다려야 하는데 이 친구들은 거의 당일날 바로바로 처리해준다.

또한 어느정도 영어에 자신있다면 디스코드 서버도 있으니 참여해서 질문해도 된다.

일단 간단하게 Unity와 웹 소켓 서버가 통신하여 서로 로그가 남도록 해보자. 

const socketIO = require('socket.io')(5000);

console.log('Server Start : port 5000');

// on은 클라이언트에서 보낸 이벤트를 실행할 때 사용
socketIO.on('connection', function(socket) {
	console.log('Player Connected');
    
    // emit은 클라이언트에 이벤트를 보낼 때 사용
    socketIO.emit('PlayerConnected');
   
    socketIO.on('disconnect', function() {
        console.log('A Player disconnected');
    });
});

웹 소켓 로직은 그다지 복잡하지 않다. 참고로 'connection', 'disconnection'과 같은 문자열들은 예약어이기 때문에

이벤트 문자열 작성 전에 확인하는 것이 좋다.

처음에 웹 서버를 열고 Unity가 아닌 브라우저를 통해 접속 확인을 하였는데 이부분에서 꽤나 삽질을 많이 했다.

결론적으로 

  • 1. 웹 소켓과 브라우저는 다르다. 애초에 브라우저를 통한 테스트 자체가 잘못된 방식
  • 2. socket.listen() 함수는 불가능.... 꽤나 이전 블로그 등에서 require('socket.io').listen(port) 같은 코드가 보였는데 listen형태로 구축하는 것이 아님
  • 3. 웹 소켓 서버가 제대로 열였는지 확인하려면 telnet을 이용하자
  • 4. 3.0 버전부터 기본 url에 /socket.io/가 자동으로 붙는다. 자세한 내용은 다음 링크 참조 (socket.io/docs/v3/server-initialization/#path)

클라이언트 코드는 더 간단하다. 

using BestHTTP.SocketIO3;
using BestHttP.SocketIO3.Events;

public class SocketClient : MonoBehaviour
{
    [SerializeField] private string Address = "";
    private SocketManager socketManager = null;
    
    private void Start()
    {
    	SocketIO3Connect();
    }
    
    private void SocketIO3Connect()
    {
    	SocketOptions options = new SocketOptions();
        options.AutoConnect = false;

        socketManager = new SocketManager(new System.Uri(address), options);
        socketManager.Open();

        socketManager.Socket.On<ConnectResponse>(SocketIOEventTypes.Connect, OnConnected);
        socketManager.Socket.On("PlayerConnected", PlayerConnected);
    }
    
    private void OnConnected(ConnectResponse res)
    {
        Debug.Log("Connected! Socket.IO");
    }

    private void PlayerConnected()
    {
        Debug.Log("Player Connected!!");
    }
    
    private void Destory()
    {
        if (this.socketManager != null)
        {
            this.socketManager.Close();
            this.socketManager = null;
        }
    }
}

SocketOption을 통해 시작하자마자 바로 연결하는 설정을 끄고 Open()을 통해 소켓 연결을 하도록 한다.

socketManager.Socket.On 함수의 모습처럼 이벤트를 등록하고 소켓 서버와 통신하면서 해당 이벤트를 서로 실행하는 

방식으로 통신이 된다. 웹 서버는 소켓 통신의 하위에 속하므로 BestHTTP 에셋 내부를 확인해보면 

C#의 소켓통신이 사용됨을 확인할 수 있다.

서버 로그

클라이언트 로그

웹 소켓 서버가 워낙 쉬워서 비지니스 로직만 신경써도 괜찮아 편하다고 했는데 실제로 사용해보니 문법만 안다면

그다지 어려운 내용이 아니였다. 소켓 통신과 다르게 간단하게 몇 줄로 서버가 생성되고 연결되니 작업 속도는 

확실히 향상될 것 같다. 하지만 메모리 누수 이슈나 Socket.IO가 너무나 빨리 버전업이 된다는 문제점이 있긴하다.

다음에는 캐릭터의 이동이나 인터렉션을 구현해보아야겠다.

Comments