패킷 정의 하나로, 개발부터 라이브까지
이 영상은 게임 클라이언트와 서버가 주고받는 패킷을 Protobuf(.proto) 한 파일로 정의하고, 같은 파일에서 생성한 코드로 봇 클라이언트까지 만드는 흐름을 보여 준다. 봇이 클라·서버와 같은 생성 코드를 쓰기 때문에 패킷 구조가 어긋나지 않고, 그 봇 하나를 서버 컨텐츠 검증과 퍼블리셔의 부하 테스트에 그대로 재사용할 수 있다.
01패킷 정의
클라와 서버가 주고받는 모든 메시지를 .proto 한 파일에 · ▶ 이 장면 보기
왼쪽 에디터에 game_packet.proto 파일이 타이핑된다. syntax = "proto3";, package game; 아래에 LoginReq(account_id, token), EnterDungeonReq(dungeon_id, party_id), SkillUseReq(skill_id, target_id) 세 메시지가 선언된다. 각 필드에는 타입과 번호(= 1, = 2)가 붙는데, 이 번호가 직렬화된 바이트 안에서 필드를 구분하는 태그다.
오른쪽 카드 세 장이 이 파일의 성격을 정리한다.
- message = 패킷 하나: 필드 이름, 타입, 번호(tag)를 선언한다.
- 언어 중립 스키마: C#, C++, Go 등 원하는 언어로 코드를 생성할 수 있다.
- Single Source of Truth: 패킷의 원본은 이 파일 하나뿐이다.
인프라 쪽 감각으로 보면 API 스펙 파일 하나를 두고 모든 소비자가 그 스펙에서 코드를 뽑아 쓰는 구조와 같다.
02코드 생성
protoc 한 번으로 클라 · 서버 · 봇 코드를 동시에 · ▶ 이 장면 보기
.proto 카드에서 출발한 선이 가운데 protoc(codegen) 노드를 거쳐 오른쪽 세 카드로 갈라진다. Client(Unity · C#, GamePacket.cs), Server(C++, game_packet.pb.h), Bot Client(C# .NET, GamePacket.cs)다. 각 카드에는 EnterDungeonReq에 해당하는 생성 코드가 찍힌다. C# 쪽은 DungeonId, PartyId 속성, C++ 쪽은 dungeon_id(), party_id() 접근자다.
봇 카드에는 "클라와 같은 생성 코드를 그대로 사용"이라는 주석과 함께 new EnterDungeonReq { DungeonId = 101, PartyId = party.Id }로 패킷을 만드는 코드가 나온다. 봇도 손으로 바이트를 짜지 않고 클라와 같은 클래스를 쓴다는 뜻이다.
화면 문구는 "protoc 한 번 → 클라 · 서버 · 봇", "같은 .proto에서 생성 → 구조가 그대로 일치"다. 세 코드가 같은 스키마에서 나왔으니 필드 이름, 타입, 번호가 서로 다를 수 없다.
03항상 동기화
봇도 같은 생성 코드를 쓰니까, 패킷이 낡지 않습니다 · ▶ 이 장면 보기
같은 화면에서 .proto의 EnterDungeonReq에 int32 difficulty = 3; 한 줄이 초록색으로 추가되고 버전 칩이 v1.3에서 v1.4로 바뀐다. 펄스가 protoc를 지나 세 카드에 동시에 도착하면 Client에는 Difficulty 속성, Server에는 difficulty() 접근자, 봇에는 같은 Difficulty 속성이 생긴다. 봇 카드의 Difficulty = 3, 줄에는 "시나리오에서 값 지정" 라벨이 붙는다. 재생성은 구조만 만들고, 값을 넣는 시나리오 코드는 사람이 쓰기 때문이다. 세 카드 모두 v1.4와 체크 배지를 단다.
왼쪽 아래에는 비교 대상으로 빨간 점선의 "손으로 짠 봇 패킷" 카드가 나온다. 버전은 v1.3에 머물러 있고 "번호 · 타입 수동 관리 → 어긋나면 서버가 잘못 파싱", "→ 테스트 결과를 믿을 수 없음"이라는 문구와 함께 X 표시가 붙는다.
문구는 "필드를 추가해도 재생성 · 재빌드 한 번이면 끝", "봇 패킷 구조가 클라 · 서버와 자동으로 같이 갱신"이다. 봇 · 클라 · 서버를 같은 .proto 리비전으로 다시 빌드해야 하므로 보통 CI에서 재생성을 강제한다. 봇을 별도로 손으로 유지하면 스키마가 바뀔 때마다 누군가 따라 고쳐야 하고, 그걸 놓치면 봇이 실제 클라와 다른 패킷을 보내게 된다.
04서버가 먼저
클라 연동 전, 봇이 클라의 패킷 플로우를 그대로 흉내 냅니다 · ▶ 이 장면 보기
앞부분은 주차별 간트 차트다. 서버팀의 "던전 컨텐츠 서버 로직"은 W3에 끝나고, 클라팀은 W7까지 "UI · 연출 · 리소스 작업 중…"이다. NOW 표시가 W3 끝에 오면 남는 빈 구간에 "클라 연동까지 대기…?"가 떴다가 "봇 클라이언트로 바로 컨텐츠 테스트" 막대로 바뀐다. 화면 문구는 "서버는 보통 클라보다 먼저 컨텐츠를 완성합니다.", "기다리지 말고, 봇이 클라 대신 패킷을 보내 검증합니다."다.
뒷부분은 Bot Client와 Game Server 사이의 시퀀스 다이어그램이다. 순서는 다음과 같다.
LoginReq→LoginAckEnterWorldReq→EnterWorldAckEnterDungeonReq→EnterDungeonAckSkillUseReq × N을 연속으로 보내는 버스트- 서버가 보내는
DungeonClearNoti
왼쪽의 Client 카드는 "개발 중…" 상태이고 "실제 클라가 보낼 패킷 순서 그대로 봇이 흉내"라고 적혀 있다. 오른쪽 "클라 없이 검증" 체크리스트에는 로그인 · 월드 입장, 던전 입장 시퀀스, 전투 패킷 반복, 클리어 · 보상 검증이 차례로 체크된다. 서버팀은 클라 완성을 기다리지 않고 실제 클라와 같은 순서의 패킷으로 컨텐츠 로직을 끝까지 돌려 볼 수 있다.
05퍼블리셔에게
같은 봇을 수천 개 띄워 장비 스펙 산정 · 라이브 인프라 테스트 · ▶ 이 장면 보기
서버팀 카드에서 퍼블리셔(QA · 인프라팀) 카드로 "BotClient 패키지"가 넘어간다. 패키지에는 생성된 패킷 코드, 컨텐츠 시나리오, 부하 설정(동접 · RPS)이 들어 있고, 용도는 장비 스펙 산정과 라이브 인프라 테스트다.
이어지는 부하 대시보드에서 동시 접속 봇 수가 0에서 6,000까지 올라간다. 가운데에는 LB, Game Server, DB의 CPU 게이지가 있고, 오른쪽 "CPU 사용률 vs 동시 접속(Game Server · 1대)" 그래프에는 "임계 70%" 선이 그어져 있다. 곡선이 동접 5,000 지점에서 70%에 닿으면 "서버 1대 ≈ 동접 5,000" 마커가 뜬다. 아래 칩에는 RPS, p99 지연, DB QPS가 동접에 따라 함께 오른다.
결과 카드는 두 장이다.
- 장비 스펙 산정: 대당 동접 5,000(CPU 70% 기준), 목표 동접 50,000 → 게임 서버 10대 + 여유분. DB · LB 같은 공유 자원은 따로 측정한다.
- 라이브 인프라 테스트: 실서비스 환경에 같은 봇으로 부하를 넣어 LB · 네트워크 · DB 병목을 오픈 전에 확인한다.
화면 하단에 "수치는 설명을 위한 예시입니다"라고 표기되어 있다. 위 숫자는 모두 예시이며 실제 산정은 각 게임의 측정값으로 해야 한다.
이 영상에 나온 용어는 용어집에 정리했다.