인프런 커뮤니티 질문&답변
socket.io 에서 sql db 사용
작성
·
715
0
1명만 존재하는 채팅방에서 나갔을때 채팅방이 화면에 렌더링 되는 오류입니다.
아래는 몽고디비를 사용했을 때 입니다.
 chat 네임스페이스 접속 해제를 한 후 DB 에서 채팅방을   제거했기 때문에 GET "/" 의 response 에는 기존의 채팅방이 포함되어 있지않습니다. (정상)
chat 네임스페이스 접속 해제를 한 후 DB 에서 채팅방을   제거했기 때문에 GET "/" 의 response 에는 기존의 채팅방이 포함되어 있지않습니다. (정상)
아래는 SQL 로 전환했을 때입니다.
 SQL 을 사용 했을때는 GET "/"  서버 response 가  chat 네임스페이스 접속 해제보다 빠릅니다.  그러므로 아무도 남아있지않은 채팅방이 GET "/" 의 response 에 포함되어 있고 화면에 렌더링 되는 오류가 발생합니다.
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초 뒤에 호출하면 문제는 없을 겁니다.






