상세 컨텐츠

본문 제목

[node.js] 실시간 멀티채팅 구현하기!

프로그래밍/서버관련

by 진:D 2014.05.18 17:55

본문







웹에서 실시간처리

학부생활중 실시간처리 관련으로 TCP/IP를 배우면서 TCP/IP를 이용한 1:1 채팅을 구현해보셨을것이라 생각합니다. 하지만 실무에서는 전~~~~혀 쓸모가 없는 것 같습니다;; 수업중 책에 나와있는 소스대로 따라한다면 1:1채팅은 잘 되지만 멀티채팅구현은 머리를 굴리고 굴려야 간신히 구현할 수 있을 겁니다. 그러나 역시 실제서비스에 적용은 무리라고 생각됩니다.

그럼, 쉽게 프로그래밍을 짜면서 실제서비스에서 적용할 수 있는 방법이 무엇이 있을까요?

멀티채팅관련으로 알아보면서 괜찮은 것을 하나 찾았습니다 : )

요즘 젊은층(?)에서 많이 사용하고 있는 node.js + socket.io 입니다. 이걸 언어라고 설명을 해야할지 프레임워크라고 설명을 해야할지 애매합니다. node.js자체가 javascript를 기반으로 만들어진것으로 알고있습니다.

Wiki(node.js위키링크)를 참고하면 Node.js는 확장성 있는 네트워크 어플리케이션(특히 Server-side) 개발에 사용되는 소프트웨어 플랫폼이라고 정의되어 있습니다.

음. 저는 일단 프레임워크로 구분하겠습니다. 서버프로그램구현에 있어서 javascript언어를 이용하면서 특화되었다고 생각하시면 될 것 같습니다.

저는 javascript언어가 그렇게 익숙치않아서 가끔씩 문법을 확인하면서 작성하는데 언어가 익숙하신 분들은 정말 쉽게 작성하면서 놀랠 것 같네요. 후후

node.js + socket.io

node.js + socket.io? 이게 무엇일가요?

일단 node.js는 서버프로그램이라는 것은 알겠지만 socket.io 확장자부터 참 이상합니다. 간단하게 설명드리면 소켓통신을 쉽게 구현할 수 있도록 도와주는 아이라고 말씀드릴 수 있습니다.

node.jssocket.io가 만나면 아까 위에서 힘들게 구현하던 멀티채팅을 순식간에 짧고 굵게 구현할 수 있습니다!

성능이 의심스러우신가요? 저는 테스트해보지 않았지만 다른분들께서 테스트한 내용들을 보게되면 실.시.간 접속 몇천명까지는 무리없이 처리해준다고 합니다! 엄청큰 서비스를 하지않는다면 몇천명이 정확하게 동시에 접속할일이 많을까요? 제 개인적으로는 그런걱정을 하고있다면, 그 서비스는 이미 성공했기 때문에 능력있는 개발자를 자신있게 영입하면 됩니다 :D 하하하하하하

이렇게 말만 주저리주저리해봤자 머리만 더 복잡해질 것 같네요. 직접 실습을 통해서 얼마나 위대한지 같이 확인해도록 합시다 : )

채팅 Server

node.js - node.js 링크

socket.io - Socket.IO 링크

본격적인 적용을 위해 위에 있는 두 웹사이트를 들어가서 설치를 해주세요. node.js를 설치하신 뒤 socket.io를 준비해주시면 됩니다 : )

기본적인 SOCKET통신을 활용하는 방법이 socket.io 웹사이트에 설명되어 있네요.

/* Server Source */
var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
/* Client Source */
<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

이렇게 서버쪽과 클라이언트에 위 예제소스를 적용하시면 실시간으로 통신할 수 있는 페이지가 완성됩니다 : ) 하지만 “위에 있는 소스가지고 채팅을 어떻게 만들어?” 하시는 분이 있을지도 모르겠습니다.

/* 실제 적용한 Server Source */
var io = require('socket.io').listen(50000);

