작성
·
631
0
1명만 존재하는 채팅방에서 나갔을때 채팅방이 화면에 렌더링 되는 오류입니다.
아래는 몽고디비를 사용했을 때 입니다.
chat 네임스페이스 접속 해제를 한 후 DB 에서 채팅방을 제거했기 때문에 GET "/" 의 response 에는 기존의 채팅방이 포함되어 있지않습니다. (정상)
아래는 SQL 로 전환했을 때입니다.
SQL 을 사용 했을때는 GET "/" 서버 response 가 chat 네임스페이스 접속 해제보다 빠릅니다. 그러므로 아무도 남아있지않은 채팅방이 GET "/" 의 response 에 포함되어 있고 화면에 렌더링 되는 오류가 발생합니다.
또한 여러번 시도하면 스페이스의 접속과 해제순서가 바뀌어 운좋게 오류가 없을 때도 있습니다.
질문
DB 종류 의 차이가 HTTP 요청과 SOCKET 연결/해제 순서를 바꿀 수 있나요?
이를 해결하기 위한 조언을 부탁 드려요
답변 1
0
db 구조 입니다.
//models/chat.js
const Sequelize = require('sequelize');
class Chat extends Sequelize.Model {
static initiate(sequelize) {
Chat.init({
user: {
type: Sequelize.STRING,
allowNull: false,
},
chat: {
type: Sequelize.STRING,
allowNull: true,
},
gif: {
type: Sequelize.STRING,
allowNull: true,
},
}, {
sequelize,
modelName: 'Chat',
tableName: 'chats',
paranoid: false,
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
});
}
static associate(db) {
db.Chat.belongsTo(db.Room);
}
}
module.exports = Chat;
// models/room.js
const Sequelize = require('sequelize');
class Room extends Sequelize.Model {
static initiate(sequelize) {
Room.init({
title: {
type: Sequelize.STRING,
allowNull: false,
},
max: {
type: Sequelize.INTEGER,
allowNull: false,
validate: {
min: 2,
max: 10
}
},
owner: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: 'local',
},
password: {
type: Sequelize.STRING(100),
allowNull: true,
},
}, {
sequelize,
modelName: 'Room',
tableName: 'rooms',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Room.hasMany(db.Chat);
}
};
module.exports = Room;
// models/index.js
const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(
config.database, config.username, config.password, config,
);
db.sequelize = sequelize;
const basename = path.basename(__filename);
fs
.readdirSync(__dirname) // 현재 폴더의 모든 파일을 조회
.filter(file => { // 숨김 파일, index.js, js 확장자가 아닌 파일 필터링
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => { // 해당 파일의 모델 불러와서 init
const model = require(path.join(__dirname, file));
console.log(file, model.name);
db[model.name] = model;
model.initiate(sequelize);
});
Object.keys(db).forEach(modelName => { // associate 호출
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
module.exports = db;
방 제거 요청이 GET / 보다 먼저 나오거나, 아니면 root 네임스페이스에 접속한 이후에 방 제거 요청이 가면 문제가 없는데 하필 그 사이에 나와버리네요. 디비 드라이버에 따른 처리 속도 차이일 수도 있을 것 같습니다.
확실한 방법은 아니긴 한데 socket.emit을 타이머로 1~2초 뒤에 호출하면 문제는 없을 겁니다.