2022. 2. 12. 20:55ㆍ프로젝트/Just Site
socket.io 튜토리얼 1편은 아래의 배너를 클릭하자.
연결 / 해제될 때 메시지 보내기
기본적으로 유저가 사이트에 접속하면 'connect',
탭을 닫거나 브라우저를 닫는 등의 경우에 'disconnect' 메시지가 온다.
그럼 이제 다음의 순서대로 작성을 해야겠다.
0. 유저가 연결 / 해제 된다 (자동. 개발 필요 x)
1. 서버에서 연결 / 해제 이벤트를 감지한다.
2. 서버에서 메시지를 클라이언트로 전송한다.
3. 클라이언트에서 메시지를 수신한다.
4. 클라이언트에서 받은 메시지를 표시한다.
1. 서버에서 연결 / 해제 이벤트를 감지한다.
2. 서버에서 메시지를 클라이언트로 전송한다.
index.js를 수정하자.
...
io.on('connection', (socket) => {
// 유저 연결 메시지
io.emit('announce', 'user connected')
socket.on('disconnect', () => {
// 유저 해제 메시지
io.emit('announce', 'user disconnected')
});
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
console.log('message: ' + msg);
});
});
...
다음과 같이
- io.on('connection')으로 유저의 연결을 감지한다.
- socket.on('disconnect')으로 유저의 연결 해제를 감지한다.
3. 클라이언트에서 메시지를 수신한다.
4. 클라이언트에서 받은 메시지를 표시한다.
index.html을 수정하자
...
socket.on('announce', function(msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
})
...
별 건 없고, announce 메시지에 대해
메시지와 같이 대화창에 추가할 수 있게 해줬다.
'...가 작성중입니다' 표시
우리는 input의 Change 이벤트를 받아서,
서버에 정보를 전송해 줄 것이다.
우선 ~가 작성중입니다를 표시할 공간을 만들어주자.
index.html의 <body> 부분을 수정해준다.
...
<body>
<div id="editing"></div>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
...
별 거 없고, editing이라는 id를 가진 <div>를 생성했다.
이제 입력 이벤트를 받아보자
index.html의 <script> 부분을 수정한다.
...
input.addEventListener('change', function(e) {
socket.emit('editing');
})
...
input의 change 이벤트가 실행되면,
서버에 'editing' 메시지를 보내게 했다.
이제 서버에서 'editing' 이벤트를 처리해보자.
index.js의 io.on('connection') 구절 안에 다음의 내용을 넣자.
...
socket.on('editing', () => {
io.emit('editing', `${socket.id} is editing`);
})
...
이제 다시 클라이언트에서 editing 메시지를 처리하자.
index.html의 <script> 부분을 수정하자.
...
var editingDiv = document.getElementById('editing');
socket.on('editing', function(msg) {
editingDiv.innerText = msg;
})
...
와! 샌즈!
온라인 상태의 유저 보여주기
왠지 현재 연결중인 유저들을 전부 조회할 수 있지 않을까 생각을 했다.
그런 기능을 안 만들어놨을리 없다.
Object.keys(io.sockets.sockets)
위의 방법으로 가져올 수 있다고 한다.
index.js의 io.on('connection') 구절을 수정하자.
...
let connected = [];
io.on('connection', (socket) => {
io.emit('announce', 'user connected');
connected.push(socket.id);
io.emit('online', connected);
socket.on('disconnect', () => {
io.emit('announce', 'user disconnected')
connected = connected.filter(id => id !== socket.id);
io.emit('online', connected);
});
...
이제 클라이언트에서 'online' 이벤트를 처리하자.
index.html를 다음과 같이 수정한다.
...
<body>
<!-- online div 생성 -->
<div id="online"></div>
<div id="editing"></div>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var form = document.getElementById('form');
var input = document.getElementById('input');
var editingDiv = document.getElementById('editing');
// online div 가져오기
var onlineDiv = document.getElementById('online');
// online 메시지 수정하기
socket.on('online', function(msg) {
onlineDiv.innerText = `online: ${msg.join(', ')}`;
})
....
닉네임 설정
각 소켓의 닉네임은 socket.data.username을 설정하면 된다.
index.js를 수정해보자.
...
socket.on('nickname', (msg) => {
socket.data.username = msg;
})
socket.on('chat message', (msg) => {
io.emit('chat message', { name: socket.data.username || socket.id, msg });
console.log('message: ' + msg);
});
...
'nickname' 이벤트가 들어오면 username을 바꿔주고,
채팅 메시지를 보내줄 때 name과 msg로 나눠서 보내주기로 했다.
index.html을 수정해보자.
...
<body>
<div id="online"></div>
<div id="editing"></div>
<ul id="messages"></ul>
<form id="nicknameForm" action="">
<input id="nicknameInput" autocomplete="off" /><button>Change</button>
</form>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
...
var nicknameForm = document.getElementById('nicknameForm');
var nicknameInput = document.getElementById('nicknameInput');
...
nicknameForm.addEventListener('submit', function(e) {
e.preventDefault();
if (nicknameInput.value) {
socket.emit('nickname', nicknameInput.value);
}
})
...
socket.on('chat message', function(msg) {
var item = document.createElement('li');
// 채팅 내용 바꿔주기
item.textContent = `${msg.name}: ${msg.msg}`;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
})
...
이런 식으로 이름이 정해졌다.
(song은 다른 탭에서 정한 이름)
이제 확실히 감도 잘 잡히긴 하는데
socket.io의 문서가 아주 불친절한 것 같다.
인덱스가 있는게 아니라 줄글 형식으로 되어있어서
원하는거 찾기가 쉽지가 않다. ㅠㅠ
'프로젝트 > Just Site' 카테고리의 다른 글
[Just Site] 10. node.js 로그 기록 (feat. winston) (0) | 2022.03.05 |
---|---|
[Just Site] 9. 살며시 내려오는 애니메이션 만들기 (CSS) (0) | 2022.02.20 |
[Just Site] 7. socket.io 공부 (1) - 튜토리얼 따라하기 (0) | 2022.02.12 |
[Just Site] 6. MYSQL과 서버 연결하기 (feat. Network) (0) | 2022.02.09 |
[Just Site] 5. React에서 node.js로 요청보내기 (0) | 2022.02.06 |