io.sockets.on('connection', function(socket) {
    socket.emit('connection', {
        type : 'connected'
    });

    socket.on('connection', function(data) {
        if(data.type == 'join') {

            socket.join(data.room);

            socket.set('room', data.room);

            socket.emit('system', {
                message : '채팅방에 오신 것을 환영합니다.'
            });

            socket.broadcast.to(data.room).emit('system', {
                message : data.name + '님이 접속하셨습니다.'
            });
        }
    });

    socket.on('user', function(data) {
        socket.get('room', function(error, room) {
            socket.broadcast.to(room).emit('message', data);
        });
    });

});

위에는 제가 이것저것 수집하면서 제대로 작동하도록 만들어본 서버소스입니다 : )

각 사용자들이 원하는 채팅방에 접속하여 서로 실시간으로 채팅할 수 있도록 지원해주는 서버입니다.

socket.io에 의해서 사용자가 해당방에 접속하여 글작성시 서버는 같은방에 있는 타접속자에게 해당메세지를 브로드캐스트해주는 역할을 합니다.

만약 대화한 내용들을 저장하고 싶다면 데이터가 넘어오는 시점에서 원하는 DBConnection하여 기록하면 됩니다 : ) 저는 여기서 요즘 유행한다는 MongoDB(몽고DB)를 이용해보았고, 실험결과! 만족스러웠습니다.

그럼 다음은 Client에서는 어떻게 같은 방에 접속하며, 메세지를 주고받을 수 있는지 살펴보도록 하겠습니다!

채팅 Client

바로 위에서 아주아주아주 간단하게 Client소스를 보셨지만, 감이 잘 안오실 것 같네요. 그래서 나름 샘플소스를 준비해보았습니다. 아주 기본적으로 대화할 수 있도록 만들어보았습니다 : )

참고하셔서 클라이언트와 서버 모두 직접 구현해보아요 : )

<!DOCTYPE html>
<html>
    <head>
    <style>
        .footer {
                width: 100%;
                height: 50px;
                position: fixed;
                bottom: 0;
            }
    </style>
    </head>
    <body>
        <div class='j-message'>
        </div>
        <div class='j-footer'>
            <table>
                <tr>
                    <td width='100%'>
                        <input id='message-input' type='text'>
                    </td>
                    <td width='20%'>
                        <button id='message-button' type='submit'> 전송 </button>
                    </td>
                </tr>
            </table>
        </div>

        <script type="text/javascript" src="http://chat.socket.io/socket.io/socket.io.js"></script>
        <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
        <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>

        <script>
            var serverURL = 'localhost:50000';

            var name = 'jin';
            var room = '100';

            $(document).ready(function() {
                var socket = io.connect(serverURL);

                socket.on('connection', function(data) {
                    if(data.type == 'connected') {
                        socket.emit('connection', {
                            type : 'join',
                            name : name,
                            room : 100
                        });
                    }
                });

                socket.on('system', function(data) {
                    writeMessage('system', 'system', data.message);
                });

                socket.on('message', function(data) {
                    writeMessage('other', data.name, data.message);
                });

                $('#message-button').click(function() {
                    var msg = $('#message-input').val();

                    socket.emit('user', {
                        name : name,
                        message : msg
                    });

                    writeMessage('me', name, msg);
                });

                function writeMessage(type, name, message) {
                    var html = '<div>{MESSAGE}</div>';

                    var printName = '';
                    if(type == 'me') {
                        printName = name + ' : ';
                    }

                    html = html.replace('{MESSAGE}', printName + message);

                    $(html).appendTo('.j-message');
                }
            });
        </script>
    </body>
</html>

음… 졸면서 클라이언트 소스를 작성하기는 했는데, 잘 돌아가는지 테스트는 못해봤네요 ㅠㅠ 참고하시면서 작성하시면 잘될겁니다 : )

멀티채팅. 어려울 것 같았지만 저희는 너무나도 좋은 세상에 살고 있습니다.

대부분 라이브러리, 프레임워크 형태로 구현되어 있고, 잘 가져다가 사용하면 됩니다. 과거였다면 으~~~ 생각만해도 끔찍합니다.

하지만 저희는 이렇게 편리하게 구현되어있는 것들을 가지고 엄청난것을 만들어야 합니다.

카카오톡, 라인, 와츠앱을 넘어 더 좋은 채팅을 많이 많이 개발해보아요 : )

