inflearn logo
강의

Course

Instructor

socket.io 실행

749

bin

1 asked

0

안녕하세요

채팅을 구현하기위해 socket.io를 썼는데 통신이 안되는 것같습니다 io에 주소를 제대로 넣었고 서버 on 마다 클라이언트에서 emit으로 작성했는데 작동하지 않습니다 이유가 무엇일까요?

 

// server 파일의 코드입니다

 

require('dotenv').config();

const { createApp } = require('./app');
const { appDataSource } = require('./models/index');

const startServer = async () => {
 const app = createApp();
const PORT = process.env.PORT;
 await appDataSource
 .initialize()
 .then(() => {
  const server = app.listen(PORT, () => {
   console.log(`🟢server is listening on ${PORT}🟢`);
    });
const io = require('socket.io')(server, {
cors: {
 origin: true,
 credentials: true,
},
  });
 const { socketMessage } = require('./middlewares/socket.io');
 socketMessage(io);
    })
.catch((err) => {
console.log(`❌Failed server connect❌`);
appDataSource.destroy();
});
};
startServer();

 

// server의 socket 파일의 코드입니다

 

const jwt = require('jsonwebtoken');
const chatDao = require('../models/chatDao');

const { catchAsync } = require('../utils/error');

const socketMessage = (io) => {
io.use((socket, next) => {

    const token = socket.handshake.headers.authorization;

    if (!token) {

      return next(new Error('Authentication error'));

    }

    jwt.verify(token, process.env.SECRET_KEY, async (err, decoded) => {

      if (err) {

        return next(new Error('Authentication error'));

      }
      userId = decoded.userId;

      next();

    });

  });

  io.on('connection', (socket) => {

    console.log('A User Connected.');

    socket.on(

      'create_room',

      catchAsync(async (postId, callback) => {

        const room = await chatDao.createRoom(userId, postId);

        socket.join(room.raw.insertId);

        callback(room.raw.insertId);

      })

    );
 socket.on(

      'enter_room',

      catchAsync(async (roomId, callback) => {

        socket.join(roomId);

        callback(roomId);

      })

    );


    socket.on('new_text', async (content, roomId, callback) => {

      await chatDao.createChat(userId, content, roomId);

      socket.to(roomId).emit('new_text', content);

      callback(content);

    });


    socket.on('disconnect', () => {

      console.log('접속이 해제되었습니다', socket.id);

      clearInterval(socket.interval);

    });


    socket.on('error', (error) => {

      console.error(error);

    });
​

    socket.on('send', (data) => {

      console.log(data);

      socket.emit('reply', {

        data,

      });

    });


    socket.interval = setInterval(() => {

      socket.emit('news', 'Hello Socket.IO');

    }, process.env.SOCKET_INTERVAL || 1000);

  });

};


module.exports = { socketMessage };
​

 

// client 코드입니다

import React, { useState, useContext } from 'react'; import io from 'socket.io-client';
import './chat.css'; import { MenuContext } from '../../components/Nav/MenuProvider'; 

const Token = localStorage.getItem('accessToken');

const socket = io.connect('http://192.168.0.194:4000', { 
withCredentials: true,
extraHeaders: {Authorization: `Bearer ${Token}`
}
appDataSource.destroy();
}),
});

socket.on('connection', () => { console.log('Connected to server'); 
});

const Chat = () => {   const [roomId, setRoomId] = useState([]);

const [searchData, setSearchData] = useContext(MenuContext);

const handleCreateRoom = event => { 
event.preventDefault(); 
socket.emit('create_room', searchData, ({ searchData, roomId }) => { 
console.log(`Joined room ${roomId}`);
setRoomId(roomId);
});
};

const handleJoinRoom = roomId => { socket.emit('enter_room', roomId, roomId => { console.log(`Joined room ${roomId}`);
setRoomId(roomId);

});

};

const handleNewText = content => { socket.emit('new_text', content, roomId, content => { console.log(`Sent message: ${content}`);

});

};

const handleNewText = content => {

socket.emit('new_text', content, roomId, content => {       console.log(`Sent message: ${content}`);

});

};

const onCheckEnter = e => {if (e.key === 'Enter') {

handleNewText();

}

};

return (

<div className="h-screen pt-36">

<button onClick={handleCreateRoom}>테스트</button>

<button onClick={() => handleJoinRoom(roomId)}>테스트2</button>

<input id="input-text" type="text" onKeyDown={onCheckEnter} />

<button onClick={handleCreateRoom}>제출</button>

</div>

);

};

