일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- js
- Next.js
- aws bucket 정책
- img upload
- AWS Access Key
- react native 개발
- 리액트 네이티브
- react native 세팅
- s3 upload
- Project
- 에러
- 백준
- error
- react native
- react native picker
- Access Key 생성
- 문자열 대소문자
- 리엑트 네이티브 아이콘
- 문자열 대소문자 구별
- 리액트 네이티브 에러
- AWS
- React
- babel.config.js
- firebase 라이브러리
- react native font
- fire base
- PongWorld
- 리액트
- react native CLI
- GIT
- 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 프로젝트 > 트러블 슈팅' 카테고리의 다른 글
[shadcn / radix-ui] Drawer 위에서 toast 동작이 막힘 (0) | 2025.04.11 |
---|---|
SPA 게임 개발에서 웹소켓 연결 끊김과 서버 다운 문제 해결: 이벤트 리스너 관리 (1) | 2024.03.24 |
메세지를 읽지 않았는데 안 읽은 메세지가 안뜬다... (2) | 2024.03.14 |