오늘은 11월 18일 18일차이다.
저번에 짰던 웹소켓 실시간 통신 절차를 좀 고쳤다. solver가 단어를 입력하면 POST /solve/:maker/add 요청을 서버에 보내 입력한 단어를 데이터베이스에 등록하게 되는데, 이때 등록 후 solvers 리스트를 데이터베이스에서 뽑아내 바로 socket.io로 보낸다. 그러면 load 페이지에서는 이벤트 리스너가 대기하고 있다가 데이터를 받는 순간 solvers 상태를 업데이트하고, 렌더링해줌으로써 실시간으로 확인할 수 있도록 하였다.
const { Server } = require('socket.io');
module.exports = (server, app) => {
const io = new Server(server, {
cors: {
origin: 'http://localhost:3000'
}
});
app.set('io', io);
const loader = io.of('/loader');
loader.on('connection', (socket) => {
console.log('loader 네임스페이스 접속');
const maker = socket.handshake.query.maker;
console.log(maker);
socket.join(maker);
socket.on('disconnect', () => {
console.log('loader 네임스페이스 해제');
socket.leave(maker);
});
});
};
서버의 socket.js이다. app.set('io', io)를 통해 라우터에서도 socket.io를 사용할 수 있도록 하였고, loader 네임스페이스를 정의하여 이 네임스페이스 내에서만 통신하도록 하였다. 이때 maker 닉네임에 따라 room들을 따로 분류하여 join 시켰다.
router.post('/:maker/add', async (req, res) => {
// solver 테이블에 등록
const solver = await Solver.findOne({
attributes: ['word_list', 'key_state'],
where: {
nickname: req.session.solver[req.params.maker],
maker: req.params.maker,
}
});
let word_list = JSON.parse(solver.word_list);
let key_state = JSON.parse(solver.key_state);
if ( word_list === null )
word_list = [];
word_list.push(req.body.newWord);
key_state = req.body.keyState;
word_list = JSON.stringify(word_list);
key_state = JSON.stringify(key_state);
await Solver.update({
word_list: word_list,
key_state: key_state,
}, {
where: {
nickname: req.session.solver[req.params.maker],
maker: req.params.maker,
}
});
req.app.get('io').of('/loader').to(req.params.maker).emit('enter', await getSolvers(req.params.maker));
console.log(word_list, key_state);
res.end();
});
POST /solve/:maker/add 요청을 처리하는 라우터이다. 예전이 짜놓은 코드이고, 여기서 추가한 것은 마지막부분에 req.app.get('io')~~ 부분이다. req.app.get('io')는 socket.js에서 등록했던 socket.io를 가져오는 것이고, of('/loader')는 loader 네임스페이스를 의미한다. to(req.params.maker)는 loader 네임스페이스 안에서 maker 닉네임에 따라 분류된 room을 지정해주는 것이고, emit('enter', await getSolvers(req.params.maker))는 enter 이벤트로 solvers 데이터를 보낸다는 의이다.
const connectSocket = ( makerNickname ) => {
const socket = io('http://localhost:4000/loader', {
transports: ['websocket'],
query: {
maker: makerNickname,
}
});
socket.on('enter', function(data) {
console.log(data);
setSolvers(data);
});
return;
};
클라이언트에서 socket.io에 연결하는 함수이다. makerNickname을 쿼리로 보내서 해당 room에 join하도록 하였고, enter 이벤트 리스너를 달아서 solvers를 업데이트할 수 있도록 하였다.
실시간으로 잘 업데이트되고 있다.
시간이 좀 걸렸지만 잘 마무리된 것 같다. 그렇지만 뭔가 찜찜한 기분이 든다. 일단 내일과 모레는 알바를 가야하기 때문에 코딩할 시간이 많지 않은데, 최대한 할 수 있는 데까지 해봐야겠다. 웹소켓을 끝내면 아마 실제 배포를 준비해보고 이번 프로젝트를 마무리지을 것 같은데, 더 보충할 내용이 있는지 훑어봐야겠다.