[Project_] RTG - Trouble Shooting 2
Real Time Game - WebSocket 통신 방식을 이용한 게임 만들기 - 2
● 클라이언트에서 얻은 점수를 서버에서 검증하기까지 과정
왜 serverScore가 0이지...?
● Item을 먹으면 item.json에 등록된 효과 및 점수가 증가하거나 발동되도록 구현하던 중에 발생한 에러(?)
- 설계상으로는 클라이언트에서는 올바르게 payload를 통해 정보를 서버에 주고 있었다.
// public/js/ItemController.js
sendEvent(21, payload, (response) => {
if (response.status === 'success') {
console.log('Item validated successfully:', response);
score.updateScore(response.newScore); // 점수 업데이트
} else {
console.error('Failed to validate item:', response.message);
}
});
- Item에 대한 처리를 하기 위해 handlerMappings에도 '21' 항목을 추가했고
디버깅을 통해 payload가 잘 받는지도 확인했다.
// src/handlers/item.handler.js
// 서버 기준 점수 계산
const serverScore = getItem(userId)?.score || 0;
const expectedScore = serverScore + itemInfo.score; // 예상되는 점수
console.log('serverScore : ', serverScore);
console.log('expectedScore : ', expectedScore);
- 또한 item.json을 사용하기 위해 stage.model.js을 정의했던 것 같이 비슷하게 userId를 받아오는
model 또한 구현했다.
// src/models/item.model.js
let userItems = {}; // 간단한 메모리 저장소
export const getItem = (uuid) => {
return userItems[uuid] || null;
};
export const setItem = (uuid, score) => {
if (!userItems[uuid]) {
userItems[uuid] = { score };
} else {
userItems[uuid].score = score;
}
};
- 프로젝트에서는 userId에 대한 정보를 uuid로 변형하여 받아오고 있기 때문에 uuid를 받아오도록 변수 설정
이렇게 점수를 받아오고 이제 디버깅으로 serverScore를 확인해보는데...
// vscode terminal에서 디버깅 했을 때 나왔던 값
userId: 'c1cb690f-32ff-4ce1-b57b-a46a2ce0e824',
clientVersion: '1.0.0',
handlerId: 21,
payload: {
itemId: 1,
currentStageId: 1002,
clientScore: 56.86139999999993,
timestamp: 1734613046250
}
serverScore : 0
expectedScore : 10
- 작성한 코드대로라면 serverScore가 clientScore와 같은 점수가 나왔어야 한다.
- 그럼에도 0이 나와서 이를 해결하기 위해 코드를 다시 읽고 디버깅도 해보았다.
디버깅 결과
● userId는 잘 받아오고 있었고 가장 큰 과정이 빠져있었다.
→ 클라이언트에서 받은 score를 서버에는 업데이트 되고 있지 않았다...
Score에 대한 데이터는 어디서 업데이트 되더라?
// public/js/Score.js
// 일정 점수가 될 때 스테이지가 변경되는 로직
async update(deltaTime) {
if (!this.userId) return; // userId가 없으면 업데이트 중단
// 점수 증가
this.score += deltaTime * 0.001;
});
... // 생략
}
- public 디렉토리에 있는 Score.js에서 업데이트 하고 있다.
- 정작 서버에 점수를 보내서 통신하는 과정이 없던 것이었다...
// public/js/Score.js
// 일정 점수가 될 때 스테이지가 변경되는 로직
async update(deltaTime) {
if (!this.userId) return; // userId가 없으면 업데이트 중단
// 점수 증가
this.score += deltaTime * 0.001;
sendEvent(22, { userId: this.userId, clientScore: this.score }, (response) => {
if (response.status === 'success') {
this.score = response.newScore; // 서버에서 반환된 최신 점수로 동기화
} else {
console.error('Failed to update score on server:', response.message);
}
});
... // 생략
}
- handlerMapping을 하나 더 추가해서 증가하는 점수를 서버에서도 처리하는 handler 추가
status : Success!
// vscode terminal에서 출력되는 log
Handler response: {
status: 'success',
message: 'Score updated successfully',
newScore: 46.826199999999936
}
Received data from client: {
userId: 'c1cb690f-32ff-4ce1-b57b-a46a2ce0e824',
clientVersion: '1.0.0',
handlerId: 22,
payload: {
userId: '17a88659-e91d-4e72-b985-194927af81af',
clientScore: 46.86139999999993
}
}
- 클라이언트에서 점수를 보내고 서버에서도 받고 있는 것에 대한 Log이다.
● 모든 검증절차를 마치고 점수도 증가하고 있으면서 아이템을 먹었을 때 받는 Log ▼
Received data from client: {
userId: 'c1cb690f-32ff-4ce1-b57b-a46a2ce0e824',
clientVersion: '1.0.0',
handlerId: 21,
payload: {
itemId: 1,
currentStageId: 1002,
clientScore: 56.86139999999993,
timestamp: 1734613046250
}
}
Received userId from client: c1cb690f-32ff-4ce1-b57b-a46a2ce0e824
validateItemHandler Payload: {
itemId: 1,
currentStageId: 1002,
clientScore: 56.86139999999993,
timestamp: 1734613046250
}
stageInfo : { id: 1002, unlockedItems: [ 1, 2, 3 ] }
serverScore : 46.86139999999993
expectedScore : 56.86139999999993
Item validated successfully: {
userId: 'c1cb690f-32ff-4ce1-b57b-a46a2ce0e824',
itemId: 1,
currentStageId: 1002
}
주거니... 받거니!
결론
● 결국은 Socket 통신 방식에 대한 원리를 제대로 이해하지 못해 일어났던 일이었다.
● Score를 처리하는 과정을 작성하면서 Socket 통신에 대해 한 발짝 더 이해가 된 느낌이다.