적용한 것들
- context api를 통한 전역 상태관리
- setState의 비동기성으로 인해 유저 생성 후 소켓 프로그래밍 오류 해결
- 이후에 채팅방에서도 사용할 수 있는 User class를 고려해 상속 사용해보기
Refused to connect to '' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"devContentSecurityPolicy": "default-src * self connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;",
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.js",
"name": "main_window"
}
]
},
"port": "3030"
}
]
]
리빌딩 하면서 음성 채팅 외에 가장 시간을 많이 쏟은 오류 중 하나는 setState함수의 비동기성에서 오는 오류였다. setUser를 통해 유저 클래스의 인스턴스를 생성하면서 소켓 연결이 정의되는데(이전 코드에서는 시간부족으로 그냥 컴포넌트 내에서 소켓을 정의했지만, 일관성이 사라져서 클래스필드에서 정의한 채로 진행해보기로했다.) setUser를 통해 소켓이 정의되어야 소켓 프로그래밍이 되는데, user가 정의되지않아 채팅방 정보를 받아오는게 불가능 했던 것. 보통 이와 관련해서는 useEffect의 의존성 배열에 변수를 추가하는 방법으로 해결하지만, 내 경우에는 잘 되지 않았다.
최종적으로 선택한 방법은 (useEffect의존성 배열) + (if문) 이었다.
lobby.js
var {user, setUser} = useContext(UserDispatch); //유저 전역관리
const [rooms, setRooms] = useState([]); //채팅방 state
useEffect(() => { //컴포넌트 렌더링 시 유저 인스턴스 생성
navigator.mediaDevices.getUserMedia({
audio: { echoCancellation: false },
video: false
}).then((stream)=>{
setUser(new Me(history.state.usr.icon, history.state.usr.nickname, stream))
})
return () => {
if(user){
user.socket.removeAllListeners(); //socketOn 이벤트는 리렌더링할 때마다 수가 늘어남에 따라 재등록을 방지함.
}
};
}, []);
useEffect(() => { //유저 인스턴스 생성 후 채팅방 정보 업데이트
if(user){
user.socket.on('showRoomList', (rooms)=>{
let roomList = [];
console.log(rooms)
for(var i=0; i<rooms.length; ++i){
//if (rooms[i])
if(rooms[i].item.slice(0,4)=="room")
roomList.push({roomname:rooms[i].item, membercount:rooms[i].leng})
}
setRooms(roomList)
})
}
}, [user]);
import {io} from 'socket.io-client'
const ENDPOINT = "localhost:8000";
class User{
host = false;
roomInfo = false;
mediaStream = null;
constructor(userIcon, nickname){
this.userIcon = userIcon;
this.nickname = nickname;
}
}
class Me extends User{
socket = io.connect(ENDPOINT);
constructor(userIcon, nickname){
super(userIcon, nickname);
this.setMedia();
}
joinRoom(roomname){
this.socket.emit('joinRoom',roomname)
this.roomInfo = roomname;
}
setMedia(deviceID){
navigator.mediaDevices.getUserMedia({
audio: { echoCancellation: false, deviceId:{exact: deviceID} },
video: false
}).then((stream)=>{
this.mediaStream = stream
})
}
}
export {User, Me}
완성화면