socket.io 모듈을 사용해 통신 기본 설정하기

 

> 클라이언트 스크립트 파일 생성 후 로드시키기

 

src 하위에 js 폴더를 생성하고 그 안에 index.js 파일을 생성합니다.

폴더구조는 아래와 같습니다.

 

통신 스크립트를 추가하기 전에 앞서서 index.html에 관련 js 파일을 로드합니다.

// index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>chat-app</title>
</head>
<body>
    <div>welcome</div>

<script src="/socket.io/socket.io.js"></script>
<script src="/js/index.js"></script>
</body>
</html>

 

index.js는 생성했는데,

socket.io.js도 생성해야하나요? 라고 질문하신다면 아니라고 답하겠습니다.

socket.io.js는 서버 실행 시 자동으로 생성되기때문에 <script> 코드만 추가하면 됩니다.

 

 

> 클라이언트-서버 양방향 스크립트 추가하기

 

서버와 클라이언트가 통신하기위해서는 app.js(서버)-index.js(클라이언트) 모두 수정이 되어야합니다.

// app.js

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

app.use(express.static('src'));

app.get('/', function(req, res){
    fs.readFile('./src/index.html', (err, data) => {
        if(err) throw err;

        res.writeHead(200, {
            'Content-Type' : 'text/html'
        })
        .write(data)
        .end();
    });
});

io.sockets.on('connection', function(socket){ 

});

server.listen(8080, function(){
    console.log('서버 실행중...');
});

 

코드 설명

 

> socket.io 모듈을 불러와서 io 변수에 담고,

io.sockets.on에 connection 이벤트가 호출되면 실행될 함수를 바인딩해줍니다.

io.sockets은 나를 포함한 모든 소켓의 객체이며 'connection' 이벤트는 소켓이 연결되면 호출되는 이벤트입니다.

const io = require('socket.io')(server);
io.sockets.on('connection', function(socket){ 

});

 

 

 

> on 메서드를 통해 이벤트를 바인딩할 수 있으며 emit 메서드를 통해 이벤트를 호출할 수 있습니다.

on은 수신 emit은 발신으로 생각하면 쉽습니다.

io.sockets.on('connection', function(socket){  

});

 

 

> connection의 콜백함수를 보면 socket 인자가 전달되어 오는데, socket은 접속된 해당 소켓의 객체입니다.

소켓 연결 중에 어떠한 이벤트를 바인딩하고 싶다하면

connection의 콜백함수 스코프 내부에 이벤트리스너들을 작성하면 됩니다.

// index.js

'use strict';

var socket = io();

socket.on('connect', function(){
    console.log('connect');
});

 

>> socket.io 실행 후 해당 객체를 리턴받아 socket 변수에 담습니다.

var socket = io();

 

 

>> 담겨진 변수를 통해 connect 이벤트에 바인딩합니다.

connect 이벤트는 소켓이 연결되면 호출됩니다.

socket.on('connect', function(){
    console.log('connect');
});

 

 

> 사용자 입력을 받아 대화명 저장하기

 

// index.js

'use strict';

var socket = io();

socket.on('connect', function(){
    var name = prompt('대화명을 입력해주세요.', '');
    socket.emit('newUserConnect', name);
});

 

코드 설명

 

> prompt는 window 메소드로 사용자가 텍스트를 입력할 수 있는 대화상자를 띄웁니다.

대화명을 입력받은 후 name 변수에 담아줍니다.

var name = prompt('대화명을 입력해주세요.', '');

 

 

> 저장한 name값을 newUserConnect 이벤트를 호출하면서 파라미터로 전달해줍니다.

지금 emit하는 newUserConnect는 커스텀 이벤트로 다른 이름이어도 상관없습니다.

예를들어 newUserInit이어도 상관없습니다.

다만 app.js에서 이벤트 호출시 실행되는 on 함수를 추가할 것인데, 이때의 네임과 동일해야합니다.

