(TIL) 2025-01-23
(TIL) 2025-01-23
Proto3의 oneof
oneof는 하나의 필드만 값을 가질 수 있는 여러 선택지를 정의할 수 있게 해주는 기능이다. 여러 필드를 정의하면서, 해당 필드 중 오직 하나만 값을 가질 수 있게 합니다. 예를 들어, 여러 타입의 데이터를 하나의 메시지 안에 담고 싶은 경우 유용하다.
1
2
3
4
5
6
7
8
9
10
11
12
syntax = "proto3";
message GamePacket {
oneof payload {
// 회원가입 및 로그인
C2SRegisterRequest registerRequest = 1;
S2CRegisterResponse registerResponse = 2;
C2SLoginRequest loginRequest = 3;
S2CLoginResponse loginResponse = 4;
}
}
위 예시에서 GamePacket라는 메시지에는 payload라는 oneof가 포함되어 있다. 이 oneof 안에는 4가지 필드 (registerRequest, registerResponse, loginRequest, loginResponse)가 정의되어 있지만, 하나의 GamePacket 인스턴스에서는 이 4가지 필드 중 하나만 값을 가질 수 있다.
특징
- 하나의 필드만 설정 가능: oneof 내부의 필드들 중 하나만 값을 가질 수 있다. 예를 들어, registerRequest을 설정하면 나머지 필드는 기본값(0, false 등)을 가지게 된다.
- 메모리 절약: 하나의 값만 저장되므로 메모리 사용을 최적화할 수 있다.
- 컴파일러 지원: 프로토콜 컴파일러는 oneof를 처리할 때, 어떤 필드가 설정되었는지를 추적하는 코드를 생성한다. 이를 통해 어떤 필드가 설정되었는지 쉽게 확인할 수 있다.
사용예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const protobuf = require('protobufjs');
// .proto 파일을 로드
protobuf.load("파일명.proto", (err, root) => {
if (err) throw err;
// MyMessage 메시지를 가져오기
const MyMessage = root.lookupType("GamePacket");
// 하나의 필드만 설정하는 예시
// 1. 'name' 설정
let message1 = MyMessage.create({ registerRequest: 5 });
console.log("registerRequest :", message1); // 5
// 4. 'oneof' 필드가 설정되었는지 확인하는 예시
if (message1.hasOwnProperty("registerResponse")) {
console.log("registerResponse :", message1.registerResponse); // 2
}
});
- protobuf.load를 사용하여 .proto 파일을 로드합니다.
- GamePacket 타입을 가져와서, oneof 내에서 필드 중 하나만(registerRequest) 설정하는 메시지를 만든다.
- 각 필드가 설정되었는지 확인하기 위해 hasOwnProperty를 사용하여 해당 필드(registerResponse)가 존재하는지 체크한다.
oneof는 여러 필드를 묶어서 그 중 하나만 값을 가지도록 하는 기능으로, 복잡한 데이터 구조를 간소화하고 메모리 사용을 최적화하는 데 유용하다. 여러 가지 선택지를 하나의 필드로 표현할 때 매우 유용하게 사용된다.
This post is licensed under CC BY 4.0 by the author.