일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- img upload
- Next.js
- babel.config.js
- React
- error
- s3 upload
- AWS
- react native 세팅
- AWS Access Key
- react native
- 백준
- 리액트 네이티브 에러
- react native 개발
- 리액트 네이티브
- GIT
- firebase 라이브러리
- react native picker
- 에러
- aws bucket 정책
- 리액트
- Access Key 생성
- 문자열 대소문자
- Project
- fire base
- 리엑트 네이티브 아이콘
- js
- react native CLI
- 문자열 대소문자 구별
- react native font
- PongWorld
- Today
- Total
밝을희 클태
웹소켓 연결 비동기 문제 해결 본문
문제 :
전체채팅 페이지에서 한 유저를 골라서 1 : 1 채팅으로 넘어가서 새로고침시 대화방의 내용이 다시 렌더링이 안된다.
다른 페이지에서 웹소켓을 연결을 하고 채팅방 페이지로 오면 문제가 없지만 채팅방 페이지에서 새로고침해서 최초로 웹소켓 연결시 문제가 발생
사실 수집:
문제 재현 과정에서 WebSocket 연결 후 메시지 송수신 과정에서 비동기 처리의 순서 문제를 확인. 새로고침 시 웹소켓 재연결 과정에서 이전 채팅 내용을 fetch하기 전에 웹소켓으로 메시지를 보내려 하였으나, 웹소켓 연결이 완료되지 않은 상태였음.
원인 추론:
await checkConnectionSocket(this.socketEventHendler.bind(this));
const $chatRoom = document.querySelector('.chatRoom');
this.$chatRoom = $chatRoom;
if (this.params.user) {
this.target = Number(this.params.user);
this.sendWebsocket();
}
await checkConnectionSocket()이 완료되기 전에 this.sendWebsocket()가 실행되어, 웹소켓 연결이 완료되기 전에 데이터를 요청하는 로직이 실행됨. 이로 인해 웹소켓 연결 완료 이전에 이전 채팅 내용을 불러오는 과정에 문제가 발생함.
조치 방안 및 구현:
WebSocket 연결이 완료될 때까지 기다린 후, 연결 완료 이후에 필요한 데이터 요청 로직을 실행하도록 Promise와 async/await을 사용해 비동기 처리 순서를 제어. WebSocket의 onopen 이벤트에서 Promise의 resolve()를 호출하여 연결 완료를 알리고, 이후 로직이 실행되도록 수정함.
결과 관찰:
수정 후 새로고침 시에도 이전 채팅 내용이 정상적으로 렌더링되는 것을 확인. 웹소켓 연결 상태를 정확히 관리하며 비동기 처리 순서가 보장되어 문제가 해결됨.
코드:
// WebSocket
import BaseWebSocket from './BaseWebSocket.js';
import {getToken, refreshAccessToken} from '../tokenManager.js';
class ConnectionSocket extends BaseWebSocket {
static instance = null;
constructor() {
super();
this.reconnectTimer = null;
}
async connect(url) {
console.log('Connection WebSocket 연결 시도중');
super.connect(url);
return new Promise(async (resolve, reject) => {
this.ws.onopen = () => {
console.log('Connection WebSocket 연결 성공!');
resolve();
};
this.ws.onclose = () => {
console.log('Connection WebSocket 닫힘');
};
});
}
setEvent(handler) {
if (handler) {
this.ws.onmessage = e => {
handler(JSON.parse(e.data));
};
}
}
static getInstance() {
if (!ConnectionSocket.instance) {
ConnectionSocket.instance = new ConnectionSocket();
}
return ConnectionSocket.instance;
}
}
const cws = ConnectionSocket.getInstance();
export default cws;
// WebSocketManager
import cws from './WebSocket/ConnectionSocket.js';
import {refreshAccessToken, getToken} from './tokenManager.js';
export const checkConnectionSocket = async handler => {
return new Promise(async (resolve, reject) => {
if (!cws.getWS()) {
try {
await connectionSocketConnect(handler);
console.log('connectionSocket 재연결!');
resolve();
} catch (error) {
console.log('checkConnectionSocket Error : ', error);
reject(error);
}
} else resolve();
cws.setEvent(handler);
});
};
export const connectionSocketConnect = async handler => {
if (!getToken().length) await refreshAccessToken();
await cws.connect('ws://127.0.0.1:8000/ws/connection/');
cws.setEvent(handler);
};
connect 함수가 실행되면, WebSocket 클래스 내에서 onopen 이벤트 핸들러에 의해 resolve 함수가 호출될 때까지 실행 흐름은 대기 상태에 들어간다. 이 과정에서 promise 및 async/await 구문을 활용하여 비동기 작업의 완료를 기다리는 방식으로 구현되어 있다. 따라서, connect 함수 및 이와 관련된 상위 함수들은 내부적으로 설정된 비동기 작업이 모두 완료될 때까지 순차적으로 실행이 보류된다. 이러한 구조는 비동기 작업의 동기적 처리를 가능하게 하여, 코드 실행의 순서와 일관성을 보장한다.
'PongWorld 프로젝트 > 트러블 슈팅' 카테고리의 다른 글
SPA 게임 개발에서 웹소켓 연결 끊김과 서버 다운 문제 해결: 이벤트 리스너 관리 (1) | 2024.03.24 |
---|---|
메세지를 읽지 않았는데 안 읽은 메세지가 안뜬다... (2) | 2024.03.14 |