[TIL] 24.11.12 TUE

GDORI·2024년 11월 12일
0

TIL

목록 보기
100/143
post-thumbnail

Sequence 검증 과정 추가

기존 프로젝트에서 시퀀스를 관리하지 않고 바로 즉각 처리했었으나, 시퀀스를 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);
}

프로젝트 종료

Notion Project Design - 팀 회의 후 노션을 이용한 프로젝트 관련 내용 유지

Implementation Image - 타워디펜스 구현 일부

Git Commit Graph - 깃 커밋목록 일부

구현 패킷 흐름도

Trouble shooting 1

EC2 환경에서 loadHandlers() 작동 오류

문제

  • 로컬 환경에서는 loadHandler() 작동에 문제가 없으나, EC2 환경에서 제대로 로드되지 않는 문제가 발생

문제점 식별

  • 윈도우 환경과 리눅스 환경의 path 구분 기준이 \, / 로 나뉘어 제대로 파싱하지 못하는 점을 파악

해결책

  • path.basename을 활용한 경로에서 바로 파일명 추출 후 확장자만 제거하는 식으로 변경

Trouble shooting 2

클라이언트 값 조작 시 무한 타워 구매 현상

문제

  • 값 변조 시 무한 타워설치 가능한 문제

문제점 식별

  • 기존 클라이언트 코드의 경우 서버를 거치지 않고 보유 금액에서 재화 구매 처리 후 x,y 좌표를 서버로 보내 id를 전달받아
    설치하는 방식이라 서버측에서 제어하지 못함.

해결책

  • 클라이언트 측에서 구매처리 하는 것이 아닌, 구매 시 패킷전송으로 서버에서 재화처리 후 id를 부여하는 방식으로 변경
  • 다만, 현재 제공받은 클라이언트를 건들이지 않기로 했기 때문에 오류 처리만 진행

이번 프로젝트의 목표

  • TCP 및 Protocol Buffers 활용 능력 향상 : 최종 프로젝트 이전까지 실전적인 네트워크 프로그래밍 실력을 높이기 위해 TCP와 ProtoBuf의 활용에 집중
  • 이해하기 쉬운 코드 구성 : 모든 팀원이 쉽게 이해하고 유지보수할 수 있는 깔끔하고 명확한 코드 작성이 목표
  • 커밋 및 코드 리뷰 : 빈번한 커밋을 통해 진행 상황을 공유하고, PR 시 팀원들과 모여 코드 리뷰를 수행한 후 dev 병합
  • 안정성과 완성도 : 기본에 충실하여 버그가 없는 안정적이고 완성도 높은 결과물이 목표

KPT

KEEP (잘된 점)

문제 해결 능력 향상: 예상치 못한 오류나 문제에 직면했을 때 포기하지 않고 다양한 접근 방식을 시도하며 해결책을 찾음.
효율적인 도구 활용: 노션, Slack 등 협업 도구를 적극 활용해 의사소통과 업무 흐름을 정리함.
팀워크 강화: 어려운 상황에서도 팀원들과 의견을 나누며 해결 방안을 함께 모색함.
TCP/PROTO 이해도 향상 : 프로젝트 초기에는 관련 지식과 이해도가 부족했으나, 후반부에는 큰 폭으로 향상


PROBLEM (문제점)

지식 및 경험 부족: 프로젝트 초반 TCP와 ProtoBuf에 대한 이해도가 낮아 학습 곡선이 높음
예상보다 느린 진행 속도: 초반 학습과 적응에 시간이 많이 소요되어 일정이 지연
코드 일관성 부족: 팀원 간 코드 스타일과 구조에 일관성이 부족해 코드 통합 시 추가적인 조율이 필요
디버깅 시간 소요: 문제가 생긴 부분을 디버깅하는데에 시간이 많이 소요


TRY (시도할 점)

문서화 강화: 코드 설명이나 주요 개념에 대한 문서화를 강화하여 팀원 모두가 이해하고 참고
테스트 프로세스 강화: 기능 개발 후 충분한 테스트 시간을 확보해 오류를 미리 발견하고 개선
리팩토링 주기 도입: 코드 작성 이후 일정 시간마다 리팩토링을 진행해 코드 품질 향상
코드 스타일 가이드라인 통일: 코드의 일관성을 위해 팀 내 코드 스타일 가이드를 통일하고 준수


회고

이번 프로젝트에서 팀은 다양한 성과를 거두었습니다. 문제 해결 능력이 향상되어 예상치 못한 문제에도 다양한 접근 방식을 통해 해결책을 찾았으며, 노션과 Slack 같은 도구를 활용해 의사소통과 업무 흐름을 개선했습니다. 프로젝트 후반에는 TCP 및 ProtoBuf 이해도도 크게 향상되었습니다.
하지만 몇 가지 문제점도 있었습니다. 초반 지식 부족으로 인한 학습 곡선이 높았고, 진행 속도가 느려지는 원인이 되었습니다. 코드 일관성 부족과 디버깅 시간 소요도 문제였습니다.
이를 개선하기 위해 앞으로 문서화 강화, 테스트 프로세스 강화, 리팩토링 주기 도입, 코드 스타일 가이드 통일을 시도할 계획입니다. 이를 통해 코드 품질과 프로젝트 효율성을 높이고자 합니다.

profile
하루 최소 1시간이라도 공부하자..

0개의 댓글