Protocol Buffers(Protobuf)는 구조화된 데이터를 위한 바이너리 시리얼라이젤션 포맷으로, Google이 서비스 간의 효율적인 정보 교환을 위해 개발했습니다. 이 포맷은 .proto 파일에서 스키마를 사전에 정의해야 하며, 여러 언어의 코드가 생성됩니다. Google의 공식 문서에 따르면, Protobuf는 JSON보다 3-10배 깁 작은 메시지 크기를 제공합니다. Protobuf는 gRPC, Google Maps 그리고 수춘개의 내부 서비스에서 사용됩니다.
주요 포인트
Protocol Buffers는 Google이 개발한 구조화된 데이터 시리얼라이젤션 메커니즘으로, JSON 및 XML과 유사하지만 근본적인 차이가 있습니다: 데이터가 바이너리 형식으로 인코딩됩니다. 이는 Protobuf 메시지를 으록으로 읽을 수 없지만, 텍스트 기반 형식보다 훨씬 적은 공간을 차지하고 빠르게 처리된다는 뜻입니다.
Protobuf는 서비스 간 데이터 교환의 성능 문제를 해결하기 위해 Google 내부에서 만들어졌습니다. 2008년에 이 기술은 몇목의 언어(C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart 등)를 지원하는 오픈 소스 프로젝트가 되었습니다. 2016년에 출시된 proto3 버전은 구문을 간소화하고 더 많은 언어에 대한 지원을 추가했습니다.
Protobuf와 JSON의 주요 차이점은 데이터 교환이 시작되기 전에 스키마를 정의해야 한다는 점입니다. 스키마 파일(.proto)은 메시지 구조(ud544드, 타입, 고유 ud544드 번호)를 설명합니다. 이 스키마로부터 protoc 컴파일러가 시리얼라이젤션과 디시리얼라이젤션을 위한 대상 언어의 클래스를 생성합니다.
Protobuf 아키텍처는 세 가지 주요 컴포넌트를 포함합니다: 스키마 정의 언어(.proto), protoc 컴파일러, 그리고 특정 언어를 위한 런타임 라이브러리. 개발자는 .proto ud30c일에 데이터 구조를 설명하고, 컴파일을 실행하며, 데이터를 다루기 위한 준비되난 클래스를 받습니다.
Protobuf 메시지의 각 ud544드에는 고유한 번호(ud544드 번호)가 있습니다. 이는 순차적인 번호가 아니라 바이너리 ud615식에서 ud544드를 식별하기 위한 태그입니다. 1부터 15까지의 번호는 1바이트로, 16부터 2047까지는 2바이트로 인코딩됩니다. 따라서 사용 빈도가 높은 중요 ud544드는 ud06c기 최적화를 위해 1부터 15까지의 번호를 부여해야 합니다.
Protobuf는 스컬라(int32, int64, float, double, bool, string, bytes), 열거형(enum), 복합(message) 그리고 특수(oneof, map) 타입같이 다양한 타입을 지원합니다. 각 타입은 해당 사용 사례에 맞게 최적화된 특정 바이너리 표현을 가집니다.
| .proto 타입 | C++ 타입 | Java/Kotlin | 설명 |
|---|---|---|---|
| double | double | double | 64비트 부동 소수점 숫자 |
| float | float | float | 32비트 부동 소수점 숫자 |
| int32 | int32 | int | 32비트, 가변 길이 인코딩 |
| int64 | int64 | long | 64비트, 가변 길이 인코딩 |
| string | string | String | UTF-8 문자열 |
| bytes | string | ByteString | 임의 바이트 |
| bool | bool | boolean | true / false |
Protobuf는 텍스트 기반 ud615식보다 세 가지 주요 장점을 제공합니다: 메시지 크기, 시리얼라이젤션 속도, 그리고 엄격한 타입. 고부하 시스템과 제한된 트래픽을 가진 모바일 애플리케이션에서는 이러한 장점이 중요해집니다.
Protobuf의 바이너리 표현은 숫자에 가변 길이 인코딩(Varint)을 사용합니다: 작은 숫자는 1바이트, 큰 숫자는 최대 10바이트를 차지합니다. 이를 ud1b5해 JSON 또는 XML에서 텍스트 문자열로 수십 바이트를 차지할 식별자, ud50c래그, 카운터를 효율적으로 인코딩할 수 있습니다. 예를 들어, 150이라는 숫자는 Protobuf에서 2바이트, JSON에서 3바이트(“150” 텍스트로), XML에서 3바이트 + 태그를 차지합니다.
추가 장점은 후어 호환성입니다. 스키마에 새로운 ud544드를 추가해도 이전 클라이언트가 깨지지 않습니다: 알 수 없는 ud544드를 단순히 무시합니다. ud544드를 삭제하려면 미래 겹돌을 피하기 위해 해당 번호를 예약하면 됩니다.
.proto 스키마는 특수 언어로 데이터 구조를 설명합니다. ud30c일은 구문(proto3), ud328키지, 그리고 임ud3ec트 종속성을 지정하며 시작됩니다. 각 메시지는 ud544드와 ud568께 키워드 message로 정의되며, 각 ud544드에는 타입, 이름, 고유 번호가 있습니다.
좋은 스키마 실천: 자주 사용되는 ud544드에는 1부터 15까지의 ud544드 번호, 의미 있는 이름, 관련 ud544드를 별도의 message로 그룹화, 여러 옵션 중 하나만 가질 수 있는 ud544드에 oneof 사용.
syntax = "proto3";
package mobileapp;
message User {
string user_id = 1;
string name = 2;
string email = 3;
int32 age = 4;
UserRole role = 5;
repeated string tags = 6;
map<string, string> metadata = 7;
}
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_USER = 1;
USER_ROLE_ADMIN = 2;
USER_ROLE_MODERATOR = 3;
}
메시지는 중첩될 수 있습니다: Profile 타입의 profile ud544드가 내부에 사용자 데이터를 포함합니다. 중첩 지원을 ud1b5해 정의를 중복하지 않고 복잡한 계층 구조를 설명할 수 있습니다.
syntax = "proto3";
package mobileapp;
message Order {
string order_id = 1;
repeated OrderItem items = 2;
double total_price = 3;
PaymentInfo payment = 4;
}
message OrderItem {
string product_id = 1;
string title = 2;
int32 quantity = 3;
double price = 4;
}
message PaymentInfo {
string method = 1;
string transaction_id = 2;
double amount = 3;
}
protoc 컴파일러가 .proto ud30c일을 대상 언어의 소스 코드로 변환합니다. Kotlin/Java에서는 --java_out 파라미터가, Swift에서는 --swift_out(Apple Swift Protobuf ud50c러그인을 ud1b5해), Dart에서는 --dart_out이 사용됩니다. 생성된 클래스는 메시지 구축을 위한 빌더 메소드와 시리얼라이젤션/디시리얼라이젤션 메소드를 포함합니다.
Android에서 Protobuf를 사용하려면 Gradle에서 com.google.protobuf ud50c러그인 버전 0.9+를 사용합니다. ud50c러그인을 추가하고 .proto ud30c일을 지정하면, 빌드가 자동으로 애플리케이션에서 사용할 수 있는 Kotlin 클래스를 생성합니다.
import com.google.protobuf.kotlin.toByteString
import com.example.mobileapp.UserOuterClass.User
fun createUser(): User {
return User.newBuilder()
.setUserId("usr_001")
.setName("IT Sectr")
.setEmail("team@itsectr.com")
.setAge(5)
.setRole(UserOuterClass.UserRole.USER_ROLE_ADMIN)
.addTags("mobile")
.addTags("backend")
.build()
}
fun serializeAndDeserialize(user: User): User {
// 바이너리 형식으로 시리얼라이젤션
val bytes = user.toByteArray()
// 바이너리 형식으로부터 디시리얼라이젤션
return User.parseFrom(bytes)
}
Protobuf는 마이크로서비스 아키텍처와 모바일 애플리케이션에서 특히 효과적입니다. 일반적인 시나리오를 고려해 봅시다: 모바일 애플리케이션이 gRPC를 ud1b5해 서버로부터 제품 목록을 수신합니다. Protobuf 메시지에는 식별자, 이름, 가격, 카테고리를 포함한 제품 정보가 들어 있습니다. 바이너리 ud615식은 JSON과 비교하여 응답 ud06c기를 5-8배 감소시킵니다.
서버 측에서 Protobuf를 사용하는 gRPC 서비스의 예시. 서비스는 GetProducts RPC 메소드를 선언하며, ud398이지네이션 파라미터가 있는 요청을 받아 제품 목록을 반환합니다. Kotlin 구현은 요청과 응답을 처리하기 위해 생성된 클래스를 사용합니다.
import com.example.mobileapp.ProductServiceGrpcKt
import com.example.mobileapp.ProductOuterClass.Product
import com.example.mobileapp.ProductOuterClass.GetProductsRequest
import com.example.mobileapp.ProductOuterClass.GetProductsResponse
class ProductService : ProductServiceGrpcKt.ProductServiceCoroutineImplBase() {
override suspend fun getProducts(
request: GetProductsRequest
): GetProductsResponse {
val products = fetchProductsFromDb(
page = request.page,
limit = request.limit
)
return GetProductsResponse.newBuilder()
.addAllProducts(products)
.setTotalCount(products.size)
.build()
}
}
Android 프로젝트에서 Protobuf 설정은 com.google.protobuf Gradle ud50c러그인을 ud1b5해 수행됩니다. 이 ud50c러그인은 빌드 시에 자동으로 protoc 컴파일러를 실행하고 .proto ud30c일로부터 Kotlin 클래스를 생성합니다. 작동하려면 ud504로젝트 레벨의 build.gradle에 ud50c러그인을 추가하고 애플리케이션 모듈에 적용해야 합니다.
Gradle을 구성한 후, .proto ud30c일은 src/main/proto 디렉토리에 배치됩니다. protoc 컴파일러는 각 빌드 시에 이들을 처리하여 애플리케이션 코드에서 사용할 수 있는 Kotlin 클래스를 생성합니다. 다른 프로젝트 라이브러리와의 종속성 겹돌을 피하기 위해 protobuf와 protoc 버전을 올바르게 지정하는 것이 중요합니다.
iOS 프로젝트의 경우 CocoaPods 또는 Swift Package Manager를 ud1b5해 Protobuf를 연결합니다. Swift Protobuf ud50c러그인은 Codable 프로토콜에 따라 Swift 구조체를 자동 생성합니다. Flutter용 Dart 프로젝트에서는 protobuf ud328키지가 사용되고, 컴파일은 dart run protoc_plugin으로 수행됩니다.
자주 묻는 질문
Protobuf는 필수 스키마가 있는 바이너리 ud615식으로 JSON보다 3-10배 더 압축되었습니다. JSON은 텍스트 기반으로 읽기 쉽고 스키마가 필요없습니다. Protobuf는 더 빠르게 시리얼라이즈하고 디시리얼라이즈하지만 .proto ud30c일의 컴파일이 필요합니다. JSON은 디버그하기 더 쉽고 사전 설정이 필요없습니다.
플랫폼에 맞는 protobuf GitHub 리리스에서 protoc를 다운로드하세요. macOS의 경우 brew install protobuf로 설치하세요. Windows의 경우 zip 아카이브를 다운로드하고 protoc.exe를 PATH에 추가하세요. Android/Kotlin의 경우 com.google.protobuf Gradle ud50c러그인을 사용하며, 빌드 시에 자동으로 컴파일을 실행합니다.
gRPC는 Google의 고성능 RPC ud504레임워크로 Protobuf를 인터 ud398이스 정의 언어(IDL)로 사용합니다. gRPC는 .proto ud30c일에서 서비스와 RPC 메소드를 정의하고, 클라이언트와 서버 코드를 생성하며, 스트리밍과 바이너리 ud504로토콜을 지원합니다.
Google이 공식 지원: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift 그리고 Dart입니다. 커뮤니티가 Rust, TypeScript, Scala, Lua 등의 언어를 지원했습니다. 모바일 개발을 위해 Kotlin/Java(Android) 그리고 Swift/Objective-C(iOS)가 사용 가능합니다.
Protobuf는 다음 규칙을 ud1b5해 후어 호환성을 지원합니다: ud544드 번호를 바꾸지 마세요, ud544드를 삭제하지 마세요(reserved 사용), 새로운 번호로 새로운 ud544드를 추가하세요. 이전 클라이언트는 알 수 없는 ud544드를 무시하고, 새 클라이언트는 누락된 이전 ud544드에 대해 기본값을 받습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.