본문 바로가기

부트캠프

protobufjs 사용법

  1. 프로토콜 버퍼 정의 파일을 작성한다.
//person.proto파일

syntax = "proto3";

//메시지 타입 정의
message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}

//기본형식

(키워드) (이름) {
 타입 변수명 = 값
}
  1. 프로토콜 파일을 로드
import protobuf from 'protobufjs'

protobuf.load("person.proto").then(root=>{
//'person.proto' 파일을 로드한다.

const Person = root.lookupType("Person")
//'Person' 메시지 타입을 'root' 객체에서 찾는다. 이는 person.proto파일에서 정의한 메시지 타입임

const message = Person.create({name:"Hong Doe", id:123, <email:"hong1212@example.com>"});
/* 'Person'메시지 타입을 사용하여 새로운 메시지 객체를 생성하는 부분 ,
 여기서 name,id,email 필드를 설정한다.*/
 
const buffer = Person.encode(massage).finish();
/* 생성된 메시지 객체를 바이너리 형식으로 인코딩하는 부분 , 'finish'메서드는 최종 인코딩된
버퍼를 반환한다.*/

const decodedMessage = Person.decode(buffer);
//인코딩된 버퍼를 다시 메시지 객체로 디코딩하는 부분

console.log("Original message:",message);
//원래 생성된 메시지 객체를 콘솔로 출력

console.log("Encoded buffer:",buffer);
//인코딩된 바이너리 버퍼를 콘솔에 출력
console.log("Decoded message:",decodedMessage);
//디코딩된 메시지 객체를 콘솔에 출력
})

 

 

패킷 구조 설계 

바이트 배열의 구조

프로젝트에서 공통적으로 사용할 패킷의 구조 정의

필드 명 타입 설명 크기

totalLength int 메시지의 전체 길이 4Byte
packetType Int 패킷 타입 1Byte
protobuf protobuf 프로토콜 버퍼 구조체 가변

프로토 버프 구조

  • common 아래의 구조로 클라이언트 요청 → “payload”에 각 핸들러에 맞는 데이터가 들어가게 된다.

필드 명 타입 설명

handlerId uint32 핸들러 ID (4바이트)
userId string 유저 ID (UUID ,16바이트)
clientVersion string 클라이언트 버전(문자열)
sequence uint32 유저의 호출 수 (42억)
payload bytes 실제 데이터
syntax = "proto3";

package common;

//공통 패킷 구조
message Packet{
uint32 handlerId = 1; //핸들러 ID (4byte)
string userId = 2; //유저 ID (UUID)
string clientVersion = 3; //클라이언트 버전(문자열)
uint32 sequence = 4; // 유저의 호출 수 (42억)
bytes payload = 5; // 실제 데이터
}
  • Response 클라이언트 요청에 대해서는 아래의 구조로 반환해주게 된다.

필드 명 타입 설명

handlerId uint32 핸들러 ID
responseCode uint32 응답 코드(성공:0 , 실패:에러 코드)
timestamp int64 메시지 생성 타임스탬프(Unix타임스탬프)
data bytes 실제 응답 데이터 (선택적 필드)
sequence uint32 시퀀스 값
syntax = "proto3";

package response;

//공통 응답 메시지 구조
message Response{
 uint32 handlerId = 1; //핸들러ID
 uint32 responseCode = 2; //응답 코드 (성공:0 , 실패:에러 코드) 
 int64 timestamp = 3; //메시지 생성 타임스탬프(Unix타임스탬프)
 bytes data = 4; //실제 응답 데이터 (선택적 필드)
 uint32 sequence = 5; //시퀀스 값
}

 

  • 프로토버프 로드
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import protobuf from "protobufjs";
import { packetNames } from "../protobuf/packetNames.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
//최상위 경로
const protoDir = path.join(__dirname, "../protobuf");

//이 폴더 내에 있는 모든 proto로 끝나는 확장자를 읽는 함수
const getAllProtoFiles = (dir, fileList = []) => {
  const files = fs.readdirSync(dir);

  files.forEach((file) => {
    const filePath = path.join(dir, file);

    if (fs.statSync(filePath).isDirectory()) {
      getAllProtoFiles(filePath, fileList);
    } else if (path.extname(file) === ".proto") {
      fileList.push(filePath);
    }
  });

  return fileList;
};

const protoFiles = getAllProtoFiles(protoDir);

const protoMessages = {}; //원본

export const loadProtos = async () => {
  try {
    const root = new protobuf.Root(); //protobuf에 내장된 메서드 Root는 새로운 인스턴스를 생성해준다.

    await Promise.all(protoFiles.map((file) => root.load(file)));

    for (const [packageName, types] of Object.entries(packetNames)) {
      console.log(`~ file: loadProtos.js:40 ~ loadProtos ~ packageName:`, packageName);
      protoMessages[packageName] = {};
      for (const [type, typeName] of Object.entries(types)) {
        protoMessages[packageName][type] = root.lookupType(typeName);
      }
    }
    // console.log(protoMessages);
    console.log(`protobuf 파일 로드됨`);
  } catch (err) {
    console.error(`Protobuf 파일 로드 중 에러발생함`, err);
  }
};

//데이터가 변조될 가능성을 최대한 줄이기위해 얕은복사로 복사한 데이터를 가져다 쓸꺼임
export const getProtoMessages = () => {
  console.log(`~ file: loadProtos.js:55 ~ getProtoMessages ~ protoMessages:`, protoMessages);
  return { ...protoMessages }; //원본을 복사한 객체
};

'부트캠프' 카테고리의 다른 글

멀티플레이 게임 파일 구조 이해  (0) 2024.11.05
프로토콜 , 로드밸런싱 , 헬스체크  (1) 2024.10.31
리눅스 기본 명령어 / PM2명령어  (1) 2024.10.24
일단박조KPT  (2) 2024.10.16
IOCP 의 개념  (0) 2024.10.14