728x90

CentOS 6.6 에서 Node.js 환경을 구성하는 법은 http://link2me.tistory.com/1344 게시글 참조하면 된다.


웹소켓(Web Socket)은 웹 서버와 웹 브라우저 간의 양방향 통신을 위한 프로토콜이다.
웹 소켓은 클라이언트와 서버의 연결을 항상 유지한다.
연결이 유지된 상태에서 서버 혹은 클라이언트상의 event(이벤트)가 발생하면 event listener에 의해 서버에서 클라이언트로, 또은 클라이언트에서 서버로 데이터의 전달이 이루어진다.
Node.js에서 web socket를 사용하기 위해 socket.io package를 사용한다.

동영상 강좌 등을 보면 Express Generator  를 이용하여 앱 개발하는 방법에 대해 설명을 주로 하고 있다.

http, path, fs, url 등의 모듈은 Node.js에서 기본 제공하는 패키지였기 때문에 설치할 필요가 없지만 Express는 Node.js가 아닌 다른 개인이나 단체가 만든 패키지이기 때문에 npm(node package manager)에서 다운로드 받아야 한다.


먼저 리눅스 쉘 상에서 npm install express-generator -g 를 입력하여 express-generator 을 설치한다.


# npm install express-generator -g

# express -h // 설치 여부 및 도움말 확인

설치하고 싶은 디렉토리에서 다음을 입력하여 디렉토리를 생성한다.

# express www

# cd www && npm install  // 의존성 패키지 설치


이제 socket.io 모듈을 설치한다.

# cd /home/nodejs/www

# npm install socket.io --save

# npm install cors --save

# npm install jquery --save


를 하면 package.json 파일에 버전 정보가 추가된다.




기본적인 채팅 창 구현 예제는 https://www.tutorialbook.co.kr/entry/NodeJS-Express-%EC%99%80-Socketio-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%B1%84%ED%8C%85-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0?category=587311 사이트에 설명이 잘 되어 있어 참조했다.

단, 그대로 실행하면 에러가 발생한다. 버전 정보를 맞게 수정해줘야 한다.


routers/ 디렉토리에 chat.js 파일을 생성하고 아래 코드를 추가한다.

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
    res.render('chat', { title: 'chat function' }); // View 에 chat.jade 를 추가해야됨
});
module.exports = router; 


views 디렉토리에 chat.jade 파일을 생성하고 아래 코드를 추가한다.

extends layout
 
block content
    ul#messages
    form(action='')
      input#m(autocomplete='off')
      button Send
     
    style.
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { padding:0px; font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
 
       
    script(src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js')
    script(src='http://code.jquery.com/jquery-3.3.1.js')
    script.
       
      var socket = io();
       
      $('form').submit(function(){

        // socket.emit('서버로 보낼 이벤트명', 데이터);

        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
      });
     

      // socket.on('서버에서 받을 이벤트명', function(데이터)
      socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
      });
</li>


클라이언트는 socket.on과 socket.emit만 있으면 된다.

위에 색상 표시된 부분은 반드시 package.json 파일에 나온 버전 정보를 확인한 다음에 수정해줘야 정상 동작한다.

즉 설치된 npm 버전과 다르면 동작되지 않는다는 걸 명심하자.

https://cdnjs.com/libraries/socket.io 에서 소켓 관련 버전이 나온 URL를 확인할 수 있다.


 {
  "name": "www",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "^1.4.3",
    "cors": "^2.8.4",
    "debug": "~2.6.9",
    "ejs": "^2.6.1",
    "express": "~4.16.0",
    "express-session": "^1.15.6",
    "http-errors": "~1.6.2",
    "jade": "~1.11.0",
    "jquery": "^3.3.1",
    "morgan": "~1.9.0",
    "multer": "^1.3.1",
    "serve-favicon": "^2.5.0",
    "socket.io": "^2.1.1"
  }
}


app.js 파일 수정내용

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');
var chat = require('./routes/chat'); // 추가

var app = express();
var http = require('http').Server(app); // 추가
var io = require('socket.io')(http); // 추가

// view engine 설정
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade'); // ejs, jade

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.set( "ipaddr", "127.0.0.1" ); // 추가
app.set( "port", 3000 ); // 추가


/*** Routing ***/
app.use('/', routes);
app.use('/users', users);
app.use('/chat', chat); // 추가

http.listen(app.get('port'), function(){
    console.log("Express server listening on port " + app.get('port'));
}); // 추가

// socket.IO : Client 가 연결했을 때의 이벤트 처리
// io는 socket.io 패키지를 import한 변수
// socket은 커넥션이 성공했을 때 커넥션에 대한 정보를 담고 있는 변수
io.on('connection', function(socket){
    console.log('a user connected');
    socket.broadcast.emit('hi'); // 나를 제외한 모든 클라이언트에게 전송

    socket.on('disconnect', function(){
        // disconnect 이벤트는 클라이언트와의 연결이 끊어졌을 때 발생
        console.log('user disconnected');
    });

    socket.on('chat message', function(msg){
        console.log('message: ' + msg);
        io.sockets.emit('chat message', msg); // 나를 포함한 모든 클라이언트에게 전송
        // io.to(socket.id).emit('이벤트명' 데이터); // 특정인 한사람에게 메시지 전송
        // socket.join(방의 아이디); // 그룹에 들어가기
        // socket.leave(방의 아이디); // 그룹 떠나기
        // io.to(방의 아이디).emit('이벤트명', 데이터); // 그룹 전체 메시지 전송
        // socket.broadcast.to(방의 아이디).emit('이벤트명', 데이터); // 나를 제외한 그룹 전체 메시지 전송
        // 그룹의 목록과 그룹 안의 소켓들을 확인하는 방법
        // io.adapter.rooms
        // io.of(네임스페이스).adapter.rooms
        // socket.adapter.rooms
    });

});


// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;



이제 실행을 하면 될 것이다.

#node app.js


클라이언트에서는

http://xxx.com:3000/chat

이라고 입력하면 입력할 수 있는 화면 창이 뜰 것이다.


웹 화면에서 데이터를 입력하면 접속된 모든 사용자에게 메시지가 전달되므로 본인 화면도 같이 업데이트되어 보이는 걸 확인할 수 있다.


리눅스 서버 상에서 확인하는 메시지 창

으로 user 가 접속된 걸 확인할 수 있다.

하지만 어떤 user가 접속했는지 여부는 알 수 없다.


어떤 user 가 접속했는지 여부를 알 수 있도록 하려면 회원정보와 연동시켜야 한다.

블로그 이미지

Link2Me

,