socket.emit('newUserConnect', name);

connect, connection, disconnect 등... 정해진 기본이벤드들이 있습니다. 

기본이벤트를 제외하고는 커스텀이벤트를 사용하면 됩니다.

 

 

// app.js

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

app.use(express.static('src'));

app.get('/', function(req, res){
    fs.readFile('./src/index.html', (err, data) => {
        if(err) throw err;

        res.writeHead(200, {
            'Content-Type' : 'text/html'
        })
        .write(data)
        .end();
    });
});

io.sockets.on('connection', function(socket){
    socket.on('newUserConnect', function(name){
        socket.name = name;
    });
});

server.listen(8080, function(){
    console.log('서버 실행중...');
});

 

index.js(클라이언트)에서

newUserConnect라는 이벤트를 emit했고 app.js(서버)에서 이벤트를 처리하는 함수를 생성하겠습니다.

 

코드 설명

 

> newUSerConnect 이벤트 호출 시 name값을 파라미터로 전달했었는데, 기억하시나요?

그 파라미터가 function의 name값으로 전달되어왔고 socket.name에 저장해둡니다.

io.sockets.on('connection', function(socket){
    socket.on('newUserConnect', function(name){
        socket.name = name;
    });
});

 

테스트 : index.html에 대화명 삽입해보기

socket.name에 저장한값을 index.html에서 확인 할 수 있게 수정해보겠습니다.

// index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>chat-app</title>
</head>
<body>
    <div id="info"></div>

<script src="/socket.io/socket.io.js"></script>
<script src="/js/index.js"></script>
</body>
</html>

welcome 문구를 지우고 동적인 값을 넣기 위해 div 태그에 id값을 넣었습니다.

 

 

// app.js

io.sockets.on('connection', function(socket){
    socket.on('newUserConnect', function(name){
        socket.name = name;

        var message = name + '님이 접속했습니다';

        io.sockets.emit('updateMessage', {
            name : 'SERVER', 
            message : message
        });
    });
});

 

코드 설명 

 

> socket.name에 name값만 저장하던 부분에 메세지를 작성하여 message 변수에 담았습니다.

그다음

io.sockets.emit을 통해 updateMessage라는 이벤트를 호출하며 해당 데이터들을 객체리터럴로 전송합니다.

newUserConnect는 서버에서 전달하는 메세지이므로 name에는 서버라고 작성해줍니다.

socket.on('newUserConnect', function(name){
    socket.name = name;

    var message = name + '님이 접속했습니다';

    io.sockets.emit('updateMessage', {
        name : 'SERVER',
        message : message
    });
});

 

 

> updateMessage 이벤트 바인딩된 부분이 없으니 추가해야겠죠?

서버쪽에서 호출했으니 클라이언트쪽 js에서 수정하여 index.html에 노출하도록 하겠습니다.

// index.js

socket.on('updateMessage', function(data){
    var infoEl= document.getElementById('info');
    infoEl.innerHTML = data.message;
});

 

 

>> updateMessage를 호출했으니, 동일한 네이밍으로 바인딩합니다.

전달했던 data를 인자로 받아서 처리해줍니다.

socket.on('updateMessage', function(data){

 

 

>> index.html의 div 태그의 id값을 이용해서 객체를 가져와서 userName이라는 변수에 담고 

innserHTML을 이용해서 userName 영역에 data.message를 넣어줍니다.

var infoEl = document.getElementById('info');
infoEl.innerHTML = data.message;

 

서버를 종료했다가 다시 실행합니다.

// cmd

node app.js

 

웹에 접속하면 아래와 같이 입력창에 입력한 [대화명]님이 접속했습니다. 라는 텍스트가 나옵니다.

 

 

 

기능동작에 대한 이해가 어느정도 되었으니

(4)회차에서는 채팅기능을 구현하겠습니다. 

 

 

 

+ Recent posts