xxx.pb.go의 전역 레지스트리 수정하기: 네임스페이스 충돌 방지하기
"go", "protocol-buffers", "protocols"와 관련된 "Why the default implementation of xxx.pb.go use global registry, can I modify it to avoid namesapce conflict?"에 대한 한국어 해설
"xxx.pb.go"의 기본 구현에서 전역 레지스트리를 사용하는 이유는 무엇이며, 네임스페이스 충돌을 방지하기 위해 수정할 수 있을까요?
해설:
Protocol Buffers는 구조화된 데이터를 직렬화하고 역직렬화하는 데 사용되는 효율적이고 확장 가능한 메커니즘입니다. Go 언어에서 Protocol Buffers를 사용하면 ".proto" 파일을 정의하여 데이터 구조를 설명하고, 이를 통해 "protoc" 컴파일러를 사용하여 Go 코드를 자동으로 생성할 수 있습니다.
"xxx.pb.go" 파일은 "protoc" 컴파일러에 의해 생성되는 Go 코드 파일입니다. 이 파일에는 생성된 메시지 유형, 서비스 및 기타 Protocol Buffers 정의에 대한 Go 코드가 포함됩니다.
기본적으로 "xxx.pb.go" 파일은 전역 레지스트리를 사용하여 생성된 메시지 유형을 등록합니다. 이는 모든 생성된 메시지 유형이 하나의 전역 네임스페이스에 존재한다는 것을 의미합니다. 즉, 두 개의 서로 다른 ".proto" 파일에서 동일한 이름의 메시지 유형을 정의하면 네임스페이스 충돌이 발생할 수 있습니다.
네임스페이스 충돌을 방지하기 위해 다음과 같은 방법으로 "xxx.pb.go" 파일의 기본 구현을 수정할 수 있습니다.
- 패키지 이름 사용: 각 ".proto" 파일에 고유한 패키지 이름을 지정하면 생성된 메시지 유형이 서로 다른 네임스페이스에 속하게 됩니다. 예를 들어, "person.proto" 및 "addressbook.proto"라는 두 개의 ".proto" 파일을 사용하는 경우 다음과 같이 패키지 이름을 정의할 수 있습니다.
syntax = "proto3";
package person;
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
syntax = "proto3";
package addressbook;
import "person.proto";
message AddressBook {
repeated Person people = 1;
}
- 임포트 별칭 사용: ".proto" 파일에 임포트 별칭을 사용하면 생성된 메시지 유형을 다른 이름으로 참조할 수 있습니다. 예를 들어, "person.proto" 파일에서 "Person" 메시지 유형을 "pbperson"이라는 별칭으로 임포트할 수 있습니다.
syntax = "proto3";
package person;
import "google/protobuf/empty.proto";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
syntax = "proto3";
package addressbook;
import "person.proto" as pbperson;
message AddressBook {
repeated pbperson.Person people = 1;
}
위의 방법 중 하나를 사용하면 네임스페이스 충돌을 방지하고 Protocol Buffers 코드를 더욱 효과적으로 구성할 수 있습니다.
예제 코드
예제 1: 패키지 이름 사용
이 예제에서는 "person.proto" 및 "addressbook.proto"라는 두 개의 ".proto" 파일을 사용하여 사람 및 주소록 메시지를 정의합니다. 각 파일에 고유한 패키지 이름을 지정하여 네임스페이스 충돌을 방지합니다.
syntax = "proto3";
package person;
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
syntax = "proto3";
package addressbook;
import "person.proto";
message AddressBook {
repeated person.Person people = 1;
}
예제 2: 임포트 별칭 사용
이 예제에서는 "person.proto" 파일에서 "Person" 메시지 유형을 "pbperson"이라는 별칭으로 임포트하여 네임스페이스 충돌을 방지합니다.
syntax = "proto3";
package person;
import "google/protobuf/empty.proto";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
syntax = "proto3";
package addressbook;
import "person.proto" as pbperson;
message AddressBook {
repeated pbperson.Person people = 1;
}
Protocol Buffers에서 네임스페이스 충돌을 방지하는 대체 방법
- 프리픽스 사용: 생성된 메시지 유형 이름 앞에 고유한 프리픽스를 추가하여 네임스페이스를 구분할 수 있습니다. 예를 들어, 모든 메시지 유형 이름 앞에 "myproject_"라는 프리픽스를 추가할 수 있습니다.
syntax = "proto3";
package myproject.person;
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
- 네스트된 메시지 사용: 메시지 유형을 네스트된 메시지로 정의하여 네임스페이스를 구분할 수 있습니다. 예를 들어, "Person" 메시지 유형을 "AddressBook" 메시지 유형의 네스트된 메시지로 정의할 수 있습니다.
syntax = "proto3";
package addressbook;
message AddressBook {
message Person {
string name = 1;
int32 id = 2;
string email = 3;
repeated PhoneNumber phones = 4;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
repeated Person people = 1;
}
- Go의
go.proto
패키지 사용:go.proto
패키지는 Go 언어에서 Protocol Buffers를 사용하기 위한 추가 기능을 제공합니다. 이 패키지에는 네임스페이스 충돌을 방지하는 데 도움이 되는 여러 기능이 포함되어 있습니다. 예를 들어,go.proto
패키지의NewMessage
함수를 사용하여 새 메시지 인스턴스를 만들 때 고유한 네임스페이스를 지정할 수 있습니다.
package main
import (
"fmt"
"github.com/golang/protobuf/ptypes/empty"
"myproject/person" // "myproject"라는 고유한 네임스페이스 지정
)
func main() {
person := &person.Person{
Name: "John Doe",
Id: 12345,
Email: "[email protected]",
}
fmt.Println(person.Name) // "John Doe"
}
go protocol-buffers protocols