ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • socket.io (실시간 데이터 주고받기)
    Node.js,MongoDB 2022. 4. 27. 12:52

    실시간으로 소통할 때 SSE말고도 WebSocket을 쓰면 서버, 유저간 실시간 통신이 가능하다.

    Server Sent Event는 서버 -> 유저의 일방적 통신이라면,

    WebSocket는 양방향 통신이 가능하다.

     

    생js로 할 순 있는데, 라이브러리 사용이 편리하다.

    npm install socket.io

    먼저, socket.io를 설치해준다. 그리고,

    const http = require('http').createServer(app);
    const { Server } = require("socket.io");
    const io = new Server(http);

    셋팅을 해준다. 세줄은 const app = express(); 밑에 작성해야 한다.

    마지막으로,

    //app.listen(8080, function(){
    //        console.log('listening on 8080')
    //});
    //app대신 http로 교체
    http.listen(8080, function(){
            console.log('listening on 8080')
    });

    이제, WebSocket을 오픈할 수 있는데, 유저가 보는 html파일에도 socket.io를 셋팅해야한다.

    socket.ejs파일을 views폴더에 만들고, /socket에 접속하면 socket.ejs페이지를 보여주게 셋팅해보자.

    app.get('/socket', function(요청, 응답){
        응답.render('socket.ejs')
    })

    그리고, socket.ejs에도 socket.io를 설치해야 유저가 이용가능하다. ejs파일에

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.0/socket.io.js" integrity="sha512-/xb5+PNOA079FJkngKI2jvID5lyiqdHXaUUcfmzE0X0BdpkgzIWHC59LOG90a2jDcOyRsd1luOr24UCCAG8NNw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

    socket cdn을 적어주는데, 서버에 설치한 버전과 동일한 cdn을 붙여넣기 해야한다.

     

    이제 socket.ejs 파일에 script태그 안에 아래처럼 입력하면 접속할 수 있다. 위의 cdn보다 아래 작성해야한다.

    var socket = io();//유저가 WebSocket접속하는 법

    WebSocket접속 시 서버에서 뭔가 실행하고 싶으면,

    io.on('connection', function(){
        console.log('유저접속됨')
    })

    위의 코드를 적어주면 된다.

     

    이제 서버에게 웹소켓으로 실시간 메세지를 보내보자.

    <button id="send">서버에 메세지 보내기</button>

    서버에 메세지를 보내는 버튼을 하나 만들고,

    //실시간 메세지를 웹소켓에 보내기
    $('#send').click(function() {
    	socket.emit('user-send','안녕하세요')//socket.emit(작명, 메세지)
    })

    버튼을 클릭하면, socket.emit을 이용해 데이터를 보내준다. 

    그리고, server.js에서 서버가 수신하려면

    io.on('connection', function(socket){
        console.log('유저접속됨');
    
        socket.on('user-send', function(data){//누가 'user-send'이름으로 메세지 보내면 내부코드 실행
            console.log(data);
        })
    })

    이렇게 실행하는 코드의 함수에 socket 파라미터를 넣어 socket.on('작명한것', function(파라미터){}이렇게 적어주고 여기서 function함수 안에 들어간 파라미턴 안녕하세요 라는 받은 메세지를 뜻한다. 

    지금까진 유저가 서버에 메세지를 전송했다.

     

    이제, 서버가 유저에게 메세지를 보내보자.

    io.on('connection', function(socket){
        console.log('유저접속됨');
    
        socket.on('user-send', function(data){//누가 'user-send'이름으로 메세지 보내면 내부코드 실행
            console.log(data);
            //서버 -> 유저 메세지 전송
            io.emit('broadcast','반가워')
        }); 
    })

    이렇게, 유저가 서버한테 메세지를 보내면 안에서 io.emit('작명','보낼내용')으로 서버에서 유저한테 보낼 수 있다. 그리고

    유저도 메세지를 받으려면 socket.ejs에서

    socket.on('broadcast',function(data){
                console.log(data)
    })

    위 처럼 적어준다. 서버가 broadcast란 이름으로 데이터를 보낸걸 받는다는 뜻이다.

     

    여기서, io.emit()은 모든 유저에게 메세지를 보내준다. 이걸 전문용어로 broadcast한다라고 한다. 

    io.emit을 쓴 이유는 보통 채팅에서 한명이 안녕이라고 하면 여러명에게 뿌려주므로 사용한다.

    그래서 코드를

    socket.on('user-send', function(data){
            console.log(data);
            io.emit('broadcast',data);
    });

    이렇게 적으면, 유저가 메세지를 보내면 data파라미터에 담기고 io.emit으로 모두에게 그 메세지를 보내주세요가 된다.

     

    이제, console.log창이 아니라 div박스를 만들어서 서버에서 메세지를 받으면 div로 보여주게 코드를 짜보자.

    <div id="content"></div>
    socket.on('broadcast',function(data){
                $('#content').append('<div>'+data+'</div>')
    })

    socket.ejs에 이렇게 div를 만들고, 서버에서 보낸 메세지를 받아서 div박스에 append해주면 담기게 된다

     

    만약, 서버와 유저간 단독으로 소통을 하고싶으면 io.emit() 이 아니라 io.to(socket.id).emit() 이렇게 적으면 socket.id를 가진 사람에게만 메세지를 보내줄 수 있다. socket.id란 function의 socket파라미터에는 유저의 정보가 담기는데, 거기중에 id를 뜻한다. 즉, 접속한 사람마다 고유의 id가 생긴다.

     

    마지막으로, 채팅방을 만들어보자.

    서버에서 채팅방을 만들고 입장은 socket.join(방이름)이렇게 쓴다.

    io.on('connection', function(socket){
        console.log('유저접속됨');
    
        socket.join('room1')
        
        socket.on('user-send', function(data){//누가 'user-send'이름으로 메세지 보내면 내부코드 실행
            console.log(data);
            //서버 -> 유저 메세지 전송
            io.emit('broadcast',data);
        });
    })

    그리고 socket.ejs에서

    <button id="room1">채팅방1 입장</button>

    채팅방입장 버튼을 만들어주고,

    $('#room1').click(function(){
              //서버한테 room1에 입장시켜줘 이러고 보내면 되는데,
              //socket쓸 땐 GET/POST요청 대체가능
              socket.emit('joinroom','채팅방입장시켜줘')
    })

    room1을 클릭하면 socket.emit으로 joinroom이라는 이름으로 '채팅방입장시켜줘'란 메세지를 보내주면 된다.

    그리고

    socket.on('joinroom', function(data){
            socket.join('room1')
    })

    socket.on으로 joinroom이란 이름으로 보내주면 socket.join으로 room1에 입장시켜줘 라고 보내준다.

    <button id="room1-send">채팅방1에서 채팅하기</button>

    그리고, 채팅방1을 눌러서 입장하고, 채팅방1에서 채팅하기 버튼을 만들어서

    $('#room1-send').click(function(){
              socket.emit('room1-send','반가워 채팅방1 사람들아')
    })

    버튼을 누르면 socket.emit으로 room1-send경로로 '반가워 채팅방1 사람들아'라는 메세지를 보내주면 된다. 그리고 server.js 에서

    socket.on('room1-send', function(data){
            io.to('room1').emit('broadcast',data);
    });

    socket.on을 이용해 room1-send경로로 io.to('room1')로 room1에만 메세지를 보내주면 된다.

    그러면, 시크릿모드에선 안보이다가 채팅방1에 입장한 사람만 보이게 된다.

    댓글

Designed by Tistory.