export default Chat; 

react javascript socket socket.io node.js

Answer 1

0

communityai8509

안녕하세요, 인프런 AI 인턴이에요.

코드를 보니 서버와 클라이언트 모두 문제가 없어보입니다. 가능성이 있다면 .env 파일에서 PORT와 SECRET_KEY의 값을 정확하게 설정했는지 확인해보시는 것이 좋을 것 같아요.

그리고 client 코드에서 아래 코드 중 appDataSource.destroy() 코드는 삭제하셔야 합니다. 여기는 server에서 initialize하고 실행하는 부분이기 때문에, client에서는 필요하지 않습니다.

const socket = io.connect(’http://192.168.0.194:4000’, {
withCredentials: true,
extraHeaders: {Authorization: Bearer ${Token}}
// appDataSource.destroy(), // 삭제!
});

일단 처음 추측하는 문제는 서버와 클라이언트 사이에 CORS (Cross-Origin Resource Sharing) 문제가 있을 수 있다는 것입니다. 서버 코드 중, socket.io 서버를 생성할 때 cors 옵션을 사용하고 있지만, client에서는 cors 설정을 하지 않았습니다. 따라서, client 코드에 cors 옵션을 추가하시면 더 매끄러운 연결이 가능할 것 같습니다.

const socket = io.connect(’http://192.168.0.194:4000’, {
withCredentials: true,
extraHeaders: {Authorization: Bearer ${Token}},
cors: {
origin: true,
credentials: true,
},
});

위와 같이 client 코드에 cors 옵션을 추가해보시기 바랍니다. 혹시 해결이 안된다면 error 이벤트를 잡아서 해당 이벤트에서 어떤 에러가 발생하는지 확인해보시는 것도 좋을 것 같습니다.

그리고 서버 실행 후 바로 client에서 접속하시면 제대로 타이밍이 안맞을 수 있어요. 만약 socket.io 서버에 의해 생성된 “connection” 이벤트에 기능을 추가해놓았다면, client에서 connect 이벤트 이후에 실행해야 멀티 사용자 기반 추적이 가능해요. 기존에 emit 함수를 사용하는 connect 이벤트는 보안과 성능 문제 때문에 권장되지 않습니다. connect 이벤트 대신, DOM이 렌더링 된 후 useEffect 함수를 통해 socket 연결 및 데이터 요청을 하시는 것이 좋습니다.

수고하세요!

plan mode를 진행하는것에 있어서

0

5

1

오픈톡 인원이 다 차서 들어가지를 못 하네요...

0

9

1

수강자료 다운로드 관련 문의

0

15

2

클로드 코드 설치 관련

0

11

1

선택정렬 이해하기 & 구현하기

0

8

1

스타터킷 중요도에 대한 질문입니다.

0

13

1

mission12-01 guide.md파일 누락

0

13

1

슬라이드 오타

0

18

0

전체적인 개발에 대해 문의드립니다.

1

33

1

자료집 관련

0

22

2

13. (App 2) 기본기 훈련 에서

0

31

1

챌린지 시작일 문의

0

38

0

2. 어떤 도구를 사용하는 것이 가장 유리할까? 강의 중

0

27

1

줄바꿈 시 \ 필수인가요?

0

43

2

11차시 Antigravity IDE 설치 후

0

30

1

2605 이후 최신 클로드코드 강의 추가 부탁드립니다.

0

41

2

처음 에이전트 설정을 잘못 했을 경우 수정 하는 방법

0

35

1

5,6,7,8 내용이 없어요

0

33

1

커리큘럼 문서 제공받을 수 있을까요?

0

40

1

ThemeProvider를 이용해서 NextThemeProvider를 따로 생성하여 Layout.tsx에 적용하는 이유는 뭘까요?

0

30

1

mission 09-01 을 수행할 수 없어요

0

33

1

outputStyle 설정하는데 어디서 문제일까요?

0

29

3

test.txt파일 삭제시 rm명령어이니 클로드의 질문이 있어야 한다고 하셨는데

0

23

2

검은화면

0

31

3