지금까지 읽어주셔서 감사합니다.

위에 기술한 내용은 조만간 잘 정리하여 GitHub에 오픈소스로 공개할 예정입니다.

등록하면 이곳에 주소 적어놓겠습니다. 감사합니다.


Github에 등록하였습니다 : https://github.com/devjin0617/nodejs-socket.io-chat-example


관련글 더보기

댓글 영역

  • 이전 댓글 더보기
  • 프로필 사진
    2017.06.04 01:25
    아 잘 연결되고 실행했습니다. 한가지 궁금한게 있는데 제가 쓴 글은 앞에 이름이 붙는데 상대방이 쓴 글은 앞에 이름이 안붙네요 ㅠㅠㅠㅠ 이것저것 건드려봤습니다만 해결이 안되서... 도움받을 수 있을까요 ㅠㅠㅠㅠ
    • 프로필 사진
      2017.06.09 17:37 신고
      진행하고 있는 프로젝트를 공유받아볼 수 있을까요? 텍스트로 설명드리기에는 양이 방대할 것 같습니다 T_T
  • 프로필 사진
    2017.06.09 18:35
    고마워용~ㅎ 많은 도움 얻고갑니다
  • 프로필 사진
    2017.09.12 10:17
    안녕하세요.
    정말 훌륭한 예제에 배우고 갑니다.

    (되는군요... 이상하네
    혹 저와 같은 문제를 겪으실 분이 계실듯 하여 남겨둡니당)
    -----------------------------------


    그런데... 서버쪽js에서 시스템 메세지는 한글로 보내면 깨지길래
    socket.broadcast.to(data.room).emit('system', {
    message : `${data.name} is 연결`
    });

    모든 js,html을 utf-8로 만들어봐도 동일하더라고요

    res.writeHead(200, {'Content-Type':'text/html;charset=UTF-8','Content-Length':data.length});
    이렇게 캐릭터셋도 utf-8로도 줘봐도 동일하고요... 서버를 재실행해도 마찬가지라서요...
    혹시 방법이 있을까요?
  • 프로필 사진
    2017.09.19 22:50
    깃홈이랑 연동해서 사용중인데 지금 별이상한 파일들이 클라우드9에서 보이네요...
    그래서 진행이안되고있습니다... 대체 뭐가 뭔지 ..
    • 프로필 사진
      2017.09.19 22:51 신고
      어떠부분에서 어려움을 겪는지 적어주시면 제가 아는 선에서 도움을 드려보도록 하겠습니다 : )
  • 프로필 사진
    2017.10.10 04:31
    정말 많이 참고가 되었습니다.! 감사합니다.
    이런 자료를 2014년에 쓰셧다는게 정말 놀랍기 그지 없네요 ㅎㅎ
    • 프로필 사진
      2017.11.06 11:39 신고
      도움이 되셨다니, 감사합니다.

      혹시 궁금한 점 있으시면 메일 or github 이슈에 남겨주시면 제가 도움 드릴 수 있는 부분 도와드리도록 하겠습니다 : )

  • 프로필 사진
    2017.11.21 10:22
    저는 윈도우 서버입니다. node.js 가 서버에도 설치가 되어 있어야 하는지 궁금합니다
    • 프로필 사진
      2017.11.21 10:28 신고
      네. 서버에도 node.js가 설치되어 있어야합니다. 그래서 node.js 코드를 실행할 수가 있습니다.
      node.js는 여기에서 편하신거 윈도우용으로 다운로드받아서 설치하시면 됩니다 : )
      https://nodejs.org/ko/
  • 프로필 사진
    2017.11.21 11:38
    많은 도움이 되었습니다. 좋은 글 감사합니다
  • 프로필 사진
    2017.11.25 14:35
    github 소스로 한방에 성공했습니다. 고맙습니다.
    응용해서 1:1 대화방을 여러개 생성할 수 있는지도 궁금합니다.
  • 프로필 사진
    2018.02.03 09:23
    이거 보구 제가만든거에 적용해보려고 하는데 Uncaught ReferenceError: require is not defined라고 뜨는더 어찌해야하나요...ㅜㅜ
    • 프로필 사진
      2018.05.28 13:50 신고
      어디부분에서 require is not defined 가 나오는지 알려주시면 도움드리기 좋을 것 같습니다!
  • 프로필 사진
    2018.08.05 23:50
    와 덕분에 제가 원하는걸 만들수 있었습니다!
    감사합니다!!
    • 프로필 사진
      2018.08.06 21:47 신고
      부족한 내용이였는데, 원하는 걸 만드셨다니 저도 기분이 좋네요 : )
  • 프로필 사진
    2018.11.26 17:23
    좋은소스 감사합니다 ^^ 혹시 중간에 mongoDB로 대화내용 저장을 하셨다고 하셨는대 혹시 참고할만한 소스같은것 있으신가요?? 대화내용을 어찌 저장하고 불러와야할지 감이 잡히지 않아서요 ㅠㅠ
    • 프로필 사진
      2018.11.26 18:05 신고
      대화내용의 경우 대화방별로 대화들을 쌓아놓고, 불러오는 경우는 따로 API서버를 만들어서 가져오는 식으로 하시면 될 것 같습니다!
      socket.io로 대화목록을 처리한다기보다는 실시간으로 사용자들에게 전달해주고, 알림을 준다는 의미로 보시면 될 것 같습니다!
      채팅구현의 경우는 각자 스타일마다 구현하는 방식이 다르다보니, 어떤 것을 참고하기 보다는 먼저 시행착오를 경험해보고, 이와 비슷한 유형을 어떻게 해결했는지를 찾아보는 것을 추천드립니다 : )
  • 프로필 사진
    2018.12.11 11:48

    웹 브라우저 콘솔에 -? net::ERR_CONNECTION_REFUSED 라는 에러가 뜹니다. 이것때문인지 휴대폰으로 하나더 키고 했을때 서로 메세지를 주고받을 수 없네요 ㅜ 도와주세요 ㅠㅠ
  • 프로필 사진
    2018.12.11 13:38
    채팅서버는 어떻게 키나요..
    localhost:8000 만 켰거든요~ 다른것도 켜야되는게 있나요?
  • 프로필 사진
    2018.12.11 13:46
    혹시 index.js 도 가동 시켜야 하는건가요? 이거 pm2로 가동해봤는데 서버에 안올라가던데요.. ㅠㅠ
    • 프로필 사진
      2018.12.11 13:55 신고
      https://github.com/devjin0617/nodejs-socket.io-chat-example

      해당 코드 받으셔서 소켓서버와 웹서버를 실행해주시면 될 거예요!
      아마 해당 오류가 발생한 것은 웹서버가 가동하고 소켓서버는 안돌아갔기 때문에 화면은 표기되지만 CONNECTION오류가 발생한 것으로 보입니다 : )
  • 프로필 사진
    2018.12.11 14:07
    아 감사합니다 ㅠㅠ 해결했어요 근데 가상머신 하나 틀어놓고 똑같은주소 들어가서 채팅하니깐 안되더라구요.. 소켓서버는 그 가상머신에서 NODE.JS 로 똑같이 돌려야 주고 받을 수 있는 거겠죠??
    • 프로필 사진
      2018.12.11 14:13 신고
      가상머신으로 띄워서 하시면 HTML페이지에서 소켓버서 연결하는 주소도 가상머신의 IP주소로 변경하셔야 동작할거예요 : )
  • 프로필 사진
    2018.12.21 15:52
    1. 우분투상에서 작업중입니다. 터미널에서 npm run socket을 할시에 다른 명령어를 입력못하는데 npm run web을 입력하려면 터미널을 두개 켜놓고 하면되는건가요?
    2. 현재 그대로 복붙해서 테스트중인데 자신이 입력할때는 'jin: 메세지내용' 같이 잘 뜨나 상대가 입력한 메세지는 jin: 이없이 메세지 내용만 뜹니다. 이것을 어떻게 해결할 수 있을까요?
    • 프로필 사진
      2018.12.21 16:25 신고
      네 터미널 두개 키고, 소켓서버와 웹서버를 둘다 돌리셔야 할거예요!
      메시지가 정상적으로 표기 안되는데 서버 2개가 안돌아가서 나오는 현상으로 보여집니다!
    • 프로필 사진
      2018.12.21 16:40
      ㅠㅠ 터미널 둘다 켜서 진행해봐도 똑같네요..
      왜 메세지만 뜨고 보낸사람은 뜨지않을까요 혹시 제가 분석해볼 부분이 다른곳인건가요?
    • 프로필 사진
      2018.12.21 16:42 신고
      따로 오류메시지 같은것도 없나요??
    • 프로필 사진
      2018.12.21 16:43
      제가 현재 원래는 웹서버를 아파치로 사용하고 있었는데 아파치용 localhost로 입장했습니다. 그거 때문에 그런걸까요?

      혹시 아파치를 이용한다면 어떤 부분을 수정하면좋을까요?
    • 프로필 사진
      2018.12.21 16:48 신고
      웹서버를 노드 자체에서 돌려주기 때문에 크게 상관은 없을 것 같은데...
      코드를 깃헙같은 곳에 올려주시거나 어디까지 성공이 되었고, 실패했는지를 알아야 자세하게 말씀드릴 수 있을 것 같습니다 ㅠㅠ
  • 프로필 사진
    2018.12.21 16:22
    1번질문추가
    npm run socket만해도 작동이 되긴합니다. 2번질문같은 현상이있긴하지만요
    • 프로필 사진
      2019.02.05 11:49 신고
      소켓서버만 열게되면 화면새로고침했을때 동작안할 수도 인씁니다!
      그래서 웹서버와 소켓서버를 동시에 운영해야할거예용!
  • 프로필 사진
    2019.02.04 12:36
    https://heroku-blog-files.s3.amazonaws.com/posts/1473343749-1407359339-button-step-1.png
    깃허브소스에 위 참조 이미지 처럼요~~
    deploy to heroku 버튼 좀 부탁드립니다~~
    왜냐하면..헤로쿠는 미국에서도 젤 많이쓰는 클라우드일뿐더러 무료구요~~

    heroku로 데모도 올리실수 있데요~~~~~
    • 프로필 사진
      2019.02.05 11:51 신고
      제 개인적인 프로젝트에는 헤로쿠를 쓰기는 하는데 여기에 적용해볼 생각은 못해봤네용!
      말씀해주신대로 준비해보도록 하겠습니다!
      조언 감사드립니다
  • 프로필 사진
    2019.07.24 15:10
    비밀댓글입니다
    • 프로필 사진
      2019.08.05 11:18 신고
      앗 PHP로 진행을 하셨군요!
      PHP로 API를 만드시고, 웹 채팅에서는 ajax등으로 API를 요청하는 식으로 채팅 데이터를 전송시켜주면서 PHP쪽에서 디비에 기록하시면 될 것 같아요.
      실제로 socket.io 를 통한 웹소켓으로 새로운 채팅이 왔다정도의 알림용도로만 사용하시고 웹소켓 데이터를 받았을 때 PHP쪽 서버에 API를 요청해서 채팅대화목록을 갱신하는 방식으로 진행하시면 될 것 같습니다.

      일단 설명을 전체적으로 해드리기는 했는데, 진행하시면서 궁금한 점이 있으시면 댓글이나 이메일로 답변주시면 답변을 드리도록 하겠습니다.
      감사합니다 : )
  • 프로필 사진
    2019.10.14 21:11
    공부하는데 도움이되는 자료를 올려주셔서 감사합니다.
    깃헙에서 파일을 다운받은뒤로 무엇을해야할지 잘 모르겠습니다.

    혹시 무엇을 해야하는지, 참고할 자료는 무엇인지, 어떤것을 공부해야할지 말씀해주실수있나요?

    저는 가상머신에서 우분투 운영체제를 사용해 두개의 파이어폭스창을 켠뒤에 두 사람이 실시간으로 체팅하는 상황을 구현하고싶습니다.
    • 프로필 사진
      2019.10.15 11:41 신고
      안녕하세요! 제가 올려드린 소스코드는 샘플코드라서 바로 사용하기는 힘들거예요.
      node.js socket.io 기본적인 웹지식이 있으시면 어느정도 도움이 되실거예요 : )