Protobuf 디코더

hex나 base64, 또는 바이너리 파일 그대로의 protobuf 메시지를 .proto 파일 없이 디코딩합니다 — 필드 번호, wire type, 문자열, 중첩된 하위 메시지까지 재귀적으로 확인합니다.

raw wire 포맷을 그대로 읽으므로 .proto가 없어도 됩니다 — 다만 필드 이름·enum 이름·선언된 타입은 wire에 없어 보여 줄 수 없습니다. 필드는 번호로 표시하고, 길이 지정 값은 텍스트, 아니면 하위 메시지, 아니면 바이트로 추정해서 보여 줍니다. 다른 해석도 보기에서 각 값이 될 수 있는 다른 해석을 볼 수 있습니다.

.proto 없이 protobuf 디코딩

protobuf로 인코딩된 메시지를 hex나 base64로 붙여넣거나 파일 열기…로 바이너리 메시지 파일(.pb·.bin) 그대로를 열면 스키마 없이 바이너리 wire 포맷을 바이트 단위로 해석합니다. 각 필드의 번호, wire type(varint, 64비트, length-delimited, 32비트), 값을 복원하고 중첩된 하위 메시지까지 재귀적으로 펼쳐 전체 트리를 보여줍니다. 모든 처리는 브라우저에서 실행되며 페이로드는 업로드되지 않습니다.

wire 포맷 해석 방식

protobuf 바이너리는 필드 번호와 wire type만 저장하고 선언된 타입은 담지 않으므로 length-delimited 바이트는 휴리스틱으로 해석합니다. 출력 가능한 UTF-8은 문자열로, 그렇지 않은 바이트가 하위 메시지로 정상 파싱되면 중첩 메시지로, 나머지는 raw hex로 표시합니다. JavaScript 안전 정수를 넘는 값은 정확한 10진 문자열로 표시합니다. 선언된 타입이 없으니, 다른 해석도 보기를 켜면 각 값이 될 수 있는 다른 해석을 함께 보여 줍니다 — varint는 부호 있는 정수·zigzag 정수·bool로, 고정 길이 바이트는 float·double로, 길이 지정 필드는 packed 숫자 목록으로 읽은 값입니다. varint 목록으로 딱 떨어지는 원시 바이트 필드는 켜지 않아도 목록으로 보여 줍니다.

입력과 출력

기본은 Hex이며, 바이트를 붙여 쓰든 띄어 쓰든, 한 줄에 하나씩 쓰든, 콜론·쉼표·하이픈으로 잇든, C 배열이나 디버거 덤프처럼 바이트마다 0x를 붙이든(0x08, 0x96, 0x01) 그대로 읽습니다. 자동 감지를 고르면 글자를 보고 16진수인지 base64인지(URL-safe나 패딩 없는 base64 포함) 알아낸 뒤 어느 쪽으로 읽었는지 알려 줍니다. 보기에서 트리와 JSON을 바꿀 수 있고, JSON은 JSON 복사와 다운로드가 가져가는 필드 번호 기준 JSON 그대로입니다. 결과 위의 한 줄에는 읽은 바이트 수, 찾은 필드 수(중첩 포함), 디코딩에 걸린 시간이 나옵니다.

자주 묻는 질문

디코딩하려면 .proto 파일이 필요한가요?

아니요. protobuf wire 포맷은 스키마 없이도 필드 번호, wire type, 원시 값을 복원할 수 있을 만큼 자기 서술적입니다. 다만 선언된 필드 이름과 정확한 타입(예: int32와 sint32)은 wire에 저장되지 않아 표시할 수 없지만, 구조와 값은 볼 수 있습니다. 다른 해석도 보기를 켜면 각 값 아래에 가능한 다른 해석(부호 있는 정수, zigzag인 sint32, float 등)이 나오므로 맞는 것을 고르면 됩니다.

gRPC 페이로드가 field number 0 오류로 실패하는 이유는?

gRPC는 각 메시지 앞에 5바이트 프리픽스(압축 플래그 1바이트 + 빅엔디언 길이 4바이트)를 붙입니다. 이 5바이트를 제거하고 나머지를 디코딩하세요.

문자열·바이트·중첩 메시지는 어떻게 구분하나요?

길이 지정 필드는 먼저 유효한 UTF-8이면서 제어 문자가 없는지 봅니다. 그러면 문자열로 보여주므로 한글이 담긴 필드도 글자 그대로 나옵니다. 그렇지 않은 바이트가 protobuf 하위 메시지로 깔끔하게 파싱되면 중첩 메시지로, 둘 다 아니면 원시 16진수로 보여줍니다. 스키마 없이 하는 추론이라 값에 따라 의도와 다르게 분류될 수 있습니다. 텍스트로 보였지만 같은 바이트가 하위 메시지로도 읽히면, 다른 해석도 보기에 그 하위 메시지도 나옵니다.

보이는 숫자가 기대한 값이 아니라면요?

다른 해석도 보기 — 부호 있는 정수·zigzag·float·packed 목록을 켜세요. 그러면 varint는 부호 있는 정수(2의 보수), zigzag인 sint32/sint64, bool로도 읽고, 고정 4바이트는 sfixed32와 float로, 8바이트는 sfixed64와 double로, 길이 지정 필드는 길이가 맞는 경우 varint·zigzag·float·double의 packed 목록으로도 읽습니다. 원래 값과 같아지는 해석은 빼므로, 실제로는 sint32였던 varint 1 아래에는 −1이 나옵니다. varint 목록으로 딱 떨어지는 원시 바이트 필드는 켜지 않아도 packed varint: 1, 2, 3처럼 보여 줍니다.

16진수와 base64를 알아서 구분하고, JSON을 보여 주고, 얼마나 디코딩했는지 알려 주나요?

네. Hex·Base64 옆의 자동 감지는 글자를 먼저 16진수로 읽어 보고, 16진수로 읽히지 않거나 메시지로 디코딩되지 않으면 base64(표준이나 URL-safe, 패딩이 있든 없든)로 읽은 뒤 어느 쪽으로 읽었는지 알려 줍니다. 기본은 여전히 Hex입니다. 보기에서 트리와 JSON을 바꿀 수 있고, JSON은 JSON 복사와 다운로드가 가져가는 필드 번호 기준 JSON 그대로입니다. 그 옆 한 줄에는 읽은 바이트 수, 필드 수와 중첩을 포함한 필드 수, 디코딩에 걸린 시간이 나오며, 타이머가 잴 수 없는 짧은 시간은 소수 대신 1밀리초 미만이라고 적습니다.

바이트마다 0x가 붙은 16진수도 붙여 넣을 수 있나요?

네. Hex로 읽을 때 글 맨 앞이나 바이트 묶음마다 앞에 붙은 0x를 접두사로 받으므로, C 배열이나 디버거 덤프처럼 적힌 0x08 0x96 0x01이나 바이트마다 쉼표가 붙은 것, 한 줄에 한 바이트씩 적은 것도 붙여 넣은 그대로 디코딩됩니다. 16진수부터 시도하는 자동 감지도 마찬가지입니다. 묶음 가운데에 든 0x는 접두사가 아니므로, 10x5는 15로 슬쩍 읽지 않고 16진수가 아니라며 거부합니다.