기존 프로젝트에서 시퀀스를 관리하지 않고 바로 즉각 처리했었으나, 시퀀스를 Map에 저장하고 누락 시 대기열에 해당 패킷을 저장 후 누락된 대기열을 요청하여 받으면 처리되는 방식으로 바꿔보았다.
다만, 클라이언트 코드에는 패킷 재전송 코드가 없기 때문에 실제로는 작동하지 않는다.
저장도 원활히 잘되고 패킷 흐름도 양호한 것을 보아하니 패킷이 누락된 적이 없는 것 같다.
import { PACKET_TYPE_REVERSED } from '../../constants/header.js';
import { getHandlers } from '../../init/loadHandlers.js';
import { GamePacket } from '../../init/loadProto.js';
import { snakeToCamel } from '../formatter/snakeToCamel.js';
// 클라이언트 시퀀스 관리
const clientSequences = new Map();
// 클라이언트 시퀀스 대기열
const clientWaitingQueue = new Map();
export function handleIncomingPacket(socket, packet) {
const currentSequence = packet.sequence;
const lastSequence = clientSequences.get(socket.clientId) || 0;
if (currentSequence === lastSequence + 1) {
clientSequences.set(socket.clientId, currentSequence);
processPacket(socket, packet);
// 대기열에서 연속된 패킷 처리
const queue = clientWaitingQueue.get(socket.clientId) || [];
// 대기열에 넣을 때 정렬하기 때문에 0번 인덱스로 비교.
while (queue.length > 0 && queue[0].sequence === clientSequences.get(socket.clientId) + 1) {
const nextPacket = queue.shift();
clientSequences.set(socket.clientId, nextPacket.sequence);
processPacket(socket, nextPacket.packet);
}
} else if (currentSequence > lastSequence + 1) {
console.warn('패킷 누락');
if (!clientWaitingQueue.has(socket.clientId)) clientWaitingQueue.set(socket.clientId, []);
const queue = clientWaitingQueue.get(socket.clientId);
if (!queue.some((q) => q.sequence === currentSequence)) {
queue.push({ sequence: currentSequence, packet });
queue.sort((a, b) => a.sequence - b.sequence); // 시퀀스 순서대로 정렬
clientWaitingQueue.set(socket.clientId, queue);
}
requestMissingPacket(socket.clientId, lastSequence + 1);
} else {
console.log(`패킷 중복`);
}
}
function requestMissingPacket(socket, Sequence) {
console.log('재전송 요청');
// 실제로 클라이언트에 재전송 요청을 보내는 로직을 구현
}
function processPacket(socket, packet) {
const { packetType, payload } = packet;
const payloadName = snakeToCamel(PACKET_TYPE_REVERSED[packetType]);
const handlers = getHandlers();
const handler = handlers[payloadName];
const decodedPayload = { ...GamePacket.decode(payload)[payloadName] };
handler(socket, decodedPayload);
}
\
, /
로 나뉘어 제대로 파싱하지 못하는 점을 파악path.basename
을 활용한 경로에서 바로 파일명 추출 후 확장자만 제거하는 식으로 변경문제 해결 능력 향상: 예상치 못한 오류나 문제에 직면했을 때 포기하지 않고 다양한 접근 방식을 시도하며 해결책을 찾음.
효율적인 도구 활용: 노션, Slack 등 협업 도구를 적극 활용해 의사소통과 업무 흐름을 정리함.
팀워크 강화: 어려운 상황에서도 팀원들과 의견을 나누며 해결 방안을 함께 모색함.
TCP/PROTO 이해도 향상 : 프로젝트 초기에는 관련 지식과 이해도가 부족했으나, 후반부에는 큰 폭으로 향상
지식 및 경험 부족: 프로젝트 초반 TCP와 ProtoBuf에 대한 이해도가 낮아 학습 곡선이 높음
예상보다 느린 진행 속도: 초반 학습과 적응에 시간이 많이 소요되어 일정이 지연
코드 일관성 부족: 팀원 간 코드 스타일과 구조에 일관성이 부족해 코드 통합 시 추가적인 조율이 필요
디버깅 시간 소요: 문제가 생긴 부분을 디버깅하는데에 시간이 많이 소요
문서화 강화: 코드 설명이나 주요 개념에 대한 문서화를 강화하여 팀원 모두가 이해하고 참고
테스트 프로세스 강화: 기능 개발 후 충분한 테스트 시간을 확보해 오류를 미리 발견하고 개선
리팩토링 주기 도입: 코드 작성 이후 일정 시간마다 리팩토링을 진행해 코드 품질 향상
코드 스타일 가이드라인 통일: 코드의 일관성을 위해 팀 내 코드 스타일 가이드를 통일하고 준수
이번 프로젝트에서 팀은 다양한 성과를 거두었습니다. 문제 해결 능력이 향상되어 예상치 못한 문제에도 다양한 접근 방식을 통해 해결책을 찾았으며, 노션과 Slack 같은 도구를 활용해 의사소통과 업무 흐름을 개선했습니다. 프로젝트 후반에는 TCP 및 ProtoBuf 이해도도 크게 향상되었습니다.
하지만 몇 가지 문제점도 있었습니다. 초반 지식 부족으로 인한 학습 곡선이 높았고, 진행 속도가 느려지는 원인이 되었습니다. 코드 일관성 부족과 디버깅 시간 소요도 문제였습니다.
이를 개선하기 위해 앞으로 문서화 강화, 테스트 프로세스 강화, 리팩토링 주기 도입, 코드 스타일 가이드 통일을 시도할 계획입니다. 이를 통해 코드 품질과 프로젝트 효율성을 높이고자 합니다.