일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 문자열 대소문자
- babel.config.js
- React
- Next.js
- react native
- 리액트 네이티브
- react native font
- 에러
- aws bucket 정책
- s3 upload
- PongWorld
- GIT
- Project
- react native 세팅
- 리액트
- js
- 리엑트 네이티브 아이콘
- fire base
- error
- firebase 라이브러리
- 백준
- img upload
- AWS
- react native 개발
- react native picker
- react native CLI
- 문자열 대소문자 구별
- Access Key 생성
- AWS Access Key
- 리액트 네이티브 에러
- Today
- Total
밝을희 클태
SPA 게임 개발에서 웹소켓 연결 끊김과 서버 다운 문제 해결: 이벤트 리스너 관리 본문
문제 :
웹소켓 연결이 끊겨 버리고 서버가 터져버림
사실 수집 :
- 게임을 하다가 뒤로 가기 동작을 하면 가끔씩 웹소켓 연결이 끊기고 서버가 터져버리는 현상이 발생
- 서버 로그를 확인해보니 같은 에러 로그가 반복적으로 발생
- 게임 페이지에서 뒤로가기를 통해 다른 페이지로 이동한 후 방향키를 누르면, 이전에 등록된 이벤트 리스너가 계속 실행되는 현상이 발생
원인 추론 :
VanillaJS로 SPA 방식의 게임을 구현했는데, SPA는 페이지가 새로고침되지 않기 때문에, 기존에 등록된 이벤트가 따로 제거되지 않으면 그대로 남아있게 된다. 방향키로 탁구채를 움직이는 동작을 할 때, 이 이벤트 리스너가 실행되면서 서버로 현재 탁구채의 좌표(int 형)를 웹소켓을 통해 보내는데, 여기서 뒤로 가기 동작을 할 경우 게임 페이지가 아닌 다른 페이지에서 방향키 입력이 이루어지면 NaN이 서버로 전송되고, 서버에서 이를 처리하지 않아 서버가 다운되고 웹소켓 연결이 끊어지는 것 같다.
조치 방안 및 구현 :
서버에 물어보니 따로 int형 외에는 처리를 안 했다고 답이 왔다. 그래서 다른 페이지로 이동시 해당 이벤트 리스너를 삭제를 해줘야겠다고 생각했다.
기존에 익명 화살표 함수로 콜백 함수를 전달하던 부분을, 아래와 같이 별도의 함수를 만들어 콜백 함수 인자로 전달하도록 변경했다.
handleKeyDown(e) {
if (e.key === 'ArrowUp') isMovingUp = true;
else if (e.key === 'ArrowDown') isMovingDown = true;
this.animatePaddleMovement();
}
handleKeyUp(e) {
if (e.key === 'ArrowUp') isMovingUp = false;
else if (e.key === 'ArrowDown') isMovingDown = false;
}
addEventListeners() {
document.addEventListener('keyup', this.handleKeyUp);
document.addEventListener('keydown', this.handleKeyDown);
}
페이지 이동 시 등록된 이벤트를 제거할 수 있는 함수를 추가로 구현했다.
cleanUpEvent() {
document.removeEventListener('keyup', this.handleKeyUp);
document.removeEventListener('keydown', this.handleKeyDown);
document.removeEventListener('mousemove', this.handleMouseMove);
}
cleanUp() {
this.cleanUpEvent();
qws.close();
}
그리고 라우팅 로직에 현재 뷰 클래스를 메모리에 저장해 두고, 다른 페이지로 이동할 때 만들어둔 함수를 실행시켜 등록된 이벤트를 제거하도록 했다.
let currentView = null;
export const router = async () => {
...
if (currentView && typeof currentView.cleanUp === 'function') {
console.log('CleanUp Event');
currentView.cleanUp();
}
currentView = view;
...
};
- 문제 발생
CleanUpEvent 함수에서 콜백 함수로 주는 this.Funtion 이 undefined로 나온다.
- 원인
Class의 메서드가 일반 함수로 호출이 돼서 this 전역 객체를 가리키고 있다.
- 해결 방안
- 인스턴스 메서드에 this 를 명시적으로 바인딩해준다.
- 인스턴스 메서드에 명시적으로 바인딩을 해줌으로 어디서 호출이 되든 동일한 인스턴스를 가리킬 수 있다.
constructor(params) { this.handleKeyUp = this.handleKeyUp.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handleMouseMove = this.handleMouseMove.bind(this); }
- 인스턴스 메서드에 명시적으로 바인딩을 해줌으로 어디서 호출이 되든 동일한 인스턴스를 가리킬 수 있다.
결과 :
인스턴스 메서드를 명시적으로 바인딩 해준 결과, 페이지 이동 시 이전의 이벤트들이 제대로 제거되어 예상치 못한 동작을 하지 않게 되었다. 또한, 게임을 하다가 뒤로 가도 서버와 웹소켓 연결이 끊기지 않는 문제가 해결되었다.
이벤트 리스너가 서버와의 상호작용하는 경우, 이러한 문제는 더욱 심각할 수 있으므로, 적절한 이벤트 리스너의 제거 및 관리는 웹의 안전성을 유지하는데 중요하다는 것을 크게 깨달았다.
'PongWorld 프로젝트 > 트러블 슈팅' 카테고리의 다른 글
메세지를 읽지 않았는데 안 읽은 메세지가 안뜬다... (2) | 2024.03.14 |
---|---|
웹소켓 연결 비동기 문제 해결 (0) | 2024.03